Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
4 captures
13 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
1
Question by rickymanalo · Oct 31, 2021 at 01:37 PM · listscriptableobjectinheritanceinterface

How to make a List that can store anything that implements an interface?

I recently hit a dilemma. I want to make something like a file explorer, where I want to show/store a List of ScriptableObjects that implements something like a "file" interface. I already figured out most of the parts. I already have this code for the container script:

 public class FileContainer : MonoBehaviour, IFileContainer
 ......
 [SerializeField]
 List<FileItem> _contents;
 public List<FileItem> contents {
     get{ return _contents; } 
     set{ _contents = contents; }
 }

And have a ScriptableObject which looks something like this:

 public class BlahFile : ScriptableObject, ..., IFileItem

If I use the interface directly as the type of List on FileContainer, the List's variable doesn't show up on the editor. Then if I use a class that implements the interface, then I can't add any other object because I can only use that specific class.

What is the cleanest way to implement what I want to do? I tried to use an abstract class for the ScriptableObject but it creates a "multiple classes" error so I didn't go with it.

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

4 Replies

· Add your reply
  • Sort: 
avatar image
0
Best Answer

Answer by rickymanalo · Nov 03, 2021 at 01:35 PM

After some thinking, I found a solution that's kinda similar to @Bunny83's first suggestion that makes sense for me. What I did is I made a class FileItem that implements IFile that also extends ScriptableObject. Then I made every field on the class a SerializeField. So now BlahFile extends FileItem, I think this could work for my use case.

Comment
Add comment · 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
2

Answer by Bunny83 · Nov 02, 2021 at 09:27 AM

I think you're lost between different concerns here. Using a List of an interface type works just fine in C# and you can Add and use those as expected in code. However you will not get any editor support for lists of interfaces. At least it seems that's your main issue:

If I use the interface directly as the type of List on FileContainer, the List's variable doesn't show up on the editor.


References to assets or generally to UnityEngine.Object derived objects can only be serialized when the field type is derived from UnityEngine.Object.


Note that there are some more or less hacky ways around that, but all require quite a bit of boilerplate and editor code. One way is to actually store a List / array of UnityEngine.Object in the class. That way it could reference any asset. In addition you would have another List of your interface type and use the ISerializationCallbackReceiver to actually fill / synchronise your Lists. Of course in order to reject any invalid references you may use a PropertyDrawer that takes care of the filtering. Though the synchronising code should be careful as well since it's possible that you added for example a scriptable object that used to have the interface but later you removed the interface. So the Object array would still hold the reference but it no longer has the interface so the cast would fail.


Another approach that could work is to use unity's SerializeReference feature. It allows to serialize anything and does even support interfaces. However those references can't be across assets. So it only supports custom serializable classes which are stored inside that MonoBehaviour or ScriptableObject that contains your List. For those it actually supports inheritance and polymorphism. So it may be possible to create wrapper classes that implement your interface and store the actual reference to the asset in a private serialized field that is of type UnityEngine.Object. This has several issues though. First of all fields with SerializeReference don't have editor support out-of-the-box. So you have to handle the creation of those wrappers in your editor code. Also the actual casting from the serialized value to the interface type is still required.


Personally I think the first approach would be simpler. It could even be packed into a custom "InterfaceList" type that does handle all this conversion stuff internally.

Comment
Add comment · 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
0

Answer by Llama_w_2Ls · Nov 02, 2021 at 08:10 AM

Have your abstract class inherit from scriptable object. Then have your child classes inherit from the abstract class. They will inherit the properties of a scriptable object and the base class, essentially allowing for multiple inheritance whilst still allowing scripts to show in the editor.

Comment
Add comment · 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
0

Answer by Arycama · Nov 02, 2021 at 08:52 AM

You can make IFileContainer and IFileItem inherit from a common interface, eg IFileData, and then have a list of IFileData.

Comment
Add comment · 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

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

137 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 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

List of Generic ScriptableObjects? Wrappers maybe? 0 Answers

A node in a childnode? 1 Answer

Can you allow inhereted ScripableObjects to be linked in the editor without dragging and dropping. 0 Answers

Interaction script 2 Answers

Why does my List overwrite itself when using .Add? 2 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