So i have a ScriptableObject “GameMode” that has a base and it’s child implements some references to other ScriptableObjects “Databases”. Then there is one more SO “SceneSettings” That has a reference to the “GameMode” one. Now if i make that “GameMode” reference (which is of type Base), point to an Instance of the child version (with the databases) then i get this error in my build (not in editor):
A scripted object (script unknown or not yet loaded) has a different serialization layout when loading. (Read 52 bytes but expected 56 bytes)
Did you #ifdef UNITY_EDITOR a section of your serialized properties in any of your scripts?
UnityEngine.Resources:Load(String, Type)
UnityEngine.Resources:Load(String) (at C:\buildslave\unity\build\Runtime\Export\Resources\Resources.bindings.cs:51)
and no i don’t have any properties with #ifdef UNITY_EDITOR
Unity do not support class hierarchies with scriptable objects when you reference them as base types. It either needs an exact type or deserialization will fail.
But there shouldn’t be any deserialization. Didn’t the OP first create every ScriptableObject needed, by clicking the menu? They’re all side-by-side in Assets, which properly saves and loads them all, right? In the problem area, “public GameModeBaseClass g;”, wasn’t that filled in by dragging over another ScriptableObject? That should be no problem.
If you could somehow create a subclassOfGameMode that wasn’t in Assets, and the only way to find it was your “public GameModeBaseClass g;” pointer, meaning it needed to be serialized along with you, then it would be a problem. But is that even possible?
so maybe better to post the relevant code:
GameModeBase:
[CreateAssetMenu(fileName = "GameMode", menuName = "ScriptableObjects/GameModes/New GameModeBase", order = 1)]
public class GameModeBase : ScriptableObject
{
public PlayerController playerControllerPrefab;
public Pawn pawnPrefab;
public HUDBase HUDPrefab;
public PlayerController PlayerController { get { return m_playerController; } }
private PlayerController m_playerController;
}
Child of base:
[CreateAssetMenu(fileName = "GameMode", menuName = "ScriptableObjects/GameModes/New GameModeGame", order = 1)]
public class GameModeGame : GameModeBase
{
[Header("Booking System")]
public BookingsSO bookingsSO;
public GroupsSO groupsSO;
public GuestsSO guestsSO;
public EthnicityDB ethnicityDB;
public ThemeRequirementSO themeRequirementSO;
[Header("Items And Structures")]
public BuildingDB buildingDB;
public PlaceableDB placeableDB;
public PropDB propDB;
public BuildingDB vehicleDB;
[Header("Characters")]
public ToolDataSO toolDataSO;
public ResortManager ResortManager { get; private set; }
public Calendar Calendar { get; private set; }
}
The Scriptable object holding reference to a gamemode as base:
(This gets generated at editor time when you create or save a new scene, It’s saved to the resource folder and gets loaded from there at runtime when we load a scene)
public class SceneSettings : ScriptableObject
{
public Scene scene;
public string scenePath;
public GameModeBase gameMode;
public ShadowmaskMode shadowMaskMode = ShadowmaskMode.DistanceShadowmask;
public ShadowQuality shadows = ShadowQuality.All;
public ShadowResolution shadowResolution = ShadowResolution.High;
public ShadowProjection shadowProjection = ShadowProjection.StableFit;
public float shadowDistance = 150f;
public float shadowNearPlaneOffset = 3f;
public int shadowCascades = 4;
}
It definitely does work with ScriptableObjects, just like it works with components and other UnityEngine.Objects.
This serialization layout error message is caused by other issues, e.g. scripts and assemblies that - for some reason - have not been updated properly, so that the deserialized version doesn’t match the expected layout.
Wait, Resources.Load? I thought people liked ScriptableObject since an Inspector slot can always be used to find them. In this case you’re trying to find the SceneSettings for the current scene. Seems like some master object could have them all as an array: SceneSettings[ ] AllSceneSettings;.
I don’t think Resources.Load is the problem, or a problem. It just seems odd there.
yes, the reason for Resources here was because the scriptable object “SceneSettings” gets auto generated and i wanted to spare extra drag and drop action which maybe get forgotten by designers…
I found that i don’t get the error when i put a base class version off GameModeBase in the gameMode field in SceneSettings:
public GameModeBase gameMode;
so my initial thought was that the extra fields implemented in GameModeGame (child) are causing the extra unexpected size. but then shouldn’t it be more then 4 bytes?
there are 12 references to objects, so on a 64bit machine thats: 768 bit = 96 bytes, is that correct?
in C++ a virtual void adds size to a class, I have 1 virtual void in the class but I’m not sure if its the same in C#?
The serialized size of an object won’t necessarily be the same as its size in RAM when running.
But you’re right, 4 bytes difference sounds far too small to be the difference between a GameModeBase and a GameModeGame. I would guess it’s not the GameModeGame object itself that’s having trouble, but some other object that is being accessed indirectly, such as one of the many other classes that it includes references to. (Which means you actually need to scrutinize the source code for all of those sub-objects, too, not just the GameModeGame itself.)
Wild speculation:
When you make a build, Unity tries to automatically exclude assets that it doesn’t think are being used in your build (for efficiency), except for scripts and anything inside a Resources folder.
Instances of ScriptableObjects are assets.
Is there any possibility that some scriptable object you are referencing (directly or indirectly) is being excluded from the build because of Unity not being able to figure out that it’s being used? Your SceneSettings asset is presumably in Resources, but are ALL related scriptable objects also in Resources? (One would think that being referenced from something inside a Resources folder ought to be enough to keep it in the build, but I’ve never tested that.)
Thanks for the suggestions! Will try it with putting all SO’s in resources, just to be sure.
But my guess is its ok, since if i drag in base instead of child, i don’t get the erorr…