Search Unity

Custom inspector - damage formula

Discussion in 'Scripting' started by henmachuca, Mar 5, 2018.

  1. henmachuca

    henmachuca

    Joined:
    Oct 14, 2016
    Posts:
    105
    Hello,

    Im creating a project in unity but as I prototype the abilities I ran into the issue that I would like to calculate the damage of a certain ability using dice notations and other parameters like the player stats for example.
    As of now I have to do it in code, but I would like to set this kind of thing in the inspector.
    Can I get some suggestions or references of how should I approach this?

    Thank you.
     
  2. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,195
    I'm not sure all the functionality you'd want to include here, but here's an example of how you might approach this. There are two files: A ScritableObject, and a custom Inspector for it. After you add the classes, the "Create" menu in Unity will contain a menu for "MyGame -> PlayerStats". (The Create menu is either in the Project window, or you can find it by right-clicking in a project directory). This will create a PlayerStats asset you can pass into other scripts.

    The PlayerStats script is simple:

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. [CreateAssetMenu(menuName = "MyGame/Player Stats")]
    4. public class PlayerStats : ScriptableObject
    5. {
    6.     [Range(3, 25)]
    7.     public int Strength;
    8.     [Range(3, 25)]
    9.     public int Stamina;
    10.     [Range(3, 25)]
    11.     public int Intelligence;
    12. }
    13.  
    The PlayerStatsEditor is a little messier, but it does kind of what you seem to want to do. There's a button to randomize the stats. This "rolls" N-sided dice M times, and assigns the values back to the PlayerStats object.

    Code (CSharp):
    1. using UnityEditor;
    2. using UnityEngine;
    3.  
    4. [CustomEditor(typeof(PlayerStats), true)]
    5. public class PlayerStatsEditor : UnityEditor.Editor
    6. {
    7.     private int numberOfDice;
    8.     private int numberOfSides;
    9.     public override void OnInspectorGUI()
    10.     {
    11.         DrawDefaultInspector();
    12.  
    13.         Rect position = GUILayoutUtility.GetLastRect();
    14.         position = new Rect(position.x, position.y + 30, position.width, position.height);
    15.         numberOfDice = EditorGUI.IntSlider(position, new GUIContent("Number of Dice"), numberOfDice, 1, 5);
    16.  
    17.         position = new Rect(position.x, position.y + 30, position.width, position.height);
    18.         var sideLabels = new GUIContent[] { new GUIContent("4"), new GUIContent("6"), new GUIContent("8"), new GUIContent("10"), new GUIContent("12") };
    19.         var sideOptions = new int[] { 4, 6, 8, 10, 12 };
    20.         numberOfSides = EditorGUI.IntPopup(position, new GUIContent("Number of Sides"), numberOfSides, sideLabels, sideOptions);
    21.  
    22.         GUILayout.Space(80);
    23.  
    24.         if (GUILayout.Button("Randomize Stats"))
    25.         {
    26.          
    27.  
    28.             ((PlayerStats)serializedObject.targetObject).Strength = RandomStat(numberOfDice, numberOfSides);
    29.             ((PlayerStats)serializedObject.targetObject).Stamina = RandomStat(numberOfDice, numberOfSides);
    30.             ((PlayerStats)serializedObject.targetObject).Intelligence = RandomStat(numberOfDice, numberOfSides);
    31.  
    32.             EditorUtility.SetDirty(((PlayerStats)serializedObject.targetObject));
    33.         }
    34.  
    35.  
    36.     }
    37.  
    38.     private int RandomStat(int numberOfDice, int dieSides)
    39.     {
    40.         Debug.Log(string.Format("Rolling {0} {1}-sided dice", numberOfDice, dieSides));
    41.         int sum = 0;
    42.         for (var i = 0; i < numberOfDice; i++)
    43.         {
    44.             sum += UnityEngine.Random.Range(0, dieSides);
    45.         }
    46.         return sum;
    47.     }
    48. }
    49.  


    Maybe that's a place to start. You could make the Editor more complex, assigning buttons for each stat individually.
     
  3. henmachuca

    henmachuca

    Joined:
    Oct 14, 2016
    Posts:
    105
    Thank you @dgoyette, but in the case you mentioned the damage is calculated totally randomized.
    What if I wanted for example to have the player spell damage to be calculated by:

    ((1d10+15+self.int/10)*self.firePower/target.resistance_fire)

    Any ideas on how to implement something like it?
     
  4. eisenpony

    eisenpony

    Joined:
    May 8, 2015
    Posts:
    974
    What you're asking for requires interpretation. You can create a custom language and parse it with your own implementation of an interpreter, or you might be able to use a LUA script parser.

    For LUA, there are plenty of examples online and I believe the asset store has at least one free one.

    Either way, the field in the editor needs to be a string. Then you feed that string into an interpreter to create code which can calculate the given formula.