Search Unity

CustomEditor with ScriptableObject: associated script could not be loaded

Discussion in 'Scripting' started by masonjash, Jul 1, 2016.

  1. masonjash

    masonjash

    Joined:
    Jan 5, 2013
    Posts:
    14
    I'm having this really bizarre problem with ScriptableObject assets where upon starting Unity or when building the game, references to a ScriptableObject created with a CustomEditor go null and upon inspecting the asset I get the following error:



    The temporary solution I found to this problem is to reimport the editor script, which will fix the issue while inside the editor and will remained fixed until the editor is relaunched.

    However this solution is not sufficient because the error is still presents in builds of the game.

    The ScriptableObject and CustomEditor are defined as follows (sorry for dumping spaghetti-code):

    ArmExtensionDefinition.cs:

    Code (CSharp):
    1. [System.Serializable]
    2. [CreateAssetMenu()]
    3. public class ArmExtensionDefinition : ScriptableObject
    4. {
    5.     [System.Serializable]
    6.     public struct ExtensionFrame
    7.     {
    8.         public Sprite sprite;
    9.         public Vector2 shoulderPosition;
    10.         public Vector2 handPosition;
    11.     }
    12.  
    13.     public ExtensionFrame[] frames;
    14. }
    15.  
    ArmEditor.cs:

    Code (CSharp):
    1. [CustomEditor(typeof(ArmExtensionDefinition))]
    2. public class ArmEditor : Editor
    3. {
    4.     Texture2D spriteTexture;
    5.  
    6.     int settingShoulderFrameIndex = -1;
    7.     int settingHandFrameIndex = -1;
    8.  
    9.     void OnEnable()
    10.     {
    11.         var spriteProp = serializedObject.FindProperty("frames.Array.data[0].sprite");
    12.  
    13.         if (spriteProp != null) {
    14.             spriteTexture = ((Sprite)spriteProp.objectReferenceValue).texture;
    15.         }
    16.     }
    17.  
    18.     public override void OnInspectorGUI()
    19.     {
    20.         this.serializedObject.Update();
    21.  
    22.         var newSpriteTexture = EditorGUILayout.ObjectField("Arm Sprite", spriteTexture, typeof(Texture2D), false) as Texture2D;
    23.  
    24.         if (newSpriteTexture != spriteTexture && newSpriteTexture != null) {
    25.             var path = AssetDatabase.GetAssetPath(newSpriteTexture.GetInstanceID());
    26.  
    27.             Sprite[] sprites = AssetDatabase.LoadAllAssetsAtPath(path).OfType<Sprite>().ToArray();
    28.  
    29.             serializedObject.FindProperty("frames.Array.size").intValue = sprites.Length;
    30.  
    31.             for (int i = 0; i < sprites.Length; i++) {
    32.                 serializedObject.FindProperty(string.Format("frames.Array.data[{0}].sprite", i)).objectReferenceInstanceIDValue = sprites[i].GetInstanceID();
    33.             }
    34.  
    35.             spriteTexture = newSpriteTexture;
    36.         }
    37.  
    38.         var len = serializedObject.FindProperty("frames.Array.size").intValue;
    39.  
    40.         var e = Event.current;
    41.         for (int i = 0; i < len; i++) {
    42.             var sprite = serializedObject.FindProperty(string.Format("frames.Array.data[{0}].sprite", i)).objectReferenceValue as Sprite;
    43.  
    44.             Texture2D preview = AssetPreview.GetAssetPreview(sprite);
    45.  
    46.             GUILayout.Label(preview);
    47.  
    48.             var previewRect = GUILayoutUtility.GetLastRect();
    49.  
    50.             if (settingShoulderFrameIndex == i && e.type == EventType.mouseDown && previewRect.Contains(e.mousePosition)) {
    51.                 var positionInTexture = new Vector2(e.mousePosition.x - previewRect.position.x, previewRect.yMax - e.mousePosition.y);
    52.                 var positionInSprite = positionInTexture - sprite.pivot;
    53.                 positionInSprite = positionInSprite * 1f / sprite.pixelsPerUnit;
    54.                 serializedObject.FindProperty(string.Format("frames.Array.data[{0}].shoulderPosition", i)).vector2Value = positionInSprite;
    55.                 settingShoulderFrameIndex = -1;
    56.             }
    57.  
    58.             if (settingHandFrameIndex == i && e.type == EventType.mouseDown && previewRect.Contains(e.mousePosition)) {
    59.                 var positionInTexture = new Vector2(e.mousePosition.x - previewRect.position.x, previewRect.yMax - e.mousePosition.y);
    60.                 var positionInSprite = positionInTexture - sprite.pivot;
    61.                 positionInSprite = positionInSprite * 1f / sprite.pixelsPerUnit;
    62.                 serializedObject.FindProperty(string.Format("frames.Array.data[{0}].handPosition", i)).vector2Value = positionInSprite;
    63.                 settingHandFrameIndex = -1;
    64.             }
    65.  
    66.             GUILayout.BeginHorizontal();
    67.  
    68.             var shoulderPosProp = serializedObject.FindProperty(string.Format("frames.Array.data[{0}].shoulderPosition", i));
    69.             EditorGUILayout.PropertyField(shoulderPosProp, new GUIContent("Shoulder Position"));
    70.  
    71.             if (GUILayout.Toggle(settingShoulderFrameIndex == i, "Set")) {
    72.                 settingShoulderFrameIndex = i;
    73.             }
    74.  
    75.             GUILayout.EndHorizontal();
    76.  
    77.             GUILayout.BeginHorizontal();
    78.  
    79.             var handPosProp = serializedObject.FindProperty(string.Format("frames.Array.data[{0}].handPosition", i));
    80.             EditorGUILayout.PropertyField(handPosProp, new GUIContent("Hand Position"));
    81.             if (GUILayout.Toggle(settingHandFrameIndex == i, "Set")) {
    82.                 settingHandFrameIndex = i;
    83.             }
    84.  
    85.             GUILayout.EndHorizontal();
    86.  
    87.         }
    88.  
    89.         serializedObject.ApplyModifiedProperties();
    90.     }
    91. }
    Any ideas what's causing this issue?
     
  2. jimroberts

    jimroberts

    Joined:
    Sep 4, 2014
    Posts:
    560
    Your scripts are working fine for me. Do you have another script that has compiler errors?
     
    Last edited: Jul 1, 2016
  3. masonjash

    masonjash

    Joined:
    Jan 5, 2013
    Posts:
    14
    The script does not contain any compiler errors or warnings. It is perfectly functional after reimporting ArmEditor.cs
     
  4. masonjash

    masonjash

    Joined:
    Jan 5, 2013
    Posts:
    14
    There are no errors in any other scripts.

    The game runs just fine with no issues. It's only when restarting the editor or when building the game that this problem is present.
     
  5. jimroberts

    jimroberts

    Joined:
    Sep 4, 2014
    Posts:
    560
    What version of Unity are you using?
     
  6. masonjash

    masonjash

    Joined:
    Jan 5, 2013
    Posts:
    14
    5.3.5f1 Personal Edition
     
  7. jimroberts

    jimroberts

    Joined:
    Sep 4, 2014
    Posts:
    560
    Is your Editor script in the \Assets\Editor\ folder?
     
  8. masonjash

    masonjash

    Joined:
    Jan 5, 2013
    Posts:
    14
    Yep it's at \Assets\Editor\ArmEditor.cs
     
  9. jimroberts

    jimroberts

    Joined:
    Sep 4, 2014
    Posts:
    560
    So... try moving it to the \Assets\ folder instead. It works fine for me when it's not in the Editor folder.
     
  10. masonjash

    masonjash

    Joined:
    Jan 5, 2013
    Posts:
    14
    I still have the same issue after moving it out of the editor folder :confused:
     
  11. jimroberts

    jimroberts

    Joined:
    Sep 4, 2014
    Posts:
    560
    Does it happen when you use only the 2 scripts in a completely new project? Sorry, grasping at straws now. I'm using 5.3.2f1 so it might be a bug in one of the newer releases.
     
  12. masonjash

    masonjash

    Joined:
    Jan 5, 2013
    Posts:
    14
    Now I'm really baffled. It works just fine in a new project. I have no clue why my project specifically is causing this problem.
     
  13. masonjash

    masonjash

    Joined:
    Jan 5, 2013
    Posts:
    14
    I noticed a difference between how its serialized in the new project vs the old project.

    In the new project it's serialized like this (text serialization mode):

    MonoBehaviour:
    m_ObjectHideFlags: 0
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 0}
    m_GameObject: {fileID: 0}
    m_Enabled: 1
    m_EditorHideFlags: 0
    m_Script: {fileID: 11500000, guid: b70a83d1fe1f4c44592f591e99e03931, type: 3}
    m_Name: Player
    m_EditorClassIdentifier:
    frames:
    - sprite: {fileID: 21300000, guid: d10c6ae1b9da7fb438d6657461b43fd7, type: 3}
    shoulderPosition: {x: -0.04, y: 0.08}
    handPosition: {x: 0.03, y: 0.01}
    ...

    while in the old project it's serialized like this:

    MonoBehaviour:
    m_ObjectHideFlags: 0
    m_PrefabParentObject: {fileID: 0}
    m_PrefabInternal: {fileID: 0}
    m_GameObject: {fileID: 0}
    m_Enabled: 1
    m_EditorHideFlags: 0
    m_Script: {fileID: 0}
    m_Name: Player
    m_EditorClassIdentifier: Assembly-CSharp::ArmExtensionDefinition
    frames:
    - sprite: {fileID: 21300000, guid: 6b19fdb02498201468de4f36f954fa96, type: 3}
    shoulderPosition: {x: 0, y: 0}
    handPosition: {x: 0.22039977, y: -0.16446209}
    ...

    Notice the m_Script and m_EditorClassIdentifier properties are changed.

    When I change the old project's .asset file to match, the problem is fixed.

    The question to me is why unity decided to serialize it incorrectly in the first place.

    Thank you for all the help, jimroberts. Much appreciated.
     
  14. jimroberts

    jimroberts

    Joined:
    Sep 4, 2014
    Posts:
    560
  15. lin_mdotor

    lin_mdotor

    Joined:
    Apr 21, 2015
    Posts:
    2
    Maybe this problem appeared after Unity changed some .meta files?
    This post may help you ;)
     
  16. orkungo

    orkungo

    Joined:
    May 3, 2014
    Posts:
    62
    I experience the same problem with ScriptableObjects on 5.6.0f3 , do you know if it is a bug still with meta files ?
     
  17. MohHeader

    MohHeader

    Joined:
    Aug 12, 2015
    Posts:
    41
    Same issue here with Unity 2017.1.0p5

    I need to re-import the script, thought that .asset file would work fine :(
     
  18. haoshisnowedin

    haoshisnowedin

    Joined:
    May 24, 2019
    Posts:
    1
    This is quite old, but I just ran into this, and it turns out to be a silly problem.
    Make sure:
    1. Each scriptable object lives in its own file.
    2. Each file's name matches exactly the scriptable object class' name.
    otherwise, you'll get that error, but nothing tells you that you can't have them in one place.