Enemies / Interactions


Enemy Implementation:

The concept of the enemy ghost was to have a harmless looking idle state that transforms into a horrifying creature that pursues the player when they get near. For this, I created a sprite sheet that included the idle state, transforming state and pursuing left and right states. 


Enemy Ghost sprite sheet created by me in Microsoft Paint. 


With this sprite sheet I created the animations and a new prefab for the enemy ghost. This prefab includes the following components: Transform, Sprite Renderer, Rigidbody2D,  BoxCollider2D, Animator, Audio Source, and a pursue script. The following state machine was implemented for the animator component, with the transitions between idle and transform+ and between pursue and transform- being triggered by the Boolean parameter "transform",  which reads true when the player is within a certain radius of the enemy ghost, and false otherwise. The other transitions have an exit time, as their purpose is to play the transforming animations. The pursue state has a blend tree so that the ghost can have both left and right animations. The parameter that controls this is a float labelled "ghostDirection".

Enemy ghost state machine. 


The enemy ghost has the tag "Death", meaning that it works with the script attached to the player that controls the player's spawn. This way the ghost is treated the same as any other hazard such as a spike, instantly killing the player and respawning them at the last checkpoint. The pursuit script attached to the enemy ghost uses the Vector2.Distance() method to calculate the distance between the ghost's position and the player's position. If this value is below a specified distance (which can be changed in the Unity Inspector), then the transform parameter in the animator is set to true and the x position of the ghost is changed using the Vector2.MoveTowards() method, which moves the ghost towards the player at a specified speed (which can be edited in the unity inspector). The y and z position of the ghost remains unchanged so that it only moves horizontally. The level design utilises this by adding barriers to the left and right of the enemy ghosts so that they are contained in a restricted area. This makes for interesting gameplay, and will be very effective when collectible items are added to the game, as the ghosts can guard these treasures. 

The "ghostDirection" parameter in the pursue blend tree is set based on the result of subtracting the current x position of the ghost from the current x position of the player, which is calculated every frame. If the result is negative then the ghost is facing left, and if the result is positive then the ghost is facing right. To add to the tension of being pursued by the ghost, the script causes the game's music to become very quiet and a loud horror drone is played to simulate the ghost's screams. When the distance between the player and the ghost becomes greater than the specified amount, the transform parameter in the animator is set to false and the ghost stops pursuing the player, along with music returning to its normal volume and the ghost screams ceasing to play. 

Although the implementation of the ghost is effective by using the Vector2.Distance() method, it is flawed due to the fact that it doesn't account for walls or other barriers between it and the player. This means that the ghost will follow the player when they are in a different room, or obscured by a wall. This can be improved by using ray casts, which can fire in the direction of the player when the distance between the player and the ghost falls below the specified threshold. The ray cast can then determine if there are any walls or barriers between the player and ghost. If there are no barriers, then the pursuit action can be set. An alternative to the Vector2.Distance() method would be to use the Physics2D.OverlapCircleAll() method, which returns a list of all the colliders within a circle of a set radius. This could be coded so that it triggers the pursuit action when the player collider is detected. This would work perfectly fine, but the Vector2.Distance() method was selected due to its simplicity. 



Ghost pursuit functionality. 

Testing:

Updates from Previous Feedback:

From feedback in previous weeks, the following improvements have been made:

- Spaces between the background tiles have been removed by disabling anti-aliasing and adjusting the tile map sprite sheet. Although this fixed the issue, it slightly compressed the level in both the x and y directions, so certain areas of the level had to be redrawn.

- Downward force on the player has been increased after jumping so that they fall faster. This has made the platforming feel much more responsive and less floaty. 

- 'Death' colliders have been added under open drops so that the player doesn't infinitely fall. 


Feedback / Testing for current build:

For the current build I have received the following feedback from those who played it:


1. Enemy ghost tracks player through walls.  

As discussed earlier, I aim to fix this by using ray casts to determine whether the player is obstructed by a wall or barrier. The ray cast will fire off when the player is within the pursuit range of the ghost. 


2. Player character needs more effects to reflect the player actions. 

I have made improvements to the player character to address this issue by adding sound effects for running, jumping, landing and parachuting. These were very straight forward to add to the player movement script. I also created a particle effect as a child of the player that creates a small dust cloud when they jump and land. The simulation space is set to world so that it behaves realistically. This effect was very simple to make and significantly improves the responsiveness of controlling the player character. 


Dust effect for when the player jumps and lands


3. No ending to the level

Addressing this feedback was very simple, as I only needed to add a game object to represent the end of the level. I chose a portal, as it fits with the aesthetic of the game. I aim to add a script that will advance the player to the next level when they make contact with it. 


Portal at the end of the level. Sprite sheet by Varkalandar at:
Animated Portal or Wormhole, several Variants | OpenGameArt.org



Added Sources:

Audio:

Checkpoint Sound Effect:
Zapsplat. 'Crazy female psychotic laugh, cackle with reverb'. Zapsplat. [Online] Available at: https://www.zapsplat.com/music/crazy-female-psychotic-laugh-cackle-with-reverb/

Ghost Scream:
Zapsplat. 'Ghost voice, EVP, eerie fearful breathing 1'. Zapsplat. [Online] Available at: Ghost voice, EVP, eerie fearful breathing 1 - ZapSplat - Download free sound effects

Jump Sound Effect:
Zapsplat. 'Game sound, arcade jump 1'. Zapsplat. [Online] Available at: Game sound, arcade jump 1 - ZapSplat - Download free sound effects 

Running Sound Effect:
Zapsplat.'Footsteps, running fast in flip flops on wet concrete ground'. Zapsplat. [Online] Available at: Footsteps, running fast in flip flops on wet concrete ground - ZapSplat - Download free sound effects

Parachute Sound Effect:
Zapsplat.'Parachute deploy, open'. Zapsplat. [Online] Available at: Parachute deploy, open - ZapSplat - Download free sound effects

Landing Sound Effect:
Zapsplat. 'Person jump land on ground, outside (with shoes on) 1'. Zapsplat. [Online] Available at: Person jump land on ground, outside (with shoes on) 1 - ZapSplat - Download free sound effects 


Sprites:

Portal Sprite Sheet:
Varkalandar.2020.'Animated Portal or Wormhole, Several Variants'. OpenGameArt.org. [Online] Available at: Animated Portal or Wormhole, several Variants | OpenGameArt.org 


Video Tutorials:

Blackthornprod.2018.'6 DETAILS TO MAKE A GREAT PLAYER CHARACTER - UNITY TUTORIAL'.Youtube. [Online] Available at: 

Press Start. 2019. 'Dust Effect when Running & Jumping in Unity [Particle Effect]'.Youtube. [Online] Available at: 

Get Cave Divin'

Leave a comment

Log in with itch.io to leave a comment.