Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Scriptable objects unique functions per instance

Discussion in 'Scripting' started by Jack-van-der-Bilt, Apr 19, 2020.

  1. Jack-van-der-Bilt

    Jack-van-der-Bilt

    Joined:
    Jul 13, 2015
    Posts:
    17
    Hello,

    I have a scriptable object named 'Biome'. Each instance of 'Biome' should have a custom unique function attached to it.

    How do I attach a unique function? If it is not possible, what workaround would be the most efficient?

    This issue is really a project-killer atm.

    Thanks for the help!
     
  2. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    7,846
    There are many ways. Some are:
    1. You could inherit from Biome and implement a virtual function.
    2. Biome could have an interface property and then use SerializeReference to store different implementations
    3. Biome could have an abstract ScriptableObject class as public property and then attach a reference to a concrete asset.
    for example

    option 2:
    Code (csharp):
    1.  
    2.  
    3. public interface MyInterface
    4. {
    5. void DoSomething();
    6. }
    7.  
    8. [Serializable]
    9. public class MyFunction : MyInterface
    10. {
    11.     public void DoSomething(){ // TODO: }
    12. }
    13.  
    14. public class Biome: SceriptableObject
    15. {
    16.     [SerializeReference]
    17.     public MyInterface function = new MyFunction();
    18.  
    19.     void UseIt()
    20.     {
    21.         function.DoSomething();
    22.     }
    23. }
     
  3. Jack-van-der-Bilt

    Jack-van-der-Bilt

    Joined:
    Jul 13, 2015
    Posts:
    17
    Hi @karl_jones,

    Thanks for the response. I got a step closer but I'm not there yet.
    I'll try to explain my problem with more detail because I'm questioning if what I want is actually possible.

    My project is set up like this;
    upload_2020-4-20_11-11-42.png

    "Biome" is the scriptable object
    "BiomeGenerator" is the base class all biome generators inherit from
    "BiomeGenerator..." is "BiomeGeneratorDessert" that inherits from "BiomeGenerator".

    My biome scriptable object, after applying your suggestions and stripping it down, looks like this;
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. [CreateAssetMenuAttribute( fileName = "New Biome", menuName = "Biome")]
    6. public class Biome : ScriptableObject
    7. {
    8.     public string biomeName;
    9.     public string someOtherInfo;
    10.  
    11.     [SerializeReference]
    12.     public BiomeGenerator generator;
    13. }
    And my BiomeGenerator class, after applying your suggestions and stripping it down, looks like this;
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. [System.Serializable]
    6. public class BiomeGenerator
    7. {
    8.    
    9. }
    10.  
    And finally, my BiomeGeneratorChild class, after applying your suggestions and stripping it down, looks like this;
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. [System.Serializable]
    6. public class BiomeGeneratorDessert : BiomeGenerator
    7. {
    8.    
    9. }
    10.  
    Currently, the inspector shows only this;
    upload_2020-4-20_11-48-22.png
    I edited out the other values not related to this question, but the generator input is actually gone, even before photoshopping it)

    My goal is to create a easy way for me to create a new instance of the "biome" scriptable object using the "create asset" menu. For each instance I would fill in some information and finally attach a reference to one of the "BiomeGenerator" child classes that override the functions of the base class that take care of the world generation for that specific biome. Finally add that Biome instance to an array in one of my "World" scriptable objects and have the GameManager script generate the to be configured world for me.

    The structure kinda look like this;
    "GameManager > World[] worlds > Biome[] biomes > Structures[], Plants[], Mobs[], etc."
    this.generateWorld( this.worlds[0] );

    Since my GameManager generates the GameObjects at runtime I don't fancy using prefabs. I also feel like there should be a way to achieve my main goal (easily creating new stuff without much coding using the editor) using a different approach. Sadly, I have no idea what Unity wants me to do and if what I want is even possible.

    So, my final question is;
    Why doesn't the inspector show the selection input field? If what I'm trying to accomplish isn't possible, what would be the best way to still realize this?
     
  4. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    7,846
    The field is empty because it has no serialized properties. Try adding some.
    For adding and removing you would need to create a custom editor as there is not currently one for SerializeReference.
    You may find it easier to use another ScriptableObject for BiomeGenerator instead. Then you can just assign a reference to the generator through the inspector.

    So have BiomeGenerator inherit from ScriptableObject and then create an asset for each type and drag and drop them into the main Biome asset.