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 Spidyy · Jul 19, 2013 at 06:20 PM · serializationclasscastnesteddeclare

How should I declare a nested class to find it latter with SerializedObject.FindProperty?

Hello. I'm trying to imitate what was explained on the Unite 11 Intro to Editor Scripting on a ScriptableObject class. The class contain an array of another "class of the class".

Example :

 public class A : ScriptableObject
 {
     [System.Serializable]
     public class B
     {
         public B()
         {
         }
         
         Rect rectangle;
         Vector2 position;
     }
     
     public A()
     {
         myArray = new B[1];
         myArray[0] = new B();
     }
     
     private B[] myArray;
 }

With this class, the serialization works like a charm.

Now, I have an EditorWindow wich I use to populate my A's with some B's. For that, following the Unite 11 video, I use a SerializedObject and access its properties with SerializedObject.FindProperty(), like that :

     public class AEditor : EditorWindow
     {
         private SerializedObject myObject;
         
         public void SetA(A a)
         {
             myObject = new SerializedObject(a);
         }
         
         public void OnGUI()
         {
             if(myObject == null)
                 return;
         
             myObject.Update();
         
             A.B[] bs = GetBs();
         
             // Do stuff
         
             myObject.ApplyModifiedProperties();
         }
 
         private A.B[] GetBs()
         {
             int arraySize = myObject.FindProperty("myArray.Array.size").intValue;
             A.B[] bs = new A.B[arraySize];
             
             for(int i = 0; i < arraySize; i++)
             {
                 Object o = myObject.FindProperty(string.Format ("myArray.Array.data[{0}]", i)).objectReferenceValue;
                 if(o == null)
                 {
                     Debug.LogError ("Object not found in array.");
                     continue;
                 }
                 A.B b = o as A.B;
                 if(b == null)
                 {
                     Debug.LogError("B object not loaded");
                     continue;
                 }
                 bs[i] = b;
             }
             
             return bs;
         }
     }

With this, The script won't compile because of line 23 "A.B b = o as A.B;", I have this :

error CS0039: Cannot convert type 'UnityEngine.Object' to 'A.B' via a built-in conversion

So, I made B inherit from System.Object :

 public class A : SerializedObject
 {
     public class B : UnityEngine.Object
     {
         ...
     }
     ...
 }

Here, FindProperty find my Bs as UnityEngine.Object, but when I try to cast them, I got a null.

B object not loaded

Here is my question : how should I declare my class B so it can be found by FindProperty() AND be castable afterward?

Comment
Add comment · Show 5
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
avatar image AntiLunchBox · Jul 19, 2013 at 06:41 PM 0
Share

what variable is "frames". Why is it not "myArray". I don't see a variable named frames here.

avatar image Spidyy · Jul 19, 2013 at 09:26 PM 0
Share

Fixed. The example code is based on my project's code, $$anonymous$$imalized to have only what matter for the question. I forgot to change the name of the array in this string.

avatar image AntiLunchBox · Jul 19, 2013 at 10:13 PM 0
Share

when you do Debug.Log(typeof(o)), what does it say?

avatar image Spidyy · Jul 20, 2013 at 10:31 AM 0
Share

I couldn't answer that, because I was faced with another problem.

When I inheritate B from Object, I try to instanciate B like this :

 public class B : Object
 {
     public B()
     {
         myArray = new B[1];
         myArray[0] = new B();
     }
 }

But it seems B is not saved within A, all I have in myArray is null... Thus I now have :

Object not found in array.

So it seems inheriting B from Object is not a solution anymore.

Now, why I had my B's in the array when I asked the question, I don't know...

avatar image Spidyy · Jul 20, 2013 at 12:25 PM 0
Share

One solution would be to access each property of B individialy, ins$$anonymous$$d of the B itself. Like this :

 Rect rect = myObject.FindProperty(string.Format ("myArray.Array.data[{0}].rectangle", i)).rectValue;
 Vector2 vect = myObject.FindProperty(string.Format("myArray.Array.data[{0}].position", i)).vector2Value;

But I'm willing to have an answer to the main question anyway, in the case my B would contains faaaaaaar more properties.

1 Reply

· Add your reply
  • Sort: 
avatar image
1

Answer by Jamora · Jul 20, 2013 at 12:10 PM

This is what works for me:

 using UnityEngine;
 using UnityEditor;
 using System.Collections;
 
 public class AEditor : EditorWindow {
     
     [SerializeField]
     private A myObject;
     
     #region methods for testing
     [MenuItem("Temp/Temp")]
     public static void Init() {
         GetWindow<AEditor>();
     }
 
     void OnGUI() {
         A.B[] temp = GetBs();
         foreach (A.B b in temp){
             if(b != null)
                 b.i = EditorGUILayout.IntField(b.i);
         }
     }
     #endregion
     
     void OnEnable(){
         if (myObject == null){
             Debug.Log("instantiating serializedobject");
             myObject = ScriptableObject.CreateInstance<A>();
         }
     }
  
     private A.B[] GetBs() {
         int arraySize = myObject.myArray.Length;
         A.B[] bs = new A.B[arraySize];
         
         for (int i = 0; i < arraySize; i++) {
             A.B b = myObject.myArray[0];
             if(b == null) {
                 Debug.LogError("B object not loaded");
                 continue;
             }
             bs[i] = b;
         }
  
         return bs;
     }
     
 }


 using UnityEngine;
 using System.Collections;
 
 [System.Serializable]
 public class A : ScriptableObject {
 
     [SerializeField]
     public B[] myArray;
     
     void OnEnable() {
         hideFlags = HideFlags.HideAndDontSave;
         if(myArray == null) {
             Debug.Log("a constructor");
             myArray = new B[1];
             myArray[0] = new B();
         }
     }
     
     #region Nested Class : B
     [System.Serializable]
     public class B {
         public B()
         {
             Debug.Log("inside B constructor");
         }
             
         [SerializeField]
         public int i;
         Rect rectangle;
         Vector2 position;
     }
     #endregion
 }

I made your private variables public because I couldn't bother with the getters. Of course you won't be that lazy...

Comment
Add comment · Show 3 · Share
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
avatar image Spidyy · Jul 20, 2013 at 12:21 PM 0
Share

Of course, this code works fine, but in my case, I'm trying to use the SerializableObject (different from ScriptableObject alone) to indirectly edit my A object. All the question here is about accessing the nested B through SerializedObject.FindProperty.

But thanks to you, I remembered that a "class of a class" is better called "nested class". :p

avatar image Jamora · Jul 20, 2013 at 12:26 PM 1
Share

Seemed to me like you wanted serialization to work, well when working with SerializedObjects, you have to use their Update and Apply$$anonymous$$odifiedProperties when you want to work directly with properties. GetBs() would be a good place to at least update the SerializedObject.

Seems to me that working with serializedProperties is making a simple thing hard... Good for practice I guess.

avatar image Spidyy · Jul 20, 2013 at 03:36 PM 0
Share

I didn't made the OnGUI appear in my example, but of course I use the Update and Apply$$anonymous$$odifiedProperties on the SerializedObject.

Well, sure it makes things a bit harder, but the features of SerializedObject are quite interresting for a sturdy tool.

(I added OnGUI in the example just to be sure.)

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

17 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Getting any type in Unity Inspector 1 Answer

Renaming Serialized Classes 1 Answer

Serialization of Singleton vs Static class in Editor 1 Answer

How to get a List of all Variables in a Class 1 Answer

Null Reference When Setting a Class? 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