Player Mechanics

 

Home

Before designing the player mechanics for the main character we had to work out how he would move, what kind of person he is, how he interacts with the world around him and the theme of the game. 

With this knowledge I could paint a good picture of his abilities, strengths and weaknesses. The main character is a human detective caught up in a web of suspicious cases in a carnival with murderous killer clowns roaming around so I thought that realistic movements, sprinting, jumping and crouching would add to the fear in the game as it makes you believe you are that player with the same physics but in an uncanny world.

He would have to be able to inflict damage and take damage from the killers or else you lose the purpose to run, hide or fight and would make for a pretty boring game. The player can sprint away from the killers easily so to make it more challenging I implemented a stamina bar that depletes when sprinting and when the bar runs out the player has to wait for it to refill while only being able to move at a walking speed as he gets his breath back. If he gets hurt by a killer, trap or puzzle he can pick up a health drop.

As a detective it would make sense that he would wield a side arm for his protection since he is a veteran and gets the most dangerous jobs. Added a gun mechanic increased the playability and gave the player another option than running away. If he had no ammo count on screen it would make the game feel more arcade like with infinite bullets so added ammo pickups to balance this. He can stun the killer which gives him 10 seconds to get away but can never kill them as they are undead. Because the game is set in an old dark carnival he needed a flashlight which would help him see but also be true to the character of a detective.

Player Mechanics Showcase

Movement

In the "Movement" script sprint, crouch and jump are controlled.
MovementScript1.jpg

Jumping changes the players vertical velocity by the jump height times negative gravity times 2.
"OnJumpPressed()", "OnCrouchPressed()" and "OnSprintPressed()" are all called when their key is pressed with the new input system.
MovementScript2.jpg
MovementScript3.jpg

Implemented 2 IEnumerator methods to refill stamina and hide stamina bar after 2 seconds of not sprinting.
Screenshot 2021-12-15 150405.jpg

I used Unity's 'Slider' component which has some properties like maxValue ready made.
"UseStamina" method decreases the current stamina value and updates the stamina bar value to that until zero value.
Screenshot 2021-12-15 152229.jpg

The stamina bar will decreases while sprinting and automatically refills until full while you can't sprint until refilled.
The bar disappears after 2 seconds of not sprinting so it doesn't obstruct the players view. 
Screenshot (263).png

Gun

The Gun Class is a component of the Player object so takes in the gun object reference "gun". From here all actions of the gun are called from game events to sound. 
Screenshot 2022-03-14 162208.png

"Equip" is called when the user hits the 'G' key, if it is equipped then it will unequip and vice versa.
Screenshot 2022-03-14 162334.png.1

When the user left clicks the mouse button the "Shoot" method is called in the "Gun" Class.
If the hit object has a "Damageable" script component then it can be shot and take damage.
One bullet is taken away along with one HP from the killer. 
If the killers HP reaches zero then "stunKiller" event is raised, which stuns him for a few seconds.
Then set the killers HP back to max HP so he can be stunned again.
Screenshot 2022-03-14 164046.png.1

Attached to each killer is an event listener that listens for the stun event to be raised, then calls the "StunKiller" method from the killers "Patrol" script which changes his state to "stunned" and plays the stun animation along with sounds.
Screenshot 2022-03-14 165837.png

Player shooting mechanic in action - shooting a dummy object to test the bullet impact effects.
Capture.PNG

Flashlight

The flashlight is an important item in the game, allowing the player to see where he is walking and find clues.

The "FlashLight" script is a component of player object so the flashlight object is "lightSource".
When the key "F" is pressed, "Use()" is called and if it is enabled it will be disabled and vice versa.
Screenshot 2022-03-14 172818.png

Screenshot (235).png

Scriptable Objects

The player mechanic systems I made rely heavily on Scriptable Objects explained in full on the Unity docs website here. Basically they are an asset and can save duplication of data when a prefab is instantiated because instead of have a variable created on each prefab you can make a SO of the variable and share it among them all also saving memory. It is a data container that can save large amounts of data independent of Class instances. If you change the value of a SO in the editor while the game is running the value will stay the same when the game stops so it makes it easier for testing.

I use Scriptable Objects to store any data that will need to communicate across different systems like player HP. When the players health reaches zero a lot of systems will need to happen like display a cutscene, play a death sound or reset some items so instead of using public methods or lots of events, just drag the SO data into each system once and when a change happens to HP all will be updated automatically.

To be able to create an asset you must include "CreateAssetMenu" and your chosen filename and menu name.
I called the Class "PlayerHPSO" and inherited from "NumberVariableSO" which just holds the generic value of the variable you choose to use, I chose "int" and inherits from "ScriptableObject" instead of "MonoBehaviour" like normal Unity scripts.
There is a max health value that can be seen by any script with the data asset attached.
Then there are two simple methods to add and subtract the HP if the player picks up health or gets damaged.
Screenshot 2022-03-15 121929.png.1

To make a data asset for player HP, right-click on any folder in the Project window, I chose the Player folder, then click "Create", "Scriptable Objects", "Player" and finally "PlayerHPSO" which is the SO Class above.
Screenshot333333.png

I added a "PlayerHPSO" reference into the "Player Pickup Behavior" script.
Screenshot 2022-03-15 134229.png

I added a "PlayerHPSO" reference into the "Inventory Manager" script.
Screenshot 2022-03-15 134048.png

Then I dragged and dropped the "PlayerHPSO" data asset into the "Player Pickup Behavior" script. Now I can use this data to check if the players health is not full so he can pick up health.
Screenshot 2022-03-15 133356.png

I dragged and dropped the "PlayerHPSO" data asset into the "Inventory Manager" script. Now I can add or subtract health depending on a health pickup or a trap and query how much health he has to know which health UI icon to display on screen.
Screenshot 2022-03-15 133833.png


Custom Events and Listeners

To make it easier sending any kind of event with or without parameters, I made a custom event and event listener.

Started off making an interface that can take any data type as a parameter with a method "OnEventRaised" that must be implemented by any Class inheriting from this Class.
Screenshot 2022-03-15 142213.png

The event listener takes in 3 parameters, the first one can be any data type like an "int", the second must be a "BaseGameEventSO<P>", the third must be a "UnityEvent<P>" and all must take the same data type as a parameter.
When the listener is enabled the game event is checked if it is null by the "?" after "GameEvent", then "RegisterListener(this)" is called from it which adds this event listener to it's list of listeners because one game event can have multiple listeners.
When "OnDisable()" is called the game event removes this event listener from it's list of event listeners.
"OnEventRaised(P parameters)" method creates a unity response in the editor that events and unity methods can be dropped into.
Screenshot 2022-03-15 143140.png

The game event must be inherited from with your own concrete data type parameter and is inherited from ScriptableObject.
It has a list of "IGameEventListener<P>" called "listeners" which holds all the event listeners listening to this game event.
When "Raise" is called, the method attached to the listener is called.
Screenshot 2022-03-15 142101.png

Pickups

The player can pick up certain items by colliding with them such as health and ammo.



Screenshot 2022-03-15 104744.png


Screenshot 2022-03-15 112611.png



Screenshot 2022-03-15 115810.png

Screenshot 2022-03-15 115401.png



Screenshot 2022-03-15 112126.png


Screenshot 2022-03-15 111938.png

Screenshot 2022-03-15 113250.png


Screenshot 2022-03-15 114434.png

  • A blood splatter effect shows on screen when damage is taken from any damageable object with the alpha value increasing for each event.
                                  wrrxE-.gif

    Blood splatter alpha decreases for each damage event and disappears once the heart is full again.
                                  nuRs-P.gif