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

Question Best way to dynamically call functions in Unity?

Discussion in 'Scripting' started by jas131072, Oct 20, 2022.

  1. jas131072

    jas131072

    Joined:
    Oct 19, 2018
    Posts:
    2
    I'm making a 2D fighter and have an issue with programming hitboxes for the game. The player is made up of a finite state machine with a list of actions the player can be doing. They have a State which keeps track of things like their position and health.

    Each action has a list of hitbox data which defines how and when the hitboxes are active, their size which bone they are currently attached to, etc. When the hitbox collides with an opponent, an INTERACTION_STATE is determined based on the opponent's action/input.

    Based on which interaction state is determined, I wanted to define some kind of list of events that are executed by the hitbox. For example:

    if interaction == INTERACTION_STATE.ON_HIT:
    TakeDamage(50);
    SetVelocity(new Vector3(8f, 3f, 0f));
    SetAction(ACTION.HURT)

    But if they blocked the attack, it could deal no damage and cause a different state:
    if interaction == INTERACTION_STATE.BLOCKED:
    SetVelocity(new Vector3(2f, 1f, 0f));
    SetAction(ACTION.BLOCK)
    AddGauge(25)

    As you can see, the list of actions is pretty different. No TakeDamage is used and the opponent's gauge increases.

    The trouble is, I'm having trouble figuring out how to define a list of events dynamically. I'm not sure what the best way to go about it is. This problem may be better illustrated throuch code:

    Code (CSharp):
    1. public class PlayerStateScript : MonoBehaviour
    2. {
    3.     public List<Action> playerActions;
    4.     public Action currentAction;
    5.     public State currentState;
    6.  
    7.     public void TakeDamage(int amount)
    8.     {
    9.         currentState.health -= amount;
    10.     }
    11.  
    12.     public void SetVelocity(Vector3 amount)
    13.     {
    14.         currentState.velocity = amount;
    15.     }
    16.  
    17.     public void AddGauge(float amount)
    18.     {
    19.         currentState.gauge += amount;
    20.     }
    21.  
    22.     public void SetAction(Action newAction)
    23.     {
    24.         currentAction = newAction;
    25.     }
    26. }
    27.  
    28. public class Action
    29. {
    30.     public string animationName;
    31.     public int frameIndex;
    32.     public List<HitboxData> hitboxData;
    33. }
    34.  
    35. public class State
    36. {
    37.     public int health;
    38.     public float gauge;
    39.     public Vector3 position;
    40.     public Vector3 velocity;
    41. }
    42.  
    43. public class HitboxData
    44. {
    45.     public Transform transformReference;
    46.     public float activeFrom;
    47.     public float activeUntil;
    48.     public Vector3 hitboxSize;
    49.     public /*???? this is where I get stuck*/ thingsToDoOnHit;
    50.     public /*???? this is where I get stuck*/ thingsToDoOnBlock;
    51.     public /*???? this is where I get stuck*/ thingsToDoOnCountered;
    52.  
    53.     OnHit(PlayerStateScript other)
    54.     {
    55.         foreach (thing in thingsToDoOnHit)
    56.         {
    57.             other.DoTheThing();
    58.         }
    59.     }
    60. }
    (this is psuedocode)

    The question is; how do I link the 'thingsToDoOnHit' etc. to the functions from the player? I figured that, in the long run, doing it this way would be more readable than having a huge list of things ie. "damageOnHit, velocityOnHit, changeStateOnHit, damageOnBlock... ad nauseum". I've been looking around online for solutions implementing Invoke events, delegates, UnityEvents.. etc. But I'm pretty new to Unity and unsure which is the best to implement.

    Has anyone run into a similar issue and what solution did you implement? I'm sorry, this is also my first time posting to the Unity Forum, thanks for having me
     
  2. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
    I don't think it's possible to do with a single delegate or UnityEvents because every receiver has a different parameter. Could you not simply push the calls up to the player and have your logic there? I'm not sure why every hitbox would need to define exactly what happens on contact.
     
  3. jas131072

    jas131072

    Joined:
    Oct 19, 2018
    Posts:
    2
    Thanks for your reply, I've progressed quite a bit with my project since then but thanks for answering.

    I'm just going to make a struct which contains lists of all the events that can happen in my game (so the takeDamage, setVelocity etc.). Then when I make at hitbox, I'll just add the events that I want to the list, and then apply them when they hit the player.