Prefab modification lost in standalone build

Issue #296 resolved
Rain Lai created an issue

I ran into a strange bug where my prefab modification works in Unity Editor, but doesn't in standalone build.

Unity version: 2017.3.1f1

Odin version: 1.0.6.0

OS: macOS

Steps to Reproducing:

  1. Create an empty scene.
  2. Create a script:
    using Sirenix.OdinInspector;
    using UnityEngine;

    public class Test : SerializedMonoBehaviour
    {
        public A a;

        private void Update()
        {
            Debug.Log(a.value);
        }
    }

    public class A
    {
    public bool value;
    }
  1. Make a gameObject and attach the above script
  2. Make the gameObject a prefab
  3. Modify the value of a.value in inspector to true, but don't apply prefab
  4. Save the scene
  5. Build and run

Expected Result: prints "true"

Actual Result: prints "false"

Note: Sometimes it works, but most of the times the modified value just disappears in the build version. Note this only affects standalone build, in Unity editor it works as expected. Also if I use Unity's serialization([System.Serializable]) to serialize class A, it works in both standalone build and editor, so I think the bug is at Odin.

Comments (18)

  1. Rain Lai reporter

    I know your prefab modification specialist is not here right now, but is there a way to work around it? My particular problem is, class A is implementing interface B, and I have a List<B>(). The problem is, even I put [System.Serializable] on A, Odin still draws custom inspector. Is it possible to just use Unity inspector on the elements of a polymorphism list and avoid custom prefab modification?

  2. Bjarke Elias
    • changed status to open

    Also, I've not managed to reproduce it on windows thus far, but I'll give it a go on a MAC later this week.

    But we did fix a number of other bugs regarding prefab modifications. So you might wanna give our beta a go and see if that solves it?

  3. Bjarke Elias

    Just send us an email from our website with your Odin invoice ID, and I'll send it right away. There is a chance it might solve it. but no guarantees ofc. Still trying to build to various platforms to see if I can reproduce it.

  4. Rain Lai reporter

    Ok, email sent. I'll try to make a separate project where one can easily reproduce this bug(at least on my machine) if beta version fails too.

  5. Rain Lai reporter

    It doesn't work either. But this time I pinpointed its behavior. I'll send you an email with my sample project(which includes Odin's code so I guess I can't post here)

  6. Bjarke Elias

    Thanks a lot for the project and the attempts with the new version. I was able to reproduce it now. If I change the scripting backend to Mono 2.0, or .Net 4.5 it fails. But with .Net 2.0 Subset it works: https://jumpshare.com/v/HfjtnLJEca6RFuCUCNol So if you can use that could be a solution for you.

    But I'll take a deeper look at it tomorrow. Thanks again.

  7. Rain Lai reporter

    Thank for your help. Unfortunately I'm using .Net 4.6 API compatibility everywhere. Guess I'll just try to not use polymorphism List in my prefab for now.

  8. epstal

    Hi, we're seeing this exact same issue in standalone builds, with latest Odin release (1.0.6.9), on Unity 2017.3.0f3. And we're using the same scripting backend settings as you're suggesting (.NET 2.0 Subset). It's a pretty big problem for us!

    I have a relatively straightforward repro case, and in setting it up, discovered an interesting wrinkle to the problem. I have a test project I can send you as well if that's easier.

    • Create an empty project and import latest Odin. Ensure Asset Serialization mode is text (for some easy diffs later)
    • Create a SerializedMonoBehavior, which contains a member value of a new TestClass, and mark the member with the System.NonSerialized/OdinSerialize attributes. Put a string value on the TestClass
    • Create a prefab that holds this behavior, and put some value, say "PrefabValue" on the string value
    • Drag an instance of that prefab into a new scene (call it, say, "BrokenScene"), and override that value to something like "SceneOverrideValue". Save the scene, but do NOT hit Play!
    • Create another scene that acts as the startup "bootstrap" scene. This will hold a script/object that will load the "BrokenScene", additively
    • Have some way of displaying the test string value of the prefab instance in the "BrokenScene" (I just used Unity UI in my test project)
    • Create a standalone build that will start with the bootstrap scene, and note that the overridden string value does not deserialize properly (stays with the value defined on the prefab)
    • The interesting bit.. you may want to create a duplicate backup of "BrokenScene". Open up "BrokenScene" in Editor, hit Play. Select the prefab in the scene. Stop Play. Note that Unity marks this scene dirty - something has changed. Save. Create another standalone build, and notice that the value now deserializes as expected! Try a text diff to compare how this new scene serialized vs. the backup "BrokenScene"

    So it appears that actually playing a scene with an overridden value on a prefab instance, then "touching" the prefab instance, will force Odin to serialize the override correctly. Again, this only seems to happen in standalone builds; running from Editor always behaves as expected.

    As I mentioned, I can send you a test project that will load either the broken or working versions of these scenes, and display the overridden values for each scene. You could also do a text diff on the two scenes if you'd like.

  9. Tor Esa Vestergaard

    ... huh. Thank you for the detailed reproduction steps, I will be giving that a shot right away.

  10. Tor Esa Vestergaard

    And you are of course also more than welcome to send the test project to tor@sirenix.net

  11. Tor Esa Vestergaard

    I can report that this replicates for me - I'm looking into what's going on. Thanks, this will be a huge help in figuring it out!

  12. Tor Esa Vestergaard

    Turns out there were two errors here.

    The first error was that the prefab modification was plain not included in the build, and was VERY nice to catch. This is fixed now.

    The second error was what caused the first error to go away, by fauiltily baking in binary serialized data into the prefab instance when it's selected while exiting play mode (since it is binary serialized in play mode), which in this case accidentally made it work in the build. This is also fixed now. So now everything is working a lot better.

    These fixes will be included in 1.1 when that releases. If anybody needs the fixes urgently, please mail me at tor@sirenix.net with your Odin invoice ID, and state if you would like a 1.1 beta build, or a 1.0.6.9 build with the fixes backported from the 1.1 beta.

  13. epstal

    Great, thanks! Sorry I wasn't able to read this in time to send you my test project, but it sounds like it was straightforward enough to reproduce anyway.

  14. Log in to comment