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

f:id:Kakovail:20200304182118g:plain

注意
2020-03-04時点、
Prefab にUIを追加、次の操作で自分自身を再度開く、とするとOnになることを確認しました
やらないとは思いますが念の為。また、改善次第反映します。

追記
数点、拡張性のあるPresetの存在を教えていただきました……!
こちらに参考としてリンクいたします!ScriptでEvemnt以外はオフにしているのを、手動でコンポーネントごとに設定できる感じです!!
私のScriptは、少し書き換えれば、移行してきたプロジェクトの当たり判定を消したりできる、というのはメリットかな、と……!

[Unity] Presetでちょっぴり楽するUI組み立て / Assemble the UI using PresetUnity UIエンジニアリング勉強会 https://unity-ui-avengers-outgame.peatix.com/viewspeakerdeck.com

speakerdeck.com

【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

baba-s.hatenablog.com

Script

C#
// 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/RaycastDefaultRemoverInPrefabView.cs at master · vailKAKO/RaycastDefaultRemoverInPrefabViewdisable RaycastTarget default in prefab view. Contribute to vailKAKO/RaycastDefaultRemoverInPrefabView development by creating an account on GitHub.github.com

github.com

使い方

RayCastDefaultRemoverInPrefabView.csをプロジェクトに配置!
大体どこでも大丈夫です。

これはなに?

UIを配置するときに、デザイナーさんと分業したりすることもあると思うんですが、RaycastTargetがOnになっているせいでめちゃくちゃに時間溶かしたり、オフにしなきゃって意識することでストレスが溜まったりするので、オフにしたいな、と思って書きました。すでにありそうでしたが、ぐぐラビティたりなかったので見つけられなく、書きました。
ボタンやスライダー等の、イベントがあるものはついたままになります。

仕組み

C#
 [InitializeOnLoadMethod]

こいつで毎回初期化するんだと思います。

C#
EditorApplication.hierarchyChanged += OnHierarchyChanged;

これでイベントを登録する、的な感じです。hierarchyChangedっていう出来事に対して、やってほしい処理を入れてる、くらいの感覚です。

C#
GetCurrentPrefabStage();

また、これでPrefabのID的なものが取れるので、これで同一かをチェックします。

C#
foreach (var tmp in currentGraphic)
{
    if (_tempPrefabGraphics.Contains(tmp)) continue;
    Debug.Log($"{tmp.name} is new Object");
    tmp.raycastTarget = tmp.GetComponent&lt;IEventSystemHandler&gt;() != null;
}

さっきまで観測していたものを格納していって、更新があった場合、Event系が入っているかどうかでDisableにします。すでに設置してあるものは無視されます。

結果

ストレスめっちゃ減りました。
ただ、明示的にオンにするのを意識しないともちろんあかんです。
また、処理的にも少し軽くなるっぽいです!

更新

2020-03-04 20時
Prefabが相違な際によろしくなさそうなのでLoadしたPrefabが違う可能性がある場合にSKIPするようにしました。

過去のコメント

Kakovail

baba_sさんありがとうございます!!
実は、これを書いた後に他の方にも指摘いただき、完全にリーチできていなかった内容だったので助かります……!
今回の裏のコンテキストとして、既存のやつを全部オフにしたい、という過程もあったので、そちらで載っけたほうが有用だったな、と思いました!
こちら、記事の中に更新で記載させていただきたいです!
問題があったらご一報ください……!

コメント