Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
2 captures
12 Jun 22 - 14 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 harrismck · Nov 17, 2018 at 07:16 AM · inspectoreditor-scriptinginheritanceinterface

How to set an object reference field in the Inspector

What I want is to be able to call a method on an object (doesn't need to be MonoBehaviour), where the specific implementation of that method is chosen in the inspector. I will paste an example of what I'm trying to do, then describe in better detail how I would like it to work.


The Base Class (Could also be an Interface, Abstract class... whatever works.)

 [System.Serializable]
 public class TestBase
 {
     public virtual string RetStr()
     {
         return "Base Class";
     }
 }

The inherited class/Implementer:

 [System.Serializable]
 public class TestClass : TestBase
 {
     public override string RetStr()
     {
         return "Inherited Class";
     }
 }

The MonoBehaviour, with the public field I wish to set:

 using UnityEngine;
 
 public class Assignee : MonoBehaviour {
     public TestBase testObj;
 
     private void Awake()
     {
         if (testObj == null)
             Debug.Log("testObj is null");
         else
             Debug.Log("testObj.RetStr() = " + testObj.RetStr());
     }
 }

And the custom editor (that, to keep it simple, Assigns either the base or the inherited):

 using UnityEngine;
 using UnityEditor;
 
 [CustomEditor(typeof(Assignee))]
 public class AssigneeEditor : Editor
 {
     Assignee assignee;
     bool setTest;
 
     void OnEnable()
     {
         assignee = target as Assignee;
         setTest = assignee.testObj.GetType() != typeof(TestBase);
     }
 
     public override void OnInspectorGUI()
     {
         setTest = EditorGUILayout.Toggle(new GUIContent("Set testObj"), setTest);
 
         if (setTest)
             assignee.testObj = new TestClass();
         else
             assignee.testObj = new TestBase();
 
         serializedObject.ApplyModifiedProperties();
     }
 }

The issue is that, while I can change the field in play mode, entering/exiting play mode resets it, also that this whole method is weird. This is probably due to it not being serialized.

The goal is for the workflow to be like: Create new C# script -> Change it to inherit from/implement TestBase -> On a MonoBehaviour component that has a TestBase field, choose a specific one somehow (for now, just selecting between two is sufficient to prove it can be done).

Comment
Add comment · Show 2
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 hexagonius · Nov 17, 2018 at 12:13 PM 1
Share

the problem is that you're assigning an actual instance, which of course is only alive at runtime. is it was a monobehaviour in the scene, unity would manage the instantiation through the serialization system for you, but it's not, you need to do that for yourself. now since you can't save an instance, what can you save. you could go for the concrete type, but System.Type is not serializable. what you can serialize though, is the name. to uniquely identify it, the assembly is also needed.
so what you need to do is populate a dropdown showing all thr derivates from your base type. you can use reflection for that. then you save the full name, including the assembly, as a string for which you wrote the editor script. I went down this road and decided to do this via custom inspector which uses an attribute to define the base type you want to serialize the derivates into the string.
one pitfall comes in when deciding to change to or from Assembly definition files as that switch changes the assembly rendering all serializations useless, unless you write code that compensates for that.

avatar image harrismck hexagonius · Nov 18, 2018 at 04:32 AM 0
Share

I did have a working method to get all System.Types that implement, but yes, I found out that System.Types are also not serializable. Saving the full name is an interesting idea though! Seems like it would work, as I could just instantiate it in Awake() based on a string. I'm certain that would work.

The original reason for this question was because my "Assignee" was a ScritptableObject, not a $$anonymous$$onoBehaviour. After asking this question, I realized I could simply make both Assignee and TestBase $$anonymous$$onoBehaviours and add them both as components, setting up the ref with GetComponent<>(). This isn't an ideal solution either, as the objects really don't need any $$anonymous$$onobehaviour features, but it seems to be what Unity wants, and avoids any weird stuff with reflection.

Thanks a lot for the solution though! I'll keep that in $$anonymous$$d.

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

110 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 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 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 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 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 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 avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Custom classes, inheritance and the inpector 0 Answers

Custom ordering of variables in inspector when using base and derived classes 1 Answer

Hide headers and variables in inspector from parent classes 1 Answer

Instantiating an object from its interface 3 Answers

TexturePropertySingleLine in Editor class 0 Answers


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