Search Unity

Fetch variable from a variable component?

Discussion in 'Scripting' started by LordMidoo, Jan 23, 2020.

  1. LordMidoo

    LordMidoo

    Joined:
    Jan 23, 2020
    Posts:
    1
    I'm making an RPG with a traditional spellbar. It parents 12 buttons and each of them has the spell_handler component which basically detects clicks and defines which spell script each of them holds. spell_handler is supposed to load a different spell icon for each slot that has a spell assigned to it, and to do so it has to fetch the sprite variable from the spell's personal script.

    I have 3 sample spells: Fireball, Minor Heal and Holy Shield, each of them has its own script (Fireball.cs, MinorHeal.cs, HolyShield.cs). I used switch at first to manually assign a different script depending on which enum the button has but I realized once I start expanding the game and having 80+ different spells I wouldn't want to keep track of all those different cases.

    So instead I tell the code to add a different component depending on the .GetType() of the enum (as scripts have the same names as the enums) and get the sprite value from that. But now Unity starts complaining that "Component" does not contain a definition for "sprite". I know why it's complaining, because it's supposed to get its variables from its components before runtime and I don't expect it to just "leap of faith" itself into whatever variable "will" be assigned to it.

    I'm wondering, how could I fix my code so Unity knows to fetch a different sprite from a variable component? Or should I just bite the towel and write 400+ lines of switch case case case or my spell handler?

    Code (csharp):
    1.  
    2. using System;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5. using UnityEngine;
    6. using UnityEngine.UI;
    7.  
    8. public enum SpellToUse
    9. {
    10.     EMPTY,
    11.     Fireball,
    12.     MinorHeal,
    13.     HolyShield,
    14. }
    15. public class spell_handler : MonoBehaviour {
    16.    
    17.     public SpellToUse spell;
    18.     private Component spellScript;
    19.     void Awake()
    20.     {
    21.         Sprite icon;
    22.         if (spell != SpellToUse.EMPTY){
    23.            gameObject.AddComponent(spell.GetType());
    24.            spellScript = GetComponent(spell.GetType());
    25.            icon = spellScript.sprite;
    26.            GetComponent<Button>().image.sprite = icon;
    27.        }
    28.        GetComponent<Button>().onClick.AddListener(OnClick);
    29.     }
    30. }
    31.  
     
  2. csofranz

    csofranz

    Joined:
    Apr 29, 2017
    Posts:
    1,556
    Huh. Isn't this the poster child case for an object-oriented Approach?

    Define a
    Code (CSharp):
    1. class spell : Monobehaviour {...}
    that defines all handlers (e.g. 'cast'), cooldown, UI etc, and then subclass further down to more specific, like

    Code (CSharp):
    1. class attackSpell : spell {}
    untill you finally come to the spell you want, e.g.

    Code (CSharp):
    1. class meteorStrike : fireBall // a Meteor strike is a more powerful AOE Version of FIREBALL
    2. {}
    ... and I'm sure Proponents of scriptable objects will now pipe up to tell you that this is the classic poster child case for scriptable objects.

    That way all your UI elements are simply an Array of spell, and you invoke their cast() method (or whatever you would want to invoke when someone clicks onto it)