Search Unity

Question Skills / Ability / PowerUps Systems with Scriptable Objects help

Discussion in 'Scripting' started by EdoC-QWERTY, May 21, 2021.

  1. EdoC-QWERTY

    EdoC-QWERTY

    Joined:
    Feb 1, 2020
    Posts:
    75
    Hello,
    I need some help on how to make a skill / ability system for my simple mobile 2D game.

    The idea is that the player can unlock new abilities by picking up power-ups scattered around the world.

    Once the ability is picked up it can be permanent or consumable.
    Permanent abilities can be leveled up.

    The player has only 2 ability slots connected to 2 UI buttons, each button triggers the corresponding ability effect.

    The player can switch abilities at any time during the game.
    He could for example have Dash ability on slot 1, and fireball on slot 2; and then when a new ability is picked up, that new ability on slot 1 and Dash moved to slot 2.

    I already searched myself and it seems that the best way is to use ScriptableObjects, I found this link
    https://learn.unity.com/tutorial/cr...h-scriptable-objects#5cf5ecededbc2a36a1bd53b7

    That provides a tutorial on how to make a similar system, it's from 2016 so I'm wondering if there is a better way, I use Unity 2020.3 .

    But it seems to me that the abilities are all already on the character, the system allows to test new abilities easier as a developer but there is no mention of an ability list.
    Also abilities are basically components added to the player Gameobject.

    Later I found out about ScriptableObjects and Unity Events and Event listeners
    https://www.monkeykidgc.com/2021/02/pass-parameters-with-scriptableobject-events-in-unity.html

    I think I just need some help to figure out how to set things up.

    Currently I have a project with this set up.

    PlayerAbility - basescriptable objects for abilities.
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. [CreateAssetMenu(fileName = "BasePlayerAbility", menuName = "ScriptableObjects/PlayerAbilities/BaseAbility")]
    6.  
    7. public class PlayerAbility : ScriptableObject
    8. {
    9.     public string name;
    10.  
    11.     public Sprite spriteicon;
    12.     public bool ispassive;
    13.     public bool ispermanent;
    14.     public bool hascharges;
    15.     public bool isoncooldown;
    16.     public int level;
    17.     public PlayerStats playerStats;
    18.     public float cooldown;
    19.     public int charges;
    20.  
    21.    // public IEnumerator CooldownEnum; // Need to figure out how to trigger couroutines from SO
    22.     public virtual void Start()
    23.     {
    24.        
    25.         isoncooldown = true;
    26.        // CooldownEnum = CoolDown(cooldown);
    27.        
    28.     }
    29.  
    30.     public virtual void OnUse()
    31.     {
    32.         if(!isoncooldown)
    33.         {
    34.            
    35.             //StartCoroutine(CooldownEnum);
    36.             TriggerEffect();
    37.         }              
    38.     }
    39.  
    40.     public virtual void TriggerEffect()
    41.     {
    42.  
    43.     }
    44. }

    With this base class I can create Custom Player Abilities that do different things. For example dash

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. [CreateAssetMenu(fileName = "AbilityDash", menuName = "ScriptableObjects/PlayerAbilities/Abilities/Dash")]
    6.  
    7. public class Ability_Dash : PlayerAbility
    8. {
    9.     // Start is called before the first frame update
    10.    
    11.     public float dashforce;
    12.     public float dashduration;
    13.  
    14.      public override void Start()
    15.     {
    16.         name = "DASH";
    17.         base.Start();
    18.  
    19.     }
    20.  
    21.     public override void OnUse()
    22.     {
    23.         base.Use();
    24.        
    25.     }
    26.  
    27.     public override void TriggerEffect()
    28.     {
    29.        
    30.         base.TriggerEffect();
    31.  
    32.         //Dash Event Triggered -- !
    33.  
    34.     }
    35.  
    36. }
    37. }

    Then the Player has different components, some monobehaviors like PlayerController and some scriptable objects like PlayerStats.
    All the picked up abilities are stored in PlayerStats in a List.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. [CreateAssetMenu(fileName = "PlayerStats", menuName = "PlayerStats")]
    6.  
    7. public class PlayerStats : ScriptableObject
    8. {
    9.     // Start is called before the first frame update
    10.     public int hp;
    11.     public float basespeed;
    12.  
    13.     public List<PlayerAbility> abilitylist = new List<PlayerAbility>();
    14.  
    15. }

    Now my Idea is to create an " AbilityCastEventListener"(monobehavior) component, and add it to the Player.

    It will "listen" for abilities Events and trigger the event response of the corresponding ability.

    So I there will be a Custom function for the ability Dash where I put all the monobehavior code I need.
    This will mean I could to add new functions for new abilities I create, right?

    The power up are easy compared to this, Prefab with triggers, OnCollisionEnter will add the Aibility to the Player.

    Is all this correct?

    Thank you
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,752
    It certainly could be.

    Starting at future code ideas in a vacuum isn't really a thing.

    I appreciate that you've spent some time and effort thinking it out, but as the late great Helmuth von Moltke the Elder observed,

    "...no plan of operations extends with any certainty beyond the first contact with the main hostile force."

    Engineering interactive software necessarily is iterative. That is you write some stuff, try it, use it, expand it, find pain points and adjust as you go.

    You can also try out tutorials on this stuff to see other approaches, although feel free to take as little or as much as needed.

    The good news is that it is SOFTware, which means it is SOFT, which means you can refactor it at any time for relatively little cost or effort.

    In the end it has to work for your game idea, it has to be usable by you, it has to be fun for you to work in, otherwise... well, it won't ever be finished or fun.
     
    Munchy2007 likes this.