Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice
  3. Dismiss Notice

Scriptable Object data not read after loading editor.

Discussion in 'Scripting' started by CoolJosh3k, Nov 2, 2020.

  1. CoolJosh3k

    CoolJosh3k

    Joined:
    Dec 3, 2016
    Posts:
    145
    I am experiencing a rather annoying issue with all my scripable object data assets.

    After closing the editor and coming back to it later, Unity no longer sees my data as valid.

    Unity_ScriptableObjectIssue.png

    How it should be vs what happens after loading the editor again.

    Forcing my script to recompile immediatly resolves the issue temporarily. Hitting play also caused the issue to resolve.

    Here is my code:
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. #if UNITY_EDITOR
    4. using UnityEditor;
    5. #endif
    6.  
    7. [CreateAssetMenu(fileName = "Data", menuName = "ScriptableObjects/StagePaletteData", order = 1)]
    8. public class StagePaletteData : ScriptableObject
    9. {
    10.     [Range(0, 63)]    public byte[] Addresses = new byte[3];
    11.    
    12.     #if UNITY_EDITOR
    13.     [SerializeField] private Color[] colors = new Color[3];
    14.     #endif
    15.    
    16.     #if UNITY_EDITOR
    17.    
    18.         public Texture2D colorPalette = null;
    19.         private Color32[] colorPaletteData;
    20.        
    21.         void OnValidate() {
    22.            
    23.             GetColorPaletteData();
    24.            
    25.             SetColors(colors, Addresses);
    26.         }
    27.        
    28.         void GetColorPaletteData() {
    29.             var data = colorPalette.GetRawTextureData<Color32>();
    30.             colorPaletteData = data.ToArray();
    31.         }
    32.        
    33.         void SetColors(Color[] colors, byte[] addresses) {
    34.             for (int i = 0; i < colors.Length; i++) {
    35.                 colors[i] = colorPaletteData[addresses[i]];
    36.             }
    37.         }
    38.     #endif
    39. }
    Is there something I am missing here? Or perhaps this is a bug?
     
  2. Madgvox

    Madgvox

    Joined:
    Apr 13, 2014
    Posts:
    1,319
    Make sure your script name matches the class name. That class should be in a file called
    StagePaletteData.cs
    .
     
  3. CoolJosh3k

    CoolJosh3k

    Joined:
    Dec 3, 2016
    Posts:
    145
    It matches.

    Assets\ScriptableObjects\StagePaletteData.cs
     
  4. CoolJosh3k

    CoolJosh3k

    Joined:
    Dec 3, 2016
    Posts:
    145
    In the inspector, choosing debug mode allows me to choose a script. I am able to drop in the StagePaletteData.cs and now it seems me problem is solved.

    Quite annoying as I'd have to insert this everytime I create a new asset, but at least it is something.
     
  5. Madgvox

    Madgvox

    Joined:
    Apr 13, 2014
    Posts:
    1,319
    In your left screenshot when it is "working", the greyed-out script field should have a reference to your script in it, but it is displaying
    None
    . This means that it's not finding your script properly for some reason. The most usual cause of this kind of issue is if your filename doesn't match the class name, but as you've ruled that out, there must be something else causing the reference to break.
     
  6. CoolJosh3k

    CoolJosh3k

    Joined:
    Dec 3, 2016
    Posts:
    145
    Makes sense, but quite odd. I do have the name right and it fixes itself after a recompile, so I'd imagine that something else is causing it to not automatically fill in that reference.

    Even when working, it still is missing that reference.
     
  7. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    39,388
    The linkage between a scriptable object instance and its script is twofold. For one it is the GUID contained in the .meta file for the script, but the other requirement is the class and file naming requirement as you list above.

    For instance, this is my StartingShips scriptable object: (StartingShips.asset, NOT the meta file)

    Code (csharp):
    1.  
    2. %YAML 1.1
    3. %TAG !u! tag:unity3d.com,2011:
    4. --- !u!114 &11400000
    5. MonoBehaviour:
    6.   m_ObjectHideFlags: 0
    7.   m_PrefabParentObject: {fileID: 0}
    8.   m_PrefabInternal: {fileID: 0}
    9.   m_GameObject: {fileID: 0}
    10.   m_Enabled: 1
    11.   m_EditorHideFlags: 0
    12.   m_Script: {fileID: 11500000, guid: 541a8be390a8a4758b654d7d6604eb8e, type: 3}
    13.   m_Name: StartingShips
    14.   m_EditorClassIdentifier:
    15.   InitialValue: 3
    16.   Save: 0
    The guid you see above references the .meta file of the ScriptableObject script, in this case
    Datasack.cs


    When I go look in
    Datasack.cs.meta
    , I see this:

    Code (csharp):
    1. fileFormatVersion: 2
    2. guid: 541a8be390a8a4758b654d7d6604eb8e
    3. timeCreated: 1517584268
    4. licenseType: Pro
    5. MonoImporter:
    6.   serializedVersion: 2
    7.   defaultReferences: []
    8.   executionOrder: 0
    9.   icon: {instanceID: 0}
    10.   userData:
    11.   assetBundleName:
    12.   assetBundleVariant:
    ... and the GUID matches. You can look in these with any text editor.

    Try cloning your SO script to a fresh renamed file, see if you can make instances that retain their connection.
     
    Madgvox likes this.
  8. CoolJosh3k

    CoolJosh3k

    Joined:
    Dec 3, 2016
    Posts:
    145
    Mine is the same.

    Code (CSharp):
    1. %YAML 1.1
    2. %TAG !u! tag:unity3d.com,2011:
    3. --- !u!114 &11400000
    4. MonoBehaviour:
    5.   m_ObjectHideFlags: 0
    6.   m_CorrespondingSourceObject: {fileID: 0}
    7.   m_PrefabInstance: {fileID: 0}
    8.   m_PrefabAsset: {fileID: 0}
    9.   m_GameObject: {fileID: 0}
    10.   m_Enabled: 1
    11.   m_EditorHideFlags: 0
    12.   m_Script: {fileID: 11500000, guid: bc4f08e4a12d9ff4cbff80cea21699a0, type: 3}
    13.   m_Name: SpinningSpitter_0
    14.   m_EditorClassIdentifier: Assembly-CSharp::StagePaletteData
    15.   Addresses: 131c26
    16.   colors:
    17.   - {r: 0.53333336, g: 0.07058824, b: 1, a: 1}
    18.   - {r: 0, g: 0.54509807, b: 0.58431375, a: 1}
    19.   - {r: 1, g: 0.5254902, b: 0.2784314, a: 1}
    20.   colorPalette: {fileID: 2800000, guid: 3ffc7985cd4abe641aac17a15bc5c5c1, type: 3}
    21.  
    Code (CSharp):
    1. fileFormatVersion: 2
    2. guid: bc4f08e4a12d9ff4cbff80cea21699a0
    3. MonoImporter:
    4.   externalObjects: {}
    5.   serializedVersion: 2
    6.   defaultReferences: []
    7.   executionOrder: 0
    8.   icon: {instanceID: 0}
    9.   userData:
    10.   assetBundleName:
    11.   assetBundleVariant:
    12.  
    This however is after that fix of using debug mode to choose the script. Ever since I did that I can not replicate the original issue as they all generate correctly.
     
  9. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    39,388
    If you rename the class from within visual studio, the currently infuriating state of that function (for actually the past decade, going back to Monobehavior) is that it renames the .cs file but does NOT rename the .cs.meta file.

    Therefore, Unity throws out your original GUID, which you MAY have already used, and creates a new one when it creates the new .meta file. It is the single most Fisher-Price non-professional feature there is in Unity. It is probably responsible for more bugs and lost engineering time than anything else.

    You can trivially reproduce it if you don't believe me. Here's how:

    - make a Scriptable Object class called Foo.cs
    - make an instance of a Foo
    - go into Visual Studio
    - rename class Foo to Bar and check the box that says rename source file
    - go back to Unity

    Tada, your ScriptableObject instance now has a missing script. Same thing goes if it was used in a prefab, or anywhere in any scene.

    Is that perhaps what happened? It's a miserable error because to me the MINIMUM thing Unity should do is not only tell you one time "I deleted the unused .meta file," but it should RIGHT THEN create a list of affected assets. It has all of that in a database FFS, and flag them PERMANENTLY in red, or at least offer to let you en-masse fix them.

    "Hey, we noticed that script Foo.cs disappeared and it was used by 2753 different prefabs. If you have a new script to replace it, tell us and we'll replace it right now."
     
    MadeFromPolygons likes this.
  10. CoolJosh3k

    CoolJosh3k

    Joined:
    Dec 3, 2016
    Posts:
    145
    I did rename my script at one point, but I had gone and recreated all my test assets for it after that anyway.

    Perhaps it got confused at some point along the way, but by me using debug mode I forced it to update?

    I don't use anything complex for coding. I just stick with Notepad++ so I can learn to not rely on those advanced features, even if it slows me down.
     
    Kurt-Dekker likes this.