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

Best way to use Scriptable Objects with multiple scripts while keeping things clean?

Discussion in 'Scripting' started by kraaazy, Feb 22, 2021.

  1. kraaazy

    kraaazy

    Joined:
    Dec 31, 2015
    Posts:
    20
    I have been reading a lot about scriptable objects and would like to incorporate them into my project, but I am a little confused on the best way to use them to keep things clean. Lets say I have a enemy and I want to make a scriptable object called EnemySO that stores all kinds of data about the enemy. I would then make one of these enemy scriptable objects for each enemy type. I can then make a script called Enemy.cs that takes in a EnemySO scriptable object and uses that data to handle its behavior. This all works great and I see multiple benefits from setting it up this way.

    My confusion comes when I want to make separate enemy scripts, say EnemyMovement and EnemyAttackManager etc. All of these scripts need to reference the EnemySO but it doesn't feel clean to have to manually drag the same EnemySO to all the enemy scripts that I have. It also doesn't feel clean to make one massive Enemy.cs script that handles all of the enemy behavior, but I only have to drag the SO into this one script. Any tips on how to set this up in a clean way?
     
  2. Ardenian

    Ardenian

    Joined:
    Dec 7, 2016
    Posts:
    313
    Well, an obvious solution is to create different SO instances for different scripts of your archetype, but you can imagine that this gets messy very quickly and requires even more steps until one has a finished enemy.

    I recommend creating a provider script for your archetype that holds the reference to the SO instance that represents your enemy. All other scripts, such as movement and attack, only reference this provider script, accessing the data from the SO instance in there using it themselves.

    Code (CSharp):
    1. public class UnitDataProvider : MonoBehaviour
    2. {
    3.     private UnitData data; // UnitData : ScriptableObject
    4.  
    5.     public UnitData Data => data;
    6. }
    Code (CSharp):
    1. public class Movement : MonoBehaviour
    2. {
    3.     [SerializeField]
    4.     private UnitDataProvider dataProvider;
    5.  
    6.     private void Update()
    7.     {
    8.         var movementSpeed = dataProvider.Data.MovementSpeed;
    9.         //do movement
    10.     }
    11. }
     
  3. kraaazy

    kraaazy

    Joined:
    Dec 31, 2015
    Posts:
    20
    My main goal of switching to SOs was to reduce references, but I guess having just one to the DataProvider still makes this much better than the alternative without using SOs. I'll go with this approach, thanks!