防止在编辑器中添加组件

Prevent component from being added in the Editor

我正在寻找一种方法来禁用在 Unity 编辑器中附加我的 MonoBehaviour 组件的可能性。 所以我不希望我的组件出现在用户可见的任何地方。

原因是我使用 AddComponent<T>() 从脚本手动附加了这个组件。所以这是一个更方便的问题,我只是不想让用户认为他必须手动添加我的组件才能让我的插件工作。 (如果他无论如何都这样做,那不会造成任何麻烦。同样,这只是方便)

精度

我正在编写一个库(dll 插件),所以我不能使用与我的组件不同的文件命名技巧,但这正是我正在寻找的效果。

我还尝试将我的 class 简单地放在内部,因为它确实如此,程序集应该是唯一可以访问该组件的程序集。但是,恐怕即使使用内部 class 从 MonoBehaviour 继承也会使该组件在编辑器中可用...

HideInInspector 属性似乎不适用于 class。

我正在使用 RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad) 从静态方法调用 AddComponent,因此我不会依赖任何其他行为。

相当大的挑战,如果我们找到答案,那就太奢侈了。 任何的想法?非常感谢

由于您是使用 AddComponent 添加它,也许您想删除组件的 MonoBehaviour 部分。

考虑到您有在“开始”中创建子组件的主要组件:

public class TopComp: MonoBehaviour
{
    void Start(){
        this.gameObject.AddComponent<SubComponent>();
    }
}

把它变成:

public class TopComp: MonoBehaviour
{
    private SubComponent sub = null;
    void Start(){
        this.sub = new SubComponent();
    }
}
public class SubComponent{ }

问题是您很可能想使用所有 Unity 回调。将它们添加到 TopComponent 并显式调用 SubComponent。

public class TopComp: MonoBehaviour
{
    private SubComponent sub = null;
    void Start(){
        this.sub = new SubComponent();
    }
    void OnEnable(){ this.sub.OnEnable();} 
    void Update(){ this.Update();}
}
public class SubComponent{
    public void OnEnable(){}
    public void Update(){}
}

So I don't want my component to appear anywhere visible by the user.

下面的代码片段应该在编辑器(检查器和层次结构)中隐藏您的脚本。

this.hideFlags = HideFlags.HideInHierarchy;
this.hideFlags = HideFlags.HideInInspector;

I am looking of a way to disable the possibility of attaching my MonoBehaviour component in the Unity Editor

只要您的脚本继承自 MonoBehaviour,您就不能阻止人们将它附加到游戏对象。

不过,您可以这样做,以便当他们将其附加到他们的 GameObject 时,您会抛出一个错误,然后销毁该组件。将一个变量设置为 true。您可以使用插件中的函数将插件中的此变量设置为 true,这样您的脚本就不会被破坏。

示例代码:

public class MoveTowards : MonoBehaviour
{
    private bool callFromMyPlugin = false;

    //Call from your plugin to not destroy this script
    public void keepAlive()
    {
        callFromMyPlugin = true;
    }

    IEnumerator Start()
    {
        //Hides component from users
        hideFromUser();


        if (!callFromMyPlugin)
        {
            destroyThisComponent();
        }
        yield return null;

    }

    //Hides component in the Hierarchy and Inspector
    void hideFromUser()
    {
        this.hideFlags = HideFlags.HideInHierarchy;
        this.hideFlags = HideFlags.HideInInspector;

    }

    //Destroys this component
    void destroyThisComponent()
    {
        Debug.LogError("You are not allowed to add this component to a GameObject");
        DestroyImmediate(this);
        Debug.LogWarning("This component is now destroyed");
    }
}

当人们这样称呼它时:

GameObject testObj = new GameObject("Test");
MoveTowards script = testObj.AddComponent<MoveTowards>();

他们会得到下面的错误并且脚本会自行销毁:

现在,如果您从插件调用创建它并调用 keepAlive 函数,脚本应该保持:

GameObject testObj = new GameObject("Test");
MoveTowards script = testObj.AddComponent<MoveTowards>();
script.keepAlive();

注:

不是 编辑器脚本,当您单击 "Play" 按钮时它会工作,但您可以使用 [ExecuteInEditMode] 使其在编辑器。

一个非常简单的解决方案是让您的 class 成为某个所有者的内部 class:

class NotAMonoBehaviour {
  class MyMonoBehaviour : MonoBehaviour {
    //etc.
  }
}

您可以很容易地添加 class:

gameObject.AddComponent<NotAMonoBehaviour.MyMonoBehaviour>()

并且它不会出现在检查器的添加组件列表中。按照建议使用隐藏标志进行设置也会阻止它在检查器本身中显示,尽管不能完全依赖它,因为您可以在检查器中打开调试视图并仍然看到隐藏的组件。

对于我的情况,我使用 Monobehaviour.Reset() 方法来防止在编辑器中添加组件。

https://docs.unity3d.com/ScriptReference/MonoBehaviour.Reset.html

Reset is called when the user hits the Reset button in the Inspector's context menu or when adding the component the first time. This function is only called in editor mode. Reset is most commonly used to give good default values in the inspector.

    private void Reset()
    {
        if (this.GetType() == typeof(MyCustomClass))
        {
            DestroyImmediate( this );
        }
    }

我有一个简单的解决方案,但我不是 100% 确定。它以不同于 cs 文件名的方式命名您的组件。