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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Combine one time button input and axis input into a shared ability-class?

Discussion in 'Scripting' started by Xarbrough, Jan 4, 2016.

  1. Xarbrough

    Xarbrough

    Joined:
    Dec 11, 2014
    Posts:
    1,184
    I was reading up on the command pattern here: http://gameprogrammingpatterns.com/command.html

    This design pattern works very well in Unity, for example by making each command a ScriptableObject, that can be edited by a designer and then in code in can all work well by assigning the base command class to any input delegate.

    However, I've run into a design problem when trying to consider all actions my player can take as a "command" or "ability". I can have an interface or abstract base class with a void Execute() method to trigger one-time shots like jump, fire and so on. Now I would also like to put my controller axis input into the same system, so that I can basically swap out if my player is moved by the float value of a joystick axis or by the input values from my AI or similar things.

    I've heard other developers talk about systems like that, but I seem to be unable to put both types of input under the same hat. Could anyone give me any pointers on how to put e.g. jumping and continuous movement under the same command class?

    My reasoning is, that my team at university is working on a local multiplayer game, that requires characters with many different skills and we would like to be able to scale up our project or make bigger changes fast, so I prefer a flexible data-driven design over hardcoding different things for movement and other abilities. Also, not trying to get everything done as fast as possible, but trying to learn how big project handle things, too.

    Thanks for any ideas!
     
  2. kietus

    kietus

    Joined:
    Jun 4, 2013
    Posts:
    54
    Hello,

    Interesting subject. I use a similar solution. well I'm not sure that's a good implementation, still testing it. I guess it can be improved.

    I use a base class for the "commands" (in my case Actions).
    Code (csharp):
    1.  
    2. public abstract class ActorAction{
    3. //[...]
    4.   public void Execute()
    5.   {
    6.     OnExecute();
    7.     OnActionExecuted(this);
    8.   }
    9.  
    10.   public void Execute<TParam>(TParam param)
    11.   {
    12.     OnExecute(param);
    13.     OnActionExecuted(this);
    14.   }
    15. }
    16.  
    17.  
    I'm not especially using the OnActionExecuted event currently, but that can be useful to follow/register all performed actions.
    The use of parameters is not so flexible as i need to write virtual methods for each case. I guess that's the downside
    Code (csharp):
    1.  
    2.   protected virtual void OnExecute()
    3.   {
    4.     throw new System.NotImplementedException();
    5.   }
    6.   protected virtual void OnExecute<TParam>(TParam param)
    7.   {
    8.     throw new System.NotImplementedException();
    9.   }
    10.  
    Example of implementation
    Code (csharp):
    1.  
    2.   public sealed class CutMiddleAA : ActorAction
    3.   {
    4.      protected override void OnExecute()
    5.      {
    6.        actor.Animator.SetInteger(Parameters.int_height, 0);
    7.        actor.Animator.SetTrigger(Parameters.trigger_attack);
    8.      }
    9.   }
    10.  
    If i need data related to the animation (like duration or whatever) i use a generic class :
    Code (csharp):
    1.  
    2. public abstract class ActorAction<TData> : ActorAction where TData : DataObject
    3.  
    TData is a base type for serialized data. I guess it can be scriptable object, xml, json, sql...

    That's my current solution, improvement/correction are welcome.