Open Lythom opened 3 months ago
Hey, thanks for the great and detailed contribution! I was also experimenting with a similar approach last time I played with unity serialization and editor integration, so something like this is likely the way to go :)
I did not push it (and other features like the subscription tracker) to the repo so far because I've been quite a purist with this one, in a way that I don't want to push non-battle-tested code, and funnily enough, I'm not currently using this library in the project I'm working on so far (although I hopefully will soon), so I have very limited opportunities to battle-test.
Anyway I'll give it another look and thought, when I have some free time again and your example is definitely helpful! Feel free to report your further findings in the meantime ;-)
Logging some experiments for the sake of openness, here's a custom property drawer without Odin (i'm using serializedValue
field name instead of _v
in my current experimentation code):
[CustomPropertyDrawer(typeof(SerializableState<>))]
public class SerializableStateDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
EditorGUI.BeginProperty(position, label, property);
position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);
EditorGUI.PropertyField(position, property.FindPropertyRelative("serializedValue"), GUIContent.none);
EditorGUI.EndProperty();
}
}
This doesn't quite to work with [SerializeReference]
though and needs more investigation. (I have a SerializableReferenceState
which is exactly like SerializableState
, but with the SerializeReference
attribute on the value field).
Hey! I've been trying TinkStateSharp on some projects to replace my home-made observable state solution that requires manual binding so that the bindings are auto-generated. It works mostly great so far; the biggest friction I had was serializing the state and driving it from a Unity MonoBehaviour.
This message is to share what I've come up with, in case it can help :)
I succeeded first by hacking the source code, breaking encapsulation, so injecting serialization code into the base code works but is not a very clean solution. Then I came up with a wrapper that can work as standalone and could be used without modifying the source code. Maybe something like this could be provided with the TinkState-Unity package?
Assets/Scripts/SerializableState.cs:
This wrapper implements the State interface but provides a concrete implementation that Unity can serialize. MessagePack or JSON.NET annotations could be added here as well. I use an alternative version with MessagePack that also works in a .NET Core environment, which is why Unity references are conditioned by macros. I removed MessagePack here to suggest code that doesn't have any hard dependencies, but it's very straightforward to modify.
The wrapper allows the value to be serialized and driven using the Unity inspector, which is very convenient while debugging: because all values are bound, any change in the inspector automatically triggers updates where needed. It can, of course, break the game state or integrity, but that's the point of debugging tools.
Also, because the value is wrapped, the inspector displays a not-so-practical drawer:
A solution is to use a custom value drawer. With the help of Odin Inspector, we can have the following editor code and result: Assets\Editor\Scripts\SerializableStateOdinDrawer.cs:
Additional note: The wrapper doesn't handle custom equality comparers (only the default one can be instantiated by Unity). Because Unity (same for MessagePack and JSON.NET) requires a default constructor to be able to handle serialization, I see two possible solutions (not implemented yet):
I plan to keep using TinkStateSharp in the future. Let me know if this feedback was useful and if you can benefit from further inputs.
Feel free to use the provided code and informations however you like.