Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by chuckrussell · Apr 12, 2012 at 03:16 PM · serializationscriptableobjectassetdatabaseloadassetatpath

AssetDatabase.LoadAssetAtPath() not working after any sort of project change.

I have created a class which holds data about an object, which looks like the following:

 using UnityEngine;
 using System.Collections;
 using System;
 using System.Collections.Generic;
 
 [Serializable]
 public class SerializedParameters : ScriptableObject 
 {
     
     private SerializedParameter[] _items;
     
     public SerializedParameter[] Items
     {
         get
         {
             return _items;
         }
         set
         {
             _items = value;
         }
     }
     
     public SerializedParameters()
     {
         Items = new SerializedParameter[0];
     }
     
     public bool Contains(string name)
     {
         for(int i = 0; i < Items.Length; i++)
         {
             if(Items[i].Name == name)
             {
                 return true;
             }
         }
         return false;
     }
     
     public object GetValue(string name)
     {
         if(Contains(name))
         {
             for(int i = 0; i < Items.Length; i++)
             {
                 if(Items[i].Name == name)
                     return Items[i].Value;
             }
             return null;
         }
         else
         {
             return null;
         }
     }
     
     public void AddParam(string name, object val)
     {
         SerializedParameter[] temp = new SerializedParameter[Items.Length + 1];
         for(int i = 0; i < Items.Length; i++)
         {
             temp[i] = Items[i];
         }
         temp[Items.Length] = new SerializedParameter(name, val);
         Items = temp;
     }
 }
 
 [Serializable]
 public class SerializedParameter
 {
     private string _name;
     private object _value;
     
     public string Name
     {
         get
         {
             return _name;
         }
         set
         {
             Debug.Log ("Name Field changed: " + value);
             _name = value;
         }
     }
     public object Value
     {
         get
         {
             return _value;
         }
         set
         {
             Debug.Log ("Value Field changed: " + value);
             _value = value;
         }
     }    
     
     public SerializedParameter(string name, object val)
     {
         Name = name;
         Value = val;
         Debug.Log ("Constructor Called: Name-" + name + " Value-" + val );
     }
     
     public SerializedParameter()
     {
         Debug.Log ("Constructor Called");
     }
 }

The purpose of this is so that at run time, if the component does not exist on the object, I can perform a replace of the component and the metadata about the component (public fields, etc.) will be restored as well, so that I can load a scene at runtime and bring in the scripts as a dll resource. The serialize and deserialize functions look like this:

 using UnityEngine;
 using UnityEditor;
 using System.Collections;
 using System.Reflection;
 using System;
 
 [ExecuteInEditMode()]
 public class ComponentBase : MonoBehaviour {
 
     public virtual void Serialize()
     {
         SerializedParameters parameters = ScriptableObject.CreateInstance<SerializedParameters>();
         
         Type type = this.GetType();
         foreach(FieldInfo info in type.GetFields())
         {            
             foreach(Attribute att in info.GetCustomAttributes(true))
             {
                 if(att.ToString().Contains("SerializableProperty"))
                 {
                     object obj = info.GetValue(this);
                     //Debug.Log (info.Name + " " + obj );
                     parameters.AddParam(info.Name, obj);
                 }
             }
         }
         
         ComponentManager cm = gameObject.GetComponent<ComponentManager>();
         if(cm != null)
         {
             AssetDatabase.CreateAsset(parameters, "Assets/" + cm.GUID + ".asset");
             AssetDatabase.SaveAssets();
             AssetDatabase.Refresh();
         }
     }
     
     public virtual void Deserialize()
     {
         ComponentManager cm = gameObject.GetComponent<ComponentManager>();
         
         SerializedParameters parameters = AssetDatabase.LoadAssetAtPath ("Assets/" + cm.GUID + ".asset", typeof (SerializedParameters)) as SerializedParameters;
         if(parameters != null)
         {
             Type type = this.GetType();
             foreach(FieldInfo info in type.GetFields())
             {            
                 foreach(Attribute att in info.GetCustomAttributes(true))
                 {
                     if(att.ToString().Contains("SerializableProperty"))
                     {
                         if(parameters.Contains(info.Name))
                         {
                             info.SetValue(this, parameters.GetValue(info.Name));
                         }
                     }
                 }
             }
         }
     }
     
     // Use this for initialization
     void Start () 
     {
         
     }
     
     // Update is called once per frame
     void Update () 
     {
     
     }
     
     void Awake()
     {
         Deserialize();
     }
 }

As you can see, I use reflection to go through all of the fields, and for every field store a SerializedParameter into the array in my SerializedParameters object. The whole SerializedParameters object is then saved as an asset using a unique GUID. If the component is ever missing, I simply run the deserialize function and the component comes back repopulated correctly, so that the scripts can activly choose whether or not to use a class at runtime (like an external dll) or to use the scripts in the project folder.

If I run serialize on all objects, and asset with their GUID pops up in the Project panel. Then I can delete the component, deserialize and all works like a charm. However, If any changes to the project are made, such as changing the directory of any script, changing any script contents, or restarting unity, the LoadAsset at path does not work correctly. The object comes back, the correct number of fields are there, and all of the name values of the SerializedParameter object are correctly assigned but the Value property of the SerializedParameter objects are all null.

Thank you for your time to look at this problem.

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

0 Replies

· Add your reply
  • Sort: 

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

4 People are following this question.

avatar image avatar image avatar image avatar image

Related Questions

Serializing a collection of ScriptableObjects to an ASSET file? 1 Answer

Creating ScriptableObject Asset "Failed to write meta file" 1 Answer

Unity loses association to ScriptableObject after exiting playmode 0 Answers

How can I create, via script, a hidden subasset (ScriptableObject) that is editor-only and invisible in Project view? 1 Answer

Using System.Object in ScriptableObject 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges