Tri-Inspector
Tri-Inspector copied to clipboard
Serializable structs with explicit layout
Describe the bug Can`t edit area of effects values Expected behavior able to edit area of effect values
Code Sample
[Serializable]
[StructLayout(LayoutKind.Explicit)]
public struct GameplayAction
{
[FieldOffset(0)]
public GameplayActionType Type;
[FieldOffset(4)]
[ShowIf(nameof(Type), GameplayActionType.SpawnProjectile)]
public SpawnProjectileAction SpawnProjectile;
[FieldOffset(4)]
[ShowIf(nameof(Type), GameplayActionType.ApplyEffect)]
public ApplyEffectAction ApplyEffect;
[FieldOffset(4)]
[ShowIf(nameof(Type), GameplayActionType.ApplyAreaOfEffect)]
public AreaOfEffectShape AreaOfEffect;
[FieldOffset(4)]
[ShowIf(nameof(Type), GameplayActionType.SpawnAreaOfEffect)]
public SpawnAreaOfEffectAction SpawnAreaOfEffect;
}
//
Screenshots
Desktop: Windows 11
**Unity version: 2020.3.35f1

Tri Inspector version: 1.1.01
TL;DR: You can easily solve this by adding
[NonSerialized]attribute to all but one field with[FieldOffset(4)]
I know this is a year-old issue, but I just did some digging.
This is actually a Unity behavior due to how Unity Serialization works, and this is also the behavior in vanilla Unity.
Consider the following struct:
[Serializable, StructLayout(LayoutKind.Explicit)]
public struct ExampleStruct
{
[FieldOffset(0)] public ActionEnum Type;
[FieldOffset(4)] public EnumA A;
[FieldOffset(4)] public EnumB B;
}
If you create a serialized object that contains this struct, Unity will save the object as such:
--- !u!114 &2043024539519176523
MonoBehaviour:
StructValue:
Type: 0
A: 0
B: 0
Unity Inspector works by updating the value to a serialized representation then deserialize it to apply to the instance. You can probably see the problem - Unity will apply A, then B. But A and B are the same field!, which means any changes to A will be immediately overwritten by the already serialized B value. This is also why we can still edit B in the Inspector.
Now, despite being able to hide fields that are not relevant using Tri-Inspector, Unity Serialization stands true always. However, we can leverage the [ShowInInspector] feature to make a non-serialized field editor...
This is what I would do:
[Serializable, StructLayout(LayoutKind.Explicit)]
public struct ExampleStruct
{
[FieldOffset(0)] public ActionEnum Type;
[NonSerialized, ShowInInspector, ShowIf(nameof(Type), ActionEnum.TypeA)]
[FieldOffset(4)] public EnumA A;
[NonSerialized, ShowInInspector, ShowIf(nameof(Type), ActionEnum.TypeB)]
[FieldOffset(4)] public EnumB B;
[SerializeField, HideInInspector]
[FieldOffset(4)] private int _internalField;
}
This way, you explicitly tell Unity to only maintain one true value, and only use other fields as an Editor provided by Tri-Inspector:
--- !u!114 &4228018463491459332
MonoBehaviour:
StructValue:
Type: 0
_internalField: 0
I believe this issue can be closed due to not being a bug on the Tri-Inspector side, if it is a bug at all.