Player Movement Controller - Dungeon Movement

This page details what needs to be scripted to make a working Player movement controller for this project.

Overview

The Player Movement Controller - Dungeon Movement is the first piece of custom scripting needed for the project. With good player movement in place a lot of other aspects of design can be prototyped and refined.

There’s going to be two methods of movement. Although for now only Dungeon Movement needs to be implemented:

  1. Dungeon Movement: Input-Timed movement based on 1 input = 1 unit of movement.

  2. Town Movement: Free, continuous movement based on momentum over time. (Not relevant to this page.)

How it should play

Movement Basics:

  • The player character is near the middle of the screen, the camera follows them.

  • The dungeon is presented from a top down 2D perspective and the floor is broken up into visually clear to see square spaces.

  • Each of these square spaces is measured in-engine at 1 unity unit squared.

  • The player character navigates by moving in 4 directions from one square to the next: They can move UP, DOWN, LEFT, RIGHT.

  • 1 Player-made Input = 1 Unit of movement made

  • Movement is not continued if the input is held down.

  • If the player character encounters a collider in the projected direction they wish to move: No movement is made.

 

Rhythm Timing:

  • Like in the game Crypt of the Necrodancer, this game has a rhythm timing aspect to it.

  • A “True/False” Bool that switches on and off to the beat of the music will be handled by a playmaker state machine and the bool is exposed via a playmaker bool global variable.

  • This means the player doing actions like moving and attacking is checked against the beat of the music playing.

  • Any benefits or bonuses will be handled by different scripts or state machines.

Similar Examples from other games

Crypt of the Necrodancer

In this game there are four movement inputs that equate to UP, DOWN, LEFT, RIGHT, and each press of the input moves the character one space.

The player controller for Dungeon Movement in this game is almost identical. The differences lay in what happens when the player successfully or fails to move to the beat.

However: Our game is going to be more forgiving then Necrodancer from a design sense in that:

  • Failing to match the beat to movement input incurs no penalties.

  • Successfully match the beat to movement input rewards a bonus.

    • That bonus will be determined through other scripts / playmaker state machines.

VIdeo Link

Deliverables

Dungeon Movement Component Script:

  • This script should work as a “Component” in unity. Meaning it’ll be attached to an Object in the Hierarchy. Most likely somewhere in the player character object.

  • Similar to Unity's “Character Controller” Component.

Integrations:

  • Integration with Playmaker: The Unity Package “Playmaker” has its own “Global Variables” list that can be used across multiple state machines. These will be used as triggers for matching up the beat of the music to the players input.

    • Example: There may be a global variable bool called “On Beat?” - If the player moves while the variable is set to true then it’s considered a successful rhythm timing.

  • Integration with Unity animator variables: Unity can use “Animation variables” like: Int, Float, Bool, & Trigger - This player movement script should be able to communicate with the ones it’s told to.

What the Playmaker Global Variables Window Looks like.

What the animator “Parameters” looks like when it has triggers in it.

 

How Collision works

  • The Character, enemies, objects in the dungeon and walls will be assigned Polygon Collider 2Ds.

  • The script should check to see if it registers a polygon collider 2D in the square it’s trying to move into.

    • If it does detect one It wont move the character forward into it.

    • If it detects no colliders, it’ll move the player into the square.

Interacting with Objects in the world

The player can interact with objects such as Chests, Enemies and Prisoners.

