Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Question Creating lookup tables that can be assigned in the inspector.

Discussion in 'Scripting' started by brandonhasasmurf, Aug 6, 2020.

  1. brandonhasasmurf

    brandonhasasmurf

    Joined:
    May 20, 2020
    Posts:
    2
    Hello! I'm still pretty new to C#, coming from C++. I'm working on a spell casting game demo, where the user can craft their own spell. The player can choose from a list on how their spell will function, such as what kind of spell it is (fire, water, etc.), what kind of path it'll take, and the spell's hitbox.

    The way I decided to balance it was make each factor affect the overall spell's functionality with multipliers. Right now, I've decided on it affecting the damage, speed, and mana cost. How I decided to define those multipliers? Right now, I just have a file with 3 static arrays which define those multiplier values for damage, speed, and mana cost for each factor of the spell, and just pull from it when I need it. I guess this is a lookup table.
    It's like such
    Code (CSharp):
    1. public class SpellConstants
    2. {
    3.  
    4.     public static readonly float[] MediumMultipliers =
    5.     {
    6.         //Could use a struct here instead but I'm fine working with this.
    7.         //Damage    //Speed     //ManaCost
    8.  
    9.         0.0f,       0.0f,       0.0f,       //NONE
    10.         1.0f,       1.0f,       1.0f,       //Fire
    11.         0.8f,       1.2f,       1.0f,       //Water
    12. ...
    And this is how I would assign the stats to a spell

    Code (CSharp):
    1.     public void setStats()
    2.     {
    3.        //mediums, means, and mod are enums defined above.
    4.         int mediumIndex = (int)components.medium;
    5.         int meansIndex = (int)components.means;
    6.         int modIndex = (int)components.mod;
    7.  
    8.  
    9.         damage = 8.0f
    10.                 * SpellConstants.MediumMultipliers[3*mediumIndex]
    11.                 * SpellConstants.MeansMultipliers [3*meansIndex]
    12.                 * SpellConstants.ModMultipliers[3*modIndex];
    13.  
    14.         speed = 8.0f
    15.                 * SpellConstants.MediumMultipliers[3*mediumIndex + 1]
    16.                 * SpellConstants.MeansMultipliers [3*meansIndex + 1]
    17.                 * SpellConstants.ModMultipliers[3*modIndex + 1];
    18.  
    19.         manacost = 8.0f
    20.                 * SpellConstants.MediumMultipliers[3*mediumIndex + 2]
    21.                 * SpellConstants.MeansMultipliers [3*meansIndex + 2]
    22.                 * SpellConstants.ModMultipliers[3*modIndex + 2];
    23.     }
    This spell (Not a component just a class) is passed to a GameObject with a CastedSpell component, which handles moving the projectile, collision, and passing the damage, etc.

    This works really well for me with floats. The path it takes is also an array, but of child classes of a base class, which affects how a spell will move, which functions as expected.

    Code (CSharp):
    1. public static readonly SpellMeans[] SpellMeansObjects =
    2.     {
    3.         null,            // NONE,
    4.         new SpellMeans_Normal(),       // Standard,
    5.         new SpellMeans_Arched(),        // Arced,
    ...

    And this is passed to the GameObject similarly.

    However, now I'm trying to make the game look nice with materials and shaders. The "medium" (again fire, water) would most likely be the only thing determining what material to assign to the spell. However, doing what I did above with the array, but with materials, just sounds bad and messy to me. Ideally, I'd like to assign these in the inspector (and possibly all these arrays), while keeping the easy way of grabbing these values.

    How could I go about restructuring how this is done to get the functionality I want from it? I'm really overthinking this and just need a push in the right direction.

    Thank you!
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    39,015
    This looks like a job tailor made for ScriptableObjects!

    ScriptableObjects are basically structured blobs of predefined data to help you create content for your game.

    For instance if I had a ScriptableObject called Weapon, it might have these properties:

    - name
    - detailed name
    - description
    - damage
    - toughness
    - weight
    - what it looks like in the inventory
    - what model it uses in game
    - what animations the player uses to swing it

    I would create many of these Weapons, each one a file on disk (also called an "asset"), with different properties. I might have Sword, Longsword, Shortword, Dagger, Knife, etc.

    Could also break it into EdgedWeapons and RangedWeapons for instance.

    And tell you what, just because it's a Wednesday night, I am giving away a brand-new ScriptableObject just for you:

    Code (csharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. [CreateAssetMenu]
    6. public class MeleeWeapon : ScriptableObject
    7. {
    8.     public string Description;    // such as "Longsword"
    9.  
    10.     // how much it deals per hit
    11.     public int damage;            // such as 4hp
    12.  
    13.     // or perhaps:
    14.     public string damageDice;    // such as 2d6+4
    15.  
    16.     public Sprite inventorySprite;
    17.  
    18.     public GameObject Prefab;    // what gets attached to the player's hand
    19.  
    20.     // add any other attributes here... magic, durability, weight, etc
    21.     // level requirements, attack speed, etc.
    22. }
    Make a script called MeleeWeapon.cs and stick the above code into it.

    When Unity finishes compiling, make a folder and then inside that folder right-click and Create -> Melee Weapon.

    Congratulations, you just made your first ScriptableObject, fully editable in Unity. Now go nuts!
     
    yotingo likes this.
  3. yotingo

    yotingo

    Joined:
    Jul 10, 2013
    Posts:
    44
    I know this was just for him... :D -but I might use it too.
    It's a great straightforward example.
    Thanks!
     
    Kurt-Dekker likes this.