5

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

  • 1 - 预制框在您的项目面板中

  • 2 - 将其拖到场景中

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

需要明确的是,当你这样做时,游戏不是玩,你只是处于普通的编辑器模式。

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

  • 当您在上面执行“1”和“2”时,(再次处于编辑器模式,而不是在游戏期间)

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

  • 所以,简单的例子:无论你把它放在哪里,我们都会将 Z 位置设置为“2”。

简而言之:编辑器代码使得每次将预制件 P 拖到场景中时,它会将位置 z 设置为 2.0。

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

很明显这应该是可能的。

4

3 回答 3

8

您可以添加一个自定义窗口编辑器,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被定义为 anint以使其能够与2. 所以你也可以有初始化逻辑x.isAdded < 1

于 2018-09-06T17:56:14.797 回答
2

你可以这样:

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


分析:

  1. 这确实有效!

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

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

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

在此处输入图像描述

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

好东西

于 2018-09-06T14:26:54.283 回答
-1

Monobehaviours 有一个Reset方法,它只在编辑器模式下被调用,每当你重置或第一次实例化一个对象时。

public class Example : MonoBehaviour
{
    void Reset()
    {
        transform.position =
           new Vector3(transform.position.x, 2.22f, transform.position.z);
        Debug.Log("Hi ...");
    }
}
于 2018-08-29T07:12:02.907 回答