Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/unity3d/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Unity,编辑器时间脚本,在添加到场景事件的游戏对象上_C#_Unity3d_Unity3d Editor - Fatal编程技术网

C# Unity,编辑器时间脚本,在添加到场景事件的游戏对象上

C# Unity,编辑器时间脚本,在添加到场景事件的游戏对象上,c#,unity3d,unity3d-editor,C#,Unity3d,Unity3d Editor,假设你有一个简单的预制件,“盒子”,我们会说它只不过是一个标准的米立方体 1-预制框位于项目面板中 2-将其拖动到场景中 3-显然,它现在也出现在层次面板中,并且可能在Inspector中被选中并显示 要明确的是,当你们这样做的时候,游戏并不是在玩,你们只是在普通的编辑器模式下 是否可以制作一个脚本(“编辑器脚本”),以便 当您执行上面的“1”和“2”时,(同样是在编辑器模式下,而不是在游戏期间) 发生3时,我们可以影响场景中的新框项目 因此,简单的例子是:我们将始终将Z位置设置为“2”,

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

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

  • 2-将其拖动到场景中

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

要明确的是,当你们这样做的时候,游戏并不是在玩,你们只是在普通的编辑器模式下

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

  • 当您执行上面的“1”和“2”时,(同样是在编辑器模式下,而不是在游戏期间)

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

  • 因此,简单的例子是:我们将始终将Z位置设置为“2”,无论您将其放置在何处

简而言之:编辑器代码,以便每次将预制件p拖动到场景时,它都会将位置z设置为2.0。

这在统一中可能吗?我对“编辑脚本”一无所知

很明显,这应该是可能的。

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

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

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
}


分析:

  • 这确实有效

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

  • 例如,这将非常有效:

    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 + "°";
        }
    }
    

    请注意,这是正确的,也就是说,当您实际玩游戏时,它不会“运行”。如果按“播放”,则不会再次设置随机旋转:)


    很棒的东西

    您可以添加一个自定义窗口编辑器,它实现了
    OnHierarchyChange
    来处理层次结构窗口中的所有更改。此脚本必须位于编辑器文件夹内。要使其自动工作,请确保先打开此窗口

    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++;
            }
        }
    }
    

    请注意,
    OnHierarchyChange
    被调用两次(一次是在开始将框拖动到场景上时,一次是在释放鼠标按钮时),因此
    isAdded
    被定义为一个
    int
    ,以启用与
    2
    的比较。因此,当添加
    x.isAdded<1

    Hmm时,也可以使用初始化逻辑-很好,但是。。。。。。。。。这几乎奏效了。不幸的是,将预置添加到场景时,它不会调用脚本。它仅在您将该组件添加到现有游戏对象时调用脚本(或者,显式单击小的“重置”按钮…(因此从手册中…“当用户点击Inspector上下文菜单中的重置按钮或第一次添加该组件时调用重置”。不幸的是,遗憾的是,这与您所说的不同,“…或首先实例化”)哦,好的,那不是你问题的解决方案!我留下这个(错)作为对其他人的警告回答。这不是真的正确,Jin…否则,你必须向我展示你在整个代码中的意思??我不认为这有统一API,但我认为你应该在问题中添加你尝试过的代码。我这么说是因为你之前的三个问题,包括这一个。我已经研究了这个问题,我也很高兴这是可能的,但很复杂。这不仅仅是使用
    Selection.activeGameObject
    和大量代码。您需要一种方法来区分何时将对象实际拖动到层次结构中以及何时在层次结构中重新排列对象。这两种方法都会触发一个回调函数。您还需要实现saving和l加载变量,因为这是一个编辑器插件,它们将在您单击“播放”时重置“导致bugUnity的按钮应为此添加功能。有
    EditorApplication.hierarchyChanged
    ,但在场景中重新排列对象时也会调用它。实际上,这里的
    Selection.activeGameObject
    并不是不相关的,因为当您将对象从“项目”拖动到“层次结构”选项卡时,对象会自动被选中,因此在
    Selection.activeGameObject
    中。它可以与
    编辑器应用程序一起使用。hierarchyChanged
    为什么在场景编辑器中如此重要?这是正确的答案!好极了也许还有另一种方法,但这种方法非常有效。请注意,在执行设置之前,您应该检查
    是否(item.isAdded==1)
    ,或者,它将执行两次(这可能无害,也可能无害)。万岁!派了一个赏金@Fattie感谢您的更正和慷慨的赏金=)注意@Bizhan ikkentim的回答部分有效,我想在某些情况下,这是一个有用的快速解决方案
    public class MyScript : MonoBehaviour {
        public int isAdded { get; set; }
    }