首页 文章

Unity,编辑时脚本,On GameObject添加到场景事件

提问于
浏览
2

假设你有一个简单的预制件,“盒子”,我们会说它只不过是一个标准的米立方体 .

  • 1 - 预制框位于“项目”面板中

  • 2 - 将其拖动到场景中

  • 3 - 显然它现在也出现在Hierarchy面板中,并且可能在Inspector中选择并显示

要清楚,当你这样做时,游戏不会播放,你只能处于普通的编辑模式 .

是否可以制作一个脚本(“编辑器脚本”?),以便,

当你在上面做“1”和“2”时

  • (再次这是在编辑模式下,而不是在游戏中)

  • 当3发生时,我们可以影响场景中的新Box项目

  • 所以,简单的例子:我们总是将Z位置设置为“2”,无论你放在哪里 .

简而言之: Editor code so that every time you drag a prefab P to the scene, it sets the position z to 2.0.

这在Unity中是否可行?我对“编辑器脚本”一无所知 .

这显然应该是可能的 .

3 回答

  • 2

    您可以添加一个自定义窗口编辑器,该编辑器实现 OnHierarchyChange 以处理层次结构窗口中的所有更改 . 此脚本应位于Editor文件夹中 . 要使其自动运行,请确保先打开此窗口 .

    using System.Linq;
    using UnityEditor;
    using UnityEngine;
    
    public class HierarchyMonitorWindow : EditorWindow
    {
        [MenuItem("Window/Hierarchy Monitor")]
        static void CreateWindow()
        {
            EditorWindow.GetWindow<HierarchyMonitorWindow>();
        }
    
        void OnHierarchyChange()
        {
            var addedObjects = Resources.FindObjectsOfTypeAll<MyScript>()
                                        .Where(x => x.isAdded < 2);
    
            foreach (var item in addedObjects)
            {
                //if (item.isAdded == 0) early setup
    
                if (item.isAdded == 1) {
    
                    // do setup here,
                    // will happen just after user releases mouse
                    // will only happen once
                    Vector3 p = transform.position;
                    item.transform.position = new Vector3(p.x, 2f, p.z);
                }
    
                // finish with this:
                item.isAdded++;
            }
        }
    }
    

    我将以下脚本附加到框中:

    public class MyScript : MonoBehaviour {
        public int isAdded { get; set; }
    }
    

    请注意 OnHierarchyChange 被调用两次(一次开始将盒子拖到场景上时,一次释放鼠标按钮时),因此 isAdded 被定义为 int 以启用与 2 的比较 . x.isAdded < 1 所以你也可以有初始化逻辑

  • -1

    你可以这样:

    using UnityEngine;
    #if UNITY_EDITOR
    using UnityEditor;
    #endif
    
    [ExecuteInEditMode]
    public class PrintAwake : MonoBehaviour
    {
        #if UNITY_EDITOR
        void Awake()  .. Start() also works perfectly
        {
            if(!EditorApplication.isPlaying)
                Debug.Log("Editor causes this Awake");
        }
        #endif
    }
    

    https://docs.unity3d.com/ScriptReference/ExecuteInEditMode.html


    分析:

    • 这确实有效!

    • 一个问题!它发生在对象开始存在时,因此,当您将其拖动到场景中时,但在您放开之前 . 所以实际上,如果你特别想以某种方式调整 position (捕捉到网格 - 无论如何),使用这种技术是不可能的!

    因此,例如,这将完美地工作:

    using UnityEngine;
    #if UNITY_EDITOR
    using UnityEditor;
    #endif
    
    [ExecuteInEditMode]
    public class PrintAwake : MonoBehaviour
    {
        #if UNITY_EDITOR
        void Start() {
            if(!EditorApplication.isPlaying) {
                Debug.Log("Editor causes this START!!");
                RandomSpinSetup();
                }
        }
        #endif
        private void RandomSpinSetup() {
            float r = Random.Range(3,8) * 10f;
            transform.eulerAngles = new Vector3(0f, r, 0f);
            name = "Cube: " + r + "°";
        }
    }
    

    enter image description here

    请注意,这可以正常工作,也就是说当您实际玩游戏时它“不会运行” . 如果你点击“播放”它将不会再设置随机旋转:)

    好东西

  • 3

    Monobehaviours有一个Reset方法,只有在重置或首次实例化对象时才会在编辑器模式下调用它 .

    public class Example : MonoBehaviour
    {
        void Reset()
        {
            transform.position =
               new Vector3(transform.position.x, 2.22f, transform.position.z);
            Debug.Log("Hi ...");
        }
    }
    

相关问题