Prefab編集画面でUIを追加した際にRaycastTargetをデフォルトでオフにするScriptを書きました

注意
2020-03-04時点、
Prefab にUIを追加、次の操作で自分自身を再度開く、とするとOnになることを確認しました
やらないとは思いますが念の為。また、改善次第反映します。
追記
数点、拡張性のあるPresetの存在を教えていただきました……!
こちらに参考としてリンクいたします!ScriptでEvemnt以外はオフにしているのを、手動でコンポーネントごとに設定できる感じです!!
私のScriptは、少し書き換えれば、移行してきたプロジェクトの当たり判定を消したりできる、というのはメリットかな、と……!
【Unity】uGUI のオブジェクト作成時に Raycast Target をデフォルトでオフにする方法 - コガネブログ概要 例えば uGUI の Image の Raycast Target をデフォルトでオフにしたい場合は Image コンポーネントの赤枠のアイコンを押して Select Preset ウィンドウで「Save current to...」ボタンを押して New Preset ダイアログで保存するフォルダとファイル名を設定して「保存」を押して Project ビューで作成されたプリセットを選択した状態で Raycast Target をオフにして「Set as Image Default」ボタンを押します これで Image オブジェクトを作成した時も Image コンポーネントを Add C…baba-s.hatenablog.com
Script
// Copyright (c) 2021 Hiroyuki Kako
// This software is released under the MIT License, see LICENSE.
#if UNITY_EDITOR
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.Experimental.SceneManagement;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using static UnityEditor.Experimental.SceneManagement.PrefabStageUtility;
public class RaycastDefaultRemoverInPrefabView : EditorWindow
{
private static List<Graphic> _tempPrefabGraphics = new List<Graphic>();
private static PrefabStage _recentPrefab;
private static GameObject _instance;
private static bool _isActive;
[InitializeOnLoadMethod]
private static void Initialize()
{
EditorApplication.hierarchyChanged += OnHierarchyChanged;
}
[MenuItem("KEditorExtensions/RaycastDefaultRemoverInPrefabView")]
private
static void Open()
{
GetWindow<RaycastDefaultRemoverInPrefabView>("Toggle");
}
private void OnGUI()
{
using (new
GUILayout.HorizontalScope())
{
_isActive = EditorGUILayout.Toggle("Use RaycastDefaultRemoverInPrefabView", _isActive);
}
}
private static void OnHierarchyChanged()
{
if (!_isActive) return;
if (Application.isPlaying) return;
var
tmpCurrentStageId = GetCurrentPrefabStage();
if (tmpCurrentStageId == null) return;
if (_recentPrefab == null ||
_recentPrefab != tmpCurrentStageId || _instance == null)
{
_recentPrefab = tmpCurrentStageId;
_instance =
tmpCurrentStageId.prefabContentsRoot;
Debug.Log("this may new or different from current opened prefab. load next.");
AddGraphicComponent();
return;
}
var currentGraphic = _instance.GetComponentsInChildren<Graphic>();
foreach (var tmp in
currentGraphic)
{
if (_tempPrefabGraphics.Contains(tmp)) continue;
Debug.Log($"{tmp.name} is new Object");
tmp.raycastTarget = tmp.GetComponent<IEventSystemHandler>() != null;
}
AddGraphicComponent();
}
private static void AddGraphicComponent()
{
var tmpList = _instance.GetComponentsInChildren<Graphic>();
_tempPrefabGraphics = new List<
Graphic>();
foreach (var content in tmpList)
{
_tempPrefabGraphics.Add(content);
}
}
}
#endif使い方
RayCastDefaultRemoverInPrefabView.csをプロジェクトに配置!
大体どこでも大丈夫です。
これはなに?
UIを配置するときに、デザイナーさんと分業したりすることもあると思うんですが、RaycastTargetがOnになっているせいでめちゃくちゃに時間溶かしたり、オフにしなきゃって意識することでストレスが溜まったりするので、オフにしたいな、と思って書きました。すでにありそうでしたが、ぐぐラビティたりなかったので見つけられなく、書きました。
ボタンやスライダー等の、イベントがあるものはついたままになります。
参考
【Unity】ボタン以外の UI の raycastTarget をデフォルトで false にするエディタ拡張「GraphicDefaultValueWriter」紹介 - コガネブログはじめに http://dev.twsiyuan.com/2016/07/unity-graphic-raycasttarget-default-value.html 上記のサイト様が公開されている 「GraphicDefaultValueWriter」を Unity プロジェクトに導入すると ボタン以外の UI の raycastTarget をデフォルトで false にすることができます ソースコード(転載) 実行結果 関連記事baba-s.hatenablog.com
Unity5 Graphic raycastTarget default valuesUnity GUI 大量的 UI 物件會使得 Graphic Raycaster 效能低落,因為要判斷該 Canvas 上許多的 Graphic 物件有沒有被 Ray 打到。主要的解決方案是減少判斷的 Graphic 物件。提供解決方案程式碼,自動在 Unity 新增新的 Graphic 後,設定新的 raycastTarget 屬性。dev.twsiyuan.com
流れ
上記サイト様、Scriptを参考したのですが、Prefab Viewに対応してない(と思います。Onのままだったので)みたいだったので、Prefab編集画面のみで動くものを参考にしながら書きました。
仕組み
[InitializeOnLoadMethod]こいつで毎回初期化するんだと思います。
EditorApplication.hierarchyChanged += OnHierarchyChanged;これでイベントを登録する、的な感じです。hierarchyChangedっていう出来事に対して、やってほしい処理を入れてる、くらいの感覚です。
GetCurrentPrefabStage();また、これでPrefabのID的なものが取れるので、これで同一かをチェックします。
foreach (var tmp in currentGraphic)
{
if (_tempPrefabGraphics.Contains(tmp)) continue;
Debug.Log($"{tmp.name} is new Object");
tmp.raycastTarget = tmp.GetComponent<IEventSystemHandler>() != null;
}さっきまで観測していたものを格納していって、更新があった場合、Event系が入っているかどうかでDisableにします。すでに設置してあるものは無視されます。
結果
ストレスめっちゃ減りました。
ただ、明示的にオンにするのを意識しないともちろんあかんです。
また、処理的にも少し軽くなるっぽいです!
更新
2020-03-04 20時
Prefabが相違な際によろしくなさそうなのでLoadしたPrefabが違う可能性がある場合にSKIPするようにしました。