Search Unity

Custom Build Pipeline Error - Extra field Can not be serialized

Discussion in 'Scripting' started by BinaryCats, Oct 29, 2018.

  1. BinaryCats

    BinaryCats

    Joined:
    Feb 8, 2016
    Posts:
    317
    Hello,

    I have a custom build pipeline, which is triggered via script not the build window.

    I have a class similar to this

    Code (CSharp):
    1. public class SomePlatformBehaviour : MonoBehaviour
    2. {
    3. #if USE_PLATFORM
    4. public PlatformSpecificClass myvar;
    5. //…. other code for "Platform"
    6. #endif
    7. }
    In my Build Pipeline, before the build I enable the compiler Flag
    USE_PLATFORM
    , Then perform the build, so something like this:
    Code (CSharp):
    1.  
    2. PlayerSettings.SetScriptingDefineSymbolsForGroup(group, "USE_PLATFORM");
    3. AssetDatabase.Refresh();
    4. result = BuildPipeline.BuildPlayer(ScenePaths, OutputPath, Target, MyOptions | BuildOptions.ShowBuiltPlayer ); //do the build
    However I get the following error
    SomePlatformBehaviour' has an extra field myvar of type 'PlatformSpecificClass' in the player and thus can't be serialized


    I thought I resolved this error in the past by adding the
    AssetDatabase.Refresh();
    however evidentially it did not resolve this issue.

    Does anybody have any ideas how I can resolve this issue?

    Thanks in advance
     
  2. MSplitz-PsychoK

    MSplitz-PsychoK

    Joined:
    May 16, 2015
    Posts:
    1,278
    You cannot change what data gets serialized in a class between platforms. Public variables are serialized by default, so you will either need to mark that variable as not serializable "[System.NonSerializable]" or make it available on all platforms.

    If you must set a reference to an instance of the class using the inspector.. maybe you could instead use a public GameObject on all platforms, and use "gameObject.GetComponent<PlatformSpecificClass>()" at runtime on your specific platform.

    Good luck!
     
    BinaryCats likes this.
  3. BinaryCats

    BinaryCats

    Joined:
    Feb 8, 2016
    Posts:
    317
    Hi thank you for the reply.

    unfortunately, this is a plug in to I can not simply mark the fields
    [System.NonSerializable]
    , or force the user to use
    GetComponent


    I would expect the above code to work the same way as
    1. in the player settings, add
      USE_PLATFORM
      to the compiler defines
    2. Make a build
    This works without the error
     
  4. MSplitz-PsychoK

    MSplitz-PsychoK

    Joined:
    May 16, 2015
    Posts:
    1,278
    If you set your serialization mode to "Text Only", you can open your scene file in notepad and see that components attached to GameObjects have a FileID. When you have a class that only exists on a specific platform, the FileID that belongs to that class represents unknown data on all other platforms. When you try to load a scene that has a component or a reference to a component that is excluded because of build flags, Unity will just see an unknown FileID and have no idea what component to load, or how important that component is.

    That's because when you change your build platform manually, the scene, prefab, and asset files get updated to include new FileIDs that match the new platform. If you try to change the platform and build without re-saving the scenes and prefabs, any changes to FileIDs will cause the build to fail.

    The error explains this: "'SomePlatformBehaviour' has an extra field myvar of type 'PlatformSpecificClass' in the player and thus can't be serialized". This is because it expects "SomePlatformBehavior" to serialize with FileIDs for one platform, but instead has data that matches FileIDs of a different platform.

    Maybe there is some way for you to save the scene and update FileIDs via script after you set the build flags but before you build? I do not have experience with building via script.
     
    BinaryCats likes this.
  5. BinaryCats

    BinaryCats

    Joined:
    Feb 8, 2016
    Posts:
    317
    Thank you for this information. The best solution to this is the latter suggestion of updating the fieldID and saving the project via script. I thought
    AssetDatabase.Refresh() 
    would do that but unfortunately not
     
  6. MSplitz-PsychoK

    MSplitz-PsychoK

    Joined:
    May 16, 2015
    Posts:
    1,278
    Try
    AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport)
    ?
     
    BinaryCats likes this.
  7. BinaryCats

    BinaryCats

    Joined:
    Feb 8, 2016
    Posts:
    317