unity3d 在Unity中查找可序列化函数的正确语法时出现问题

c3frrgcw  于 2023-05-01  发布在  其他
关注(0)|答案(2)|浏览(135)

我试图将一些参数化函数保存在一个数据结构中,以便在运行时使用。我希望能够在编辑器中输入参数。
我排除了UnityEvent,因为我不想在编辑器中指定将受影响的gameobject。
我来自Python,所以我的思想是装饰器,这显然在C#中行不通。我很确定委托,也许反射或动作将发挥作用,但我只是不能数字的语法。

public interface IStuffInstantiatedInEditor {
    public abstract void Call(Transform transfo);
}

[Serializable]
public class EditorTranslate: IStuffInstantiatedInEditor {
    public Vector3 trans;

    public void Call(Transform transfo) {
        transfo.Translate(trans);
    }
}

[Serializable]
public class EditorRotateAround: IStuffInstantiatedInEditor {
    public Vector3 point;
    public float angle;

    public void Call(Transform transfo) {
        transfo.RotateAround(point, Vector3.forward, angle);
    }
    
}

[Serializable]
public delegate void CallWrapper(Transform transfo);

[Serializable]
public class EditorDataStructure {
    public List<CallWrapper> wrappers;
}

缺少的部分是链接CallWrapper wrap1 = EditorTranslate(vecEnteredInEditor).Call

lsmepo6l

lsmepo6l1#

我的方法是使用ScriptableObjects。现在接口将无法实现这一点,因为它们不能被序列化,但您可以使用抽象继承来创建相同的契约。

public abstract class StuffInstantiatedInEditor : ScriptableObject
{
    public abstract void Call(Transform transfo);
}

然后创建此

public class EditorTranslate: IStuffInstantiatedInEditor 
{
   ...
}

等等
然后,您可以为这些子类型提供CreateAssetMenu属性,如下所示

[CreateAssetMenu(menuName = "StuffInstantiatedInEditor/EditorTranslate")]
public class EditorTranslate: StuffInstantiatedInEditor 
{
   ...
}

然后,您可以创建这些示例,这些示例将存在于您的资产文件夹中,并且可以序列化到您需要的任何场景中。
最后,你的收藏可以

[Serializable]
public class EditorDataStructure 
{
    public List<StuffInstantiatedInEditor> wrappers;
}

它将按原样工作,因为ScriptableObject可通过defualt序列化

insrf1ej

insrf1ej2#

你写的代码和你试图做的事情有点倒退。除非您想要事件,否则您不需要使用委托过度使用它。反射在这里也是不相关的。它有不同的目的。另外,不要将委托与c# event-actions和UnityEvents混淆。
接口及其实现都很好。要调用它们,只需使用示例和方法调用的基本引用:

IStuffInstantiatedInEditor translateInterface; // default visibility is private
                                               // so make sure to set it explicitly if needed
translateInterface.Call();

对它赋值的方法与对任何其他变量赋值的方法相同,除非它在不同的类中,因此需要为internalpublic
因此,类MyClass1具有这个成员,并在myCls中创建:

myCls.translateInterface = new EditorTranslate();
myCls.translateInterface.trans = Vector3.one;
myCls.translateInterface.Call();

然后你可以对EditorRotateAround做同样的事情。
请记住,ScriptableObjectsMonoBehaviours不会使用new ()进行示例化。
如果你想得到指向其他示例的Call()函数的指针,那不是最好的方法。只需将对象添加到列表中,并在每个集合元素上调用Call()
还要注意,对于这个场景,虽然它是一个示例,但您可以只使用abstract类并向下推送多态性。如果您不想过多地“外部化”代码,多态性是我的选择(但这是我个人的选择)。当继承以某种方式出现或类的某些“方面”发生变化时,接口是最好的,而不管继承是什么。

相关问题