unity3d 防止在编辑器中添加组件

p1iqtdky  于 2023-03-03  发布在  其他
关注(0)|答案(6)|浏览(173)

我正在寻找一种方法来禁止在Unity编辑器中附加MonoBehaviour组件的可能性。所以我不希望我的组件出现在用户可见的任何地方。
原因是我用AddComponent<T>()从脚本中手动添加了这个组件。所以这更多的是一个方便的问题,我只是不想让用户认为他必须手动添加我的组件才能让我的插件工作。(如果他这样做了,那也不会引起任何麻烦。同样,这只是方便)

精密度

我正在写一个库(dll插件),所以我不能使用不同于我的组件命名文件的技巧,但这正是我所寻找的效果。
我也试着简单地把我的类作为内部类,因为这就是它的本质,程序集应该是唯一一个可以访问这个组件的。然而,我担心从MonoBehaviour继承,即使是一个内部类,也会使这个组件在编辑器中可用...
HideInInspector属性似乎在类上不起作用。
我使用RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)从一个静态方法调用AddComponent,因此没有任何其他行为可依赖。
这是一个很大的挑战,如果我们能找到答案,那将是一种奢侈。有什么想法吗?非常感谢

sg3maiej

sg3maiej1#

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

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

你可以很容易地添加这个类:

gameObject.AddComponent<NotAMonoBehaviour.MyMonoBehaviour>()

而且它不会显示在检查器的Add Component列表中。按照建议使用hide标记设置也会阻止它显示在检查器本身中,尽管这不能完全依赖,因为您可以在检查器中打开Debug视图,仍然可以看到隐藏的组件。

yzuktlbb

yzuktlbb2#

因此,我不希望组件出现在用户可见的任何地方。
下面的代码片段应该会在编辑器(检查器和层次结构)中隐藏您的脚本。

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

我正在寻找一种方法来禁止在Unity Editor中附加MonoBehaviour组件的可能性
只要你的脚本继承自MonoBehaviour,你不能阻止人们将它附加到游戏对象。
尽管如此,你也可以让它在他们连接游戏对象的时候,抛出一个错误,然后破坏那个组件。有一个你设置为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>();

他们将得到下面的错误,脚本将销毁自己:

现在,如果你从插件中调用create并调用keepAlive函数,脚本应该保持:

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

这不是一个编辑器脚本,当你点击"播放"按钮时,它就可以工作,但是你可以使用[ExecuteInEditMode]使它在编辑器中执行。

ulydmbyx

ulydmbyx3#

对于我的情况,我使用Monobehavior.reset()方法来防止在编辑器中添加组件。
https://docs.unity3d.com/ScriptReference/MonoBehaviour.Reset.html
当用户点击Inspector上下文菜单中的Reset按钮或第一次添加组件时,会调用Reset。此函数仅在编辑器模式下调用。Reset最常用于在Inspector中给予良好的默认值。

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

toiithl64#

因为您是使用AddComponent添加它的,所以您可能希望删除组件的MonoBehaviour部分。
假设您在Start中有一个创建子组件的主组件:

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(){}
}
esbemjvw

esbemjvw5#

我有一个简单的解决办法,但我不是100%肯定。它是命名您的组件不同的cs文件名。

bvjveswy

bvjveswy6#

只要使类抽象化,就不能添加它。

相关问题