A script behaviour has a different serialization layout...
Problem Summary
When running a development Windows build I'm seeing these errors:
There are 4 serializable classes inside files where the main class does have the #if UNITY_EDITOR platform dep. compilation flags, but they are in this format:
#if UNITY_EDITOR
....editor imports here...
#endif
[Serializable]
public class MySerializedClassOne(){ }
[Serializable]
public class MySerializedClassOne(){ }
#if UNITY_EDITOR
public class MyEditorOnlyClass(){ }
#endif
All threads that my GoogleFu yielded were either super old (2012-2014) with solutions that didn't work, or were simply completely unanswered (all the ones in the past year).
Constraints
I saw in threads about these errors (from 2012) that found marking things as [NonSerialized] fixed the problem. Thing is, these classes hold prefab references and various level design settings for our automated maze generation Editor tools (see this devblog if you're curious about wtf I'm talking about). Point is, these need to be serialized, otherwise they are not useful Editor tools.
Attempted Fixes
I found that I actually could eliminate some of these errors by removing scripts from the Scene that did not need to exist in the runtime version of the game. For example Alan Zucconi's ColorBlindFilter was throwing one of these errors and isn't needed at runtime, so I simply deleted all Components from the Scene and presto that one error went away. So I figured if I did this for every single editor script we'd be gucci. So...I wrote runtime versions of some scripts that were needed at runtime, then I wrote more editor tools to automatically "prepare for publishing" which simply RemoveComponent()'s all the editor scripts that has anything to do with serialization. This eliminates a few more errors, but I still see a cascade of errors that guess SubtileScript and PillarScript "probably" are the cause (neither script have any [Serializable] tags and are marked for editor only with the PDC flags and [ExecuteInEditMode]).
One curious thing I noticed (this might help myself or someone else figure out the cause of the problem) is that Zucconi's script (which threw the same error as our scripts) has no serialization or #if UNITY_EDITOR flags whatsoever - I did add the PDC flag myself though.
I made doubly sure absolutely no [Serializable] tags were inside of an #if UNITY_EDITOR flag across every single one of our scripts (not just the scripts that the console is saying "probably" are the cause).
Moved the 4 serializable classes to a separate file just to make check if the #if UNITY_EDITOR even being in the same file was the issue. No such luck.
Questions
Any ideas on what I can try?
Could this be a Unity bug? In one of the super old 2012 threads this was in fact a bug with how C# development builds were created that Unity later fixed.
These errors don't appear to actually impact the game itself, either in development or non-development builds. Everything works fine and there doesn't appear to be a performance impact, so is it possible we could just ignore these if no solution is found? Or is that a really bad idea?
Answer by Adam-Mechtley · Dec 21, 2016 at 05:57 PM
Your post is pretty long so it's possible I missed something, but I wanted to speak to this point:
I made doubly sure absolutely no [Serializable] tags were inside of an #if UNITY_EDITOR flag across every single one of our scripts
So what matters here is whether there are any serialized fields inside #if UNITY_EDITOR
blocks, not necessarily whether any serializable types are defined inside them. So, for example, this will cause the problem:
using UnityEngine;
public class NewBehaviourScript : MonoBehaviour
{
#if UNITY_EDITOR
public string someStringOnlyUsedAtEditTime;
#endif
}
In this case, someStringOnlyUsedAtEditTime
unfortunately needs to be part of the run-time serialization layout, even if you never use it. The fix is to just remove the #if UNITY_EDITOR
guard for these cases.
Could you explain why someStringOnlyUsedAtEditTime needs to be part of the runtime serialization layout? I'm lost on why that's the case.
I'm pretty sure this is the answer, as I have a shitton of public variables (some hidden with [HideInInspector] some not) inside of #if UNITY_EDITOR flags. But I'm unclear on how/why these variables are being serialized for runtime builds if they are inside the PDC flag.
I don't work on the serialization system so I don't want to speculate too much here on whether it's desirable or why it is done, but it is a problem with the ti$$anonymous$$g of when the assets are serialized. For example, while it might seem intuitive that these fields would be stripped out for assets directly included in your build, when AssetBundles are built from within the editor, UNITY_EDITOR
will always be true. Whether it is intentional, this at least ensures consistent behavior no matter how and when the assets are serialized. That said, it's certainly annoying and it would be nice to get at least some kind of build-time warning about it so it doesn't catch you by surprise. It could be worthwhile to file a bug report.
Yep indeed this did the trick, simply restructuring the PDC flags for all editor tools from the structure in the OP to this:
#if UNITY_EDITOR
....editor imports here...
#endif
[Serializable]
public class $$anonymous$$ySerializedClassOne(){
public float myFloat;
public bool myBool;
#if UNITY_EDITOR
void DoEditorStuff(){
}
#endif
}
Frankly this feels ugly and wrong to have split PDC flags, but I now understand why it's needed. I dunno if this could be considered a bug, to me it seems like a design decision made by Unity that is not well documented.
I an empty/new Unity project (with the Scene saved, added to build settings, Windows x64 development build run) this code doesn't reproduce the issue:
using UnityEngine;
public class $$anonymous$$yTest : $$anonymous$$onoBehaviour {
public string boat;
#if UNITY_EDITOR
public string apple;
#endif
}
And folks in this thread appear to be suggesting OP does what I think you're saying causes these errors, if I understood correctly.
I wouldn't necessarily go by what people in that thread suggest be done. Historically I have encountered this problem on some run-time platforms but not on others with identical code. Whether or not that specific example reproduces the problem for you, I would strongly suggest you move your UNITY_EDITOR
guards so that none of your serialized fields are in them and see if it fixes your problem.
Yes I'm currently in the process of refactoring our editor scripts to do as you suggest (we have a lot of editor tools). Just wanted to check if I was supposed to reproduce the error with that specific example. Perhaps, as you suggested, these errors are only seen with certain behaviors or on certain platforms.
I ripped all those out of my source code and still get the error.
Answer by bengetme · Nov 16, 2017 at 08:23 PM
My own solution to this error was fixing a mismatched class-name / script-name. I had a scriptable object class named State, but I'd named the file AIState. There were five instances of the scriptable object in my project, corresponding to five "serialization layout" error messages that appeared on load in the build (note that the errors only appeared in the build, not in play mode). Renaming my scriptable object class to AIState solved the problem.
Answer by CapeGuyBen · May 10, 2019 at 03:47 PM
You might also find that the class in question in an assembly which isn't present in standalone build for your target platform (ie. test or editor only assemblies). This can be either because it's in an editor folder or, if you're using assembly definition files, that it's in an assembly which has been marked as editor only or as a test assembly. That seems to also lead to this error at runtime.
An error saying the type was missing would be way more helpful than the one saying it's the wrong size. It took me ages to work out what was going on when I hit this!
How did you find the source of your problem? Did you have a tool to scan through your bundle data?
Answer by KoonDuck · Jul 10, 2019 at 09:53 PM
I had a similar problem, due to the fact that the scripts were located in the folder with the Assembly Definition, in which the required target platform was not specified
Answer by BionicWombatGames · Dec 16, 2020 at 09:17 PM
I encountered this error when I was referencing SOs in the inspector. Moving those SOs into resources and switching to Resources.Load() (rather than using the public inspector var) fixed the problem for me.
Your answer
Follow this Question
Related Questions
Array does not serialize properly in a prefab instance for a scene 0 Answers
EditorWindow and serialization of scene objects 0 Answers
UnityEvent with all derived types in listeners serialized in Inspector 0 Answers
Factories, serialization and the editor 0 Answers
OnValidate For Other Components? 0 Answers