我试图在数据结构中保存一些参数化函数,以便在运行时使用。我希望能够在编辑器中输入参数。
我排除了 UnityEvent,因为我不想在编辑器中指定将受到影响的游戏对象。
我来自 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
您在代码中编写的内容和您尝试做的事情彼此之间有点倒退。除非你想要事件,否则你不需要使用委托来矫枉过正它。反射在这里也无关紧要。它有不同的目的。另外,不要将委托与 c# 事件操作和 UnityEvents 混淆。
接口及其实现很好。要调用它们,您只需使用实例和方法调用的基本引用:
IStuffInstantiatedInEditor translateInterface; // default visibility is private
// so make sure to set it explicitly if needed
translateInterface.Call();
分配它的方式与任何其他变量相同,除非它在不同的类中,因此需要是
internal
或 public
.
So类
MyClass1
有这个成员并在myCls
中创建:
myCls.translateInterface = new EditorTranslate();
myCls.translateInterface.trans = Vector3.one;
myCls.translateInterface.Call();
然后你可以为
EditorRotateAround
做同样的事情。
只需记住
ScriptableObjects
和MonoBehaviours
DO NOT使用new ()
.
如果你想获得指向属于其他实例的其他
Call()
函数的指针,那不是最好的方法。只需将对象添加到列表中,然后在每个集合元素上调用Call()
。
还要注意这个场景,虽然它只是一个例子,但您可以只使用一个
abstract
类并向下推动多态性。如果您不想过多地“外部化”代码,多态性是我的选择(但这是个人的选择)。当继承以某种方式或类的某些“方面”发生变化时,无论继承如何,接口都是最好的。
我这样做的方法是使用 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;
}
这将按原样工作,因为 ScriptableObjects 是默认可序列化的