Search Unity

  1. Unity 2020.2 has been released.
    Dismiss Notice
  2. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

Use interface to call scriptableObject

Discussion in 'Scripting' started by nwxp, Mar 21, 2018.

  1. nwxp

    nwxp

    Joined:
    Apr 4, 2017
    Posts:
    19
    I have a Base Object abstract class :

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3.  
    4. public abstract class BaseObject : ScriptableObject {
    5.     public int hauteur = 1;
    6.     public int level = 1;
    7. }
    And I have multiple interface that can be implemented into BaseObject :

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3.  
    4. public interface ISpawnable {
    5.     GameObject GetGameObject();
    6.  
    7.     int GetSpawnPosition();
    8.     bool ShouldSpawn();
    9. }
    So I have objects that looks like that :

    Code (CSharp):
    1. [CreateAssetMenu(fileName = "Spawnable", menuName = "Inventory/Spawnable", order = 1)]
    2. public class SpawnableObject : BaseObject, ISpawnable {
    3.     public GameObject gameObject;
    4.     public int nbrOfBlockForSpawning;
    5.     public int nbrBeforeFirstSpawn;
    6.     public int spawnPosition;
    7.  
    8.     public GameObject GetGameObject() {
    9.         return gameObject;
    10.     }
    11.  
    12.     public int GetSpawnPosition() {
    13.         return spawnPosition;
    14.     }
    15.  
    16.     public bool ShouldSpawn(int index) {
    17.         return (index > nbrBeforeFirstSpawn && index % nbrOfBlockForSpawning == 0);
    18.     }
    19. }
    I have SpawnController that handle Spawning Object :

    Code (CSharp):
    1. using System.Collections.Generic;
    2. using UnityEngine;
    3.  
    4. public class SpawnController : MonoBehaviour {
    5.     [SerializeField]
    6.     public List<SpawnableObject> spawnableObjects;
    7.  
    8.     // Stripped some code here since it's not important for what I want to show
    9.  
    10.     void Update() {
    11.         if (!isSpawning) return;
    12.  
    13.         if (counterFrequency <= 0.0f) {
    14.             SpawnObjects();
    15.             counterBlocks++;
    16.         } else {
    17.             counterFrequency -= Time.deltaTime * frequency;
    18.         }
    19.     }
    20. }
    Now I also want my spawnableObject to be Collectable (player can pick it up) and my design break here because I would have to make a class "SpawnableAndCollectableObject" which seems horrible.

    So I think my design is flawed but I cannot figure out a good way to have a scriptableObject with multiple interface.

    Can anyone tell me why me design is wrong and what I could do to make it better ?

    I'm practicing Unity so this project is to help me figure out good architectural and design pattern.
     
  2. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    2,216
    This is a classic OOP issue where your inheritance tree becomes too granular. The solution is generally composition of behaviours:
    Code (csharp):
    1.  
    2.  
    3. public class MyGameObject : ISpawnable, IKillable
    4. {
    5.    SpawnBehaviour spawn;
    6.    KillBehaviour kill;
    7.  
    8.    // initialize their data in Awake()
    9.  
    10.    // pass-through implementation of your interface contracts:
    11.    public void OnSpawn() { return spawn.OnSpawn(); }
    12.    public void OnKill() { return kill.OnKill(); }
    13. }
    14.  
    15.  
    I'm curious why you're using so much inheritance though. Unity is designed around composition. The Player isn't a MoveableKillableSpawnableObject, the Player is a GameObject with Moveable, Killable, Spawnable behaviours.
     
  3. nwxp

    nwxp

    Joined:
    Apr 4, 2017
    Posts:
    19
    The thing is, not every ScriptableObject will have Spawnable behaviour, so I don't want to have a field "SpawnBehaviour".

    I get it now that Unity isn't really made to work with interface but I think it's a great OOP feature and I was wondering if I could make it work with my design pattern.
     
unityunity