通过MenuItem在场景中生成GameObject

发布时间 2023-04-09 21:25:15作者: dewxin

MenuItem Attribute允许你在主菜单中添加新的选项。而这个菜单选项来自于一个静态函数。

public class TestMenuItem
{
    // Creates a new menu item 'Examples > Create Prefab' in the main menu.
    [MenuItem("TestMenuItem/Create Prefab")]
    static void CreatePrefab()
    {
        Debug.Log("do something");
    }
}

上面的代码会产生一个如下图所示的菜单。点击这个选项,就会产生日志信息。

我们还可以对这个选项添加热键,比如如果我们希望按下alt+g触发这个函数。那么可以修改注解为"TestMenuItem/Create Prefab &g" 对应关系为 % (ctrl), ^ (ctrl), # (shift), & (alt).

Some special keyboard keys are supported as hotkeys. For example, "#LEFT" would map to Shift-Left. The keys supported like this are: LEFT, RIGHT, UP, DOWN, F1 .. F12, HOME, END, PGUP, PGDN, INS, DEL, TAB, and SPACE.

比如下面的代码,当我们在project面板选中一个prefab,然后按下ctrl+g,就会在场景中实例化一个这样的对象,并且打印日志。

public class Example
{
    [MenuItem("Examples/Instantiate Selected %g")]
    static void InstantiatePrefab()
    {
        /*Selection.activeObject =*/
        PrefabUtility.InstantiatePrefab(Selection.activeObject as GameObject);
        Debug.Log($"InstantiatePrefab {Selection.activeObject.name}");
    }

}

但是当我们对着C#代码按下Ctrl+g的时候,虽然没有在场景中生成什么,但会显示对应的日志,说明也触发了这个函数。这在某些情况下可能不是我们希望的结果,我们可以通过添加一个新的函数来实现拦截对这个函数的调用。

public class Example
{
    [MenuItem("Examples/Instantiate Selected %g")]
    static void InstantiatePrefab()
    {
        /*Selection.activeObject =*/
        PrefabUtility.InstantiatePrefab(Selection.activeObject as GameObject);
        Debug.Log($"InstantiatePrefab {Selection.activeObject.name}");
    }

    [MenuItem("Examples/Instantiate Selected %g", true)]
    static bool ValidateInstantiatePrefab()
    {
        GameObject go = Selection.activeObject as GameObject;
        if (go == null)
        {
            Debug.Log($"Validate false");
            return false;
        }

        return PrefabUtility.IsPartOfPrefabAsset(go);
    }
}

这样我们可以看到日志不再显示 “InstantiatePrefab ”,说明拦截函数中返回false成功拦截对原有函数的调用。