Skip to content

PlayerActions

Falko edited this page Feb 24, 2021 · 5 revisions

NOTE: This is outdated. New types have to be added in ActionStateType.cs, and the PlayerMenu changes are no longer necessary. The Wiki page should be updated at some point.

This page contains a generic description on how to implement player actions executed locally. In the following, we are assuming that we want to add a new player action X to the PlayerMenu:

New ActionState.Type

Create a new action-state value in ActionState.Type. Let's call this ActionState.X in the following.

        public enum Type
        {
            ...
            X,  // the user wants to do X
            ...
        }

New class for the player action

Create a new class for this action in the namespace SEE.Controls.Actions. Let's call this class XAction. Likely, it will derive from MonoBehaviour and be added to a game object as a component.

Name the action state triggering XAction

Add a constant declaration as follows to XAction:

const ActionState.Type ThisActionState = ActionState.Type.X;

This constant will determine whether the action is to be executed (see below).

Register delegate listing to ActionState.OnStateChanged

Register a delegate listening to ActionState.OnStateChanged. If XAction derives from MonoBehaviour, this could be done in the Start() method.

The delegate can be anonymous. It will be called upon every change of the ActionState, but quite likely whatever should be executed by XAction should be run only if the ActionState is ActionState.Type.X. ActionState will pass a parameter to the delegate that denotes the newly entered state. Thus, you will simply check this parameter whether anything needs to be done. If XAction derives from MonoBehaviour, it can be disabled so that Unity avoids unnecessary calls to Update().

Here is an example:

  private void Start()
  {
    ActionState.OnStateChanged += (ActionState.Type newState) =>
    {
        if (newState == ThisActionState)
        {
            // The monobehaviour is enabled and Update() will be called by Unity.
            enabled = true;
            <do whatever needs to be done for XAction>
        }
        else
        {
            // The monobehaviour is disabled and Update() no longer be called by Unity.
            enabled = false;
            <do whatever needs to be done when XAction is disabled>
        }
    };
    enabled = ActionState.Is(ThisActionState);
  }

Entry in PlayerMenu

In the class Assets/SEE/GameObjects/Menu/PlayerMenu.cs, there is a method CreateModeMenu(). In this method, there is an array named entries: Add your entry here as a new object of type ToggleMenuEntry. A short explanation of each parameter follows:

  • toggled: Whether the entry should be active on creation. This should only be true for one of the actions, so it's almost always correct to leave this false!
  • entryAction: What action to take when the entry is selected. This should set the action state to the selected entry's state, i.e. (written as a lambda expression) () => ActionState.Value = ActionState.Type.X, where X is your new action state type.
  • exitAction: What action to take when the entry is deselected. In most cases, this can be set to null.
  • title: The title of the entry.
  • description: A description of the entry. Should not be more than 3 lines of text. Not yet used in player menu.
  • entryColor: The color with which this entry shall be displayed. Not yet used in player menu.
  • icon: The icon which will be displayed alongside this entry. Not yet used in player menu.
  • enabled: Whether this entry should be enabled on creation. At the moment, disabled entries don't show up at all.

Example:

   ...
   new ToggleMenuEntry(
                active: true,
                entryAction: () => ActionState.Value = ActionState.Type.Move,
                exitAction: null,
                title: "Move",
                description: "Move a node within a graph",
                entryColor: Color.red.Darker(),
                icon: AssetDatabase.LoadAssetAtPath<Sprite>("Assets/Resources/Materials/Charts/MoveIcon.png")
            ),
   ...

Note on general interaction behaviour implemented in CircularMenu

Regarding the interaction to select a menu entry of the circular in-game menu: Beyond clicking on the disc representing the menu entry, the user can as well use the keyboard. By pressing a number key (any from 1 to 9) the corresponding menu entry indexed by this number will be selected. The interaction for this is implemented in CircularMenu.Update(). A developer does not need to make any adjustments here if she/he adds a new menu entry as this interaction will be handled generically. The order in which the menu descriptors are added in PlayerMenu.Start() determines the indices of the menu entries.