Hi fellow game developers, I'm working on a Unity project that allows level designer to edit instructions to scene elements of how they should act to events.
screenshot of command editor in unity inspector
I've managed to express all executable instruction units--expressions, statements, control blocks--with a common abstract base class Command
. It comes like this:
[Serializable]
abstract class Command {
public abstract object Execute();
public abstract void Inspect(/* ... */);
}
class CommandCarrier : MonoBehaviour {
public Command command;
}
/*
There are several carrier classes in the real project,
this one is only for illustrating the problem.
Command.Inspect() would be called by a CustomEditor of CommandCarrier.
*/
Where Execute()
is to perform the command at runtime, and Inspect()
is to draw the inspector GUIs.
Every solid type of command would be a derived class of Command
, e.g. an if-else block would be like:
[Serializable]
class Conditional : Command {
public Command condition, trueBranch, falseBranch;
public override object Execute() {
if((bool)condition.Execute()) trueBranch.Execute();
else falseBranch.Execute();
return null;
}
public override void Inspect(/* ... */) { /* ... */ }
}
A constant expression would contain no sub-commands:
[Serializable]
class Constant<T> : Command {
public T value = default(T);
public override object Execute() => value;
public override void Inspect(/* ... */) { /* ... */ }
}
Here comes the problem: all the commands I've written in the inspector panel would be lost as long as a reserialization is triggered (like when the code changed and therefore is recompiled). This is probably because Unity failed to serialize a subclass instance stored in a field of base class; all the type information and the contained data are lost during reserialization. What's worse is that these polymorphical instances are even nested.
I've tried to solve the case and failed: given a field of base class, it's apparently impossible to "upgrade" an instance to a subclass by calling whatever methods belonging to that instance; it must be done externally by assigning the field with a subclass instance created elsewhere. But again, every subclasses have their own fields, and these data I haven't figure out where to recover from.
Could anybody help?