For the player to interact directly with an object, three things need to be true:

  1. They are standing 1 unity unit or less next to it. (Visually the character is standing one square beside the object.

  2. They are pressing down a movement direction button in the correct direction of the object. (They wont move due to the collision rules being abided.)

  3. They have also pressed the “Action Button 1” input. (eg: Hitting spacebar.) at the same time.

When all three conditions are met then the player character will spawn an invisible trigger volume with the space of the object for an amount of time.

This trigger volume will be detected by whatever playmaker state machine or script is attached to the object in that space and count it as a successful interaction.

That objects state machine will then take on the responsibilities for the rest of the interaction right up until player control is returned to the player.

Some examples:

  • If it was a chest. The character would animate opening a chest and collecting loot.

  • If it was an enemy. The character would animate attacking it and entering into a battle sequence.

  • If it was a doorway. The character would animate entering into the doorway.

On Beat Check:

A “On Beat” Check will also be made to see if the interaction was done to the beat of the music. If it is that triggers a global variable true bool that may incur some bonuses for the player.

 

Disable Dungeon Movement Control

There are multiple times when Dungeon Movement needs to be disabled. Such as when the player is in a battle sequence or trying to solve a puzzle on screen. Possibly even cutscenes.

Disabling player movement will be determined by a Playmaker Global Variable Bool.

The dungeon movement scripts job is to detect the state of the bool and act accordingly:

  • Detects False: Player Movement and object interaction is permitted.

  • Detects True: Player Movement and object interaction is Disabled.

This does not disable the keyboard inputs from the game as they’ll be used in UI Screens, enemy encounters, and puzzles. It just stops the player character moving or triggering any more interactions from the dungeon until the variable is set to false again.

 

Exposed Variables

The following variables for the component script should be exposed in the unity Inspector window to allow some customization and design tuning.

 

Similar to as seen here for the sprite renderer component. Variables are available to the designer:

 

Variable Name

Variable type

Playmaker or Animator Integration?

Description

Default Variable Setting:

Variable Name

Variable type

Playmaker or Animator Integration?

Description

Default Variable Setting:

Movement UP

Keyboard Input

 

The input needed to move up. (+Y)

W

Movement DOWN

Keyboard Input

 

The input needed to move down. (-Y)

S

Movement LEFT

Keyboard Input

 

The input needed to move left. (-X)

A

Movement RIGHT

Keyboard Input

 

The input needed to move Right. (+X)

D

Action Button 1

Keyboard Input

 

The input needed to count an action.

Action button 1 will be the games main “Context Sensitive” button. In that it accounts for opening chests, engaging in battles, etc.

Spacebar

Movement Distance

Float

 

The distance in unity units the player moves per successful input

1

Movement Time

Float

 

The time in seconds it takes for the player character to physically move from the initial location to the destination location.

Setting to -1 will equate to instant movement.

0.1

Next Movement Delay

Float

 

The time in seconds that the player has to wait until another movement input will register and send off checks.

Setting to -1 will equate to no delay

0.1

Next Action Delay

Float

 

The time in seconds that the player has to wait until they can perform another action after completing one.

Setting to -1 will equate to no delay

0.1

Playmaker Integrations:

 

 

 

 

On Beat Check

Bool Name

Playmaker global variable

The name of the playmaker global variable bool that it checks to see if the input was made “On Beat”

The true / false state of this variable is determined external to this script.

On Beat?

On Beat Move Success

Bool Name

Playmaker global variable

The name of the playmaker global variable bool this script sets to true if the “On Beat Check” comes back as true on a movement input.

A playmaker state machine will check for the true change and then reset it back to false after an amount of time.

On Beat Move Success

On Beat Interaction Success

Bool Name

Playmaker global variable

The name of the playmaker global variable bool this script sets to true if the “On Beat Check” comes back as true on a object interaction input.

A playmaker state machine will check for the true change and then reset it back to false after an amount of time.

On Beat Interaction Success

Movement Disabled

Bool Name

Playmaker global variable

The name of the playmaker global variable this script checks to see if it needs to disable movement.

The script should be making this check quite often.

Move Disabled?

Unity Animator Integrations:

 

 

 

 

Animator Component Location

Object Path

 

The path location of the object that has the character “animator” component attached to it.

(None)

Movement Animator Name

Trigger (Animator) Name

Animator

The name of the animator trigger variable it triggers when a successful movement is made.

Character Move

On Beat Move Animator Name

Trigger (Animator) Name

Animator

The name of the animator trigger variable that it triggers when a movement is made “On Beat”

Character On Beat

No Movement Animator Name

Trigger (Animator) Name

Animator

The name of the animator trigger variable that it triggers when an input resulted in no movement.

Character No Movement

 

Player Controller Update: Written 26th of July - 2021

As development has continued some extra functionality is needed to integrate the player controller with new variables and playmaker state machine triggers.

Stamina Integration:

Stamina is the INT-based resource that’s spent when the player character attacks or interacts with the world and it’s entities.

 

It’s now also a resource that sits at a Maximum until player inputted interactions “Drain” the resource.

It’s then replenished over-time by recharging itself.

There now exists the situation where attacks and interactions with the world shouldn’t happen if the stamina cost is more then the amount of stamina available.

 

New functionality needed:

Lowest Stamina Interaction Cost:

1: The player movement controller Script needs to be aware of the playmaker INT global variable “Player Stamina”

2: The Player Movement Controller Script needs to deny the “Interact” input (In the input manager) if the player stamina amount is below a pre-determined INT amount.

Meaning: The player cannot attack if there’s not enough stamina to pay for the attack.

3: The said pre-determined amount should be a tweakable INT number in the inspector. Named “Lowest Stamina Interact Cost”

Example: If the “Lowest Stamina Interact Cost” is set to 4. Then the player can’t attack if the amount of “Player Stamina” is 3 when the Interact input is made.

 

Stunned disables Interact Input:

1: I’ve created a “Stunned” state that occurs for a time after the player character gets hit by an enemy.

This is handled in the playmaker FSM object: “Logic - Stunned Logic”

2: When the player character is stunned a playmaker global bool called “Player Stunned” is set to “True”

3: When this playmaker global bool is true I’d like the “interact” input to be disabled.

Meaning: If the player character is stunned, then they cant attack until the bool is back to “False”

 

 

New Animator Variable Settings in Inspector:

The following are additional “Animator Variable Settings” that need to be exposed in the inspector

Animator Character Attack

If the player inputs the “interact” input successfully.

  • Note: I’m currently faking this via the playmaker FSM object “Logic - Attack Sprite Animation”.
    I’d delete the playmaker logic out once it’s part of the player controller.

  • I’d delete it because it currently has no way of knowing if an attack is valid to do. So it just does it everytime.

 

Animator Character Attack Failed

This should trigger If the player inputs the “Interact” input but doesn’t have the stamina to pay for it or if the player is currently stunned.