Monday, 10 December 2018

Game - Adding Controller Input

In my Unreal game, I was interested in adding custom controller input. This is because I enjoy giving players an option of which controller method to use - keyboard and mouse, or controller.


Input methods supported in Unreal:
Within Unreal, the software allows you to use keyboard and mouse input for the player input for PC games, but the software also allows you to add input for PC controllers, touch-screen (for mobile and tablet games), console controllers (Steam, Xbox and Playstation), and Virtual Headsets.



How to add a custom input:
To adjust the input to the game, I went to the Project Settings under the Edit menu toolbar. Scroll down on the left to find Input under the Engine header.




In the Bindings section at the top, there is a series of arrays containing to map input keys and input axis's.  Under Action Mappings, there are a series of pre-existing action keys for Jump, Fire and ResetVR.



I wanted to add a new action to allow the player to reload. I added a new item under the Action Mapping array, which I titled 'Reload'. I added two different input methods - the keyboard key R and the left face button on the controller (usually known as X on Xbox controllers and Square on Playstation controllers).

Blueprint code (right-click and drag):


In the above Blueprint class, I have demonstrated how I previously got the player to reload, and how I ended up getting the player to reload. Previously, I relied on the player reloading with just the R key, but now they can use the special Reload input mapping, which works with R and the left face controller button.

In conclusion, I am happy that I have been able to add controller input, as I enjoy trying to make my games work on different input types, and it could give players a different experience with using the controller.

Game - Importing my model into Unreal

After completing my model of a weapon, I needed to export it out of Maya and import it into Unreal.

Step 1: Exporting out of Maya:
Before exporting the model, I was required to group and combine the objects together, to allow the model to import as a single item.

I used my mouse to select all of the items in the scene, which I wanted to export. I used the Combine tool, under the Mesh toolbar menu, which joined all of my gun model items together. This allowed me to have a single object to import into Unreal, as opposed to different polygons and shapes. I was also able to use the Split tool (also under the Mesh toolbar menu), which forced the model to be broken back into the individual components.

To export the model out of my weapon, I used the Game Exporter plugin, a tool recommended to me by my lecturer. To find the tool, I went to 'Game Exporter' under the File toolbar menu, as seen below.


This will show a popup box, which allows you to adjust numerous settings, such as exporting specific parts of a Maya scene, smoothing edges and polygon subdivisions, adjusting parts of an animation, or adjusting the output file (changing the file path, or fbx version). I did not feel the need to change any settings, so I just kept this the same.





Step 2: Importing into Unreal:
To import the model into Unreal, I use the Import into Levels feature under the File toolbar menu. I felt this was a suitable option, instead of dragging it into the assets, as Unreal would be able to process the file correctly.




I chose a location to save the file to, within my Unreal assets folder.



A window popped up which allowed me to review what would be imported into my project. I could use this to adjust what parts of the model are imported, such as mesh shapes or materials . After clicking 'Import' at the lower right of the box, my model was imported into the project.




To add the model onto my player, I opened up the First Person Character window, in the viewport model. I removed the existing gun models on the scene, and added my model in the place.



Final model viewed in Unreal:



Sunday, 9 December 2018

Game - Shooting enemy turrets

In my Unreal game, I wanted to add a series of enemy targets to shoot at the player. I decided to add these turrets into the game, as it adds a challenge for the player to overcome, and I feel it adds an element of enjoyment and fun.

The enemy turrets are static gameobjects, which perform a series of mechanics using the Sequence function.

  1. Rotates to face the player
  2. Shoots projectiles in the player's direction

Enemy Model:
The enemy model was taken from the Unreal FPS template kit. It is a built in object which felt like a turret-like model. I added a custom red material onto this component to give it a distinct look. The red color was used, as it usually represents a negative connotation.



How the code works:
The Blueprint class works around the On See Pawn (PawnSensing) event, and runs the exact same as the enemy boss class.

If the player is within a close proximity of the enemy turret, then the enemy turret sets the look rotation (using FindLookAtRotation, starting at the turret's location with GetActorLocation, and targets the new rotation to be towards the player's location with GetActorLocation).

To fire the projectile, the Blueprint checks a custom boolean variable (SpawnProjectile) to see if a projectile can be spawned. If not, a projectile will be spawned (SpawnActor), and an impulse (AddImpulse) towards the forward vector (GetForwardVector) multiplied by a large speed will fire it. It will then set the boolean to false and add a delay (Delay).

Just like the boss, the boolean acts as a cool down mechanic to avoid an overload of projectiles to be fired. If there was an large number of projectiles in the scene, it would cause the game to lag, and make it difficult to play.

The boss enemy class extends on this mechanic to perform the movement, which is something I did not plan to include on this.


About PawnSensing:
PawnSensing is a feature within UE4 which allows an actor to use logic to understand the movement of other actors. This is a feature which is a good way to add an AI which could perform a mechanic, such as movement.

PawnSensing can be added as a component onto a game object. It will add a series of lines and shapes onto the viewport of the affected actor. The green shapes in the image below show the 'eyes' or area which the actor will look to find other actors - the distance and radius of this can be adjusted at the developer's preference.



The developer can change different features such as checking for only player-controlled actors (which I have set to true, to avoid enemies interacting with each other) and listening for footstep sounds.

There is a similar feature called AI Perception, which is a newer feature which allows for sensing of actors in the scene.



Blueprint code (right-click and drag):



What I have learnt:
In this mechanic, I was happy to be able to utilize a built-in Pawn Sensing method which I have not encountered within Unity. I found this method to make it easier to add add logic to the enemy characters, and I would happily use the PawnSensing mechanic in the future again. I have been able to understand the PawnSensing mechanic, which I have described above.

During development, I was experiencing an issue relating to the shooting of the projectiles from the enemy point of view, which gave me the error below:

FirstPersonProjectile_C_0.Sphere FirstPersonProjectileMesh has to have 'Simulate Physics' enabled if you'd like to AddImpulse. 

To fix this, I was required to enable Simulate Physics on the Projectile game object details, and change the Collisions Preset to Ragdoll.

Game - Rotating target and door opening

In my Unreal game, I added a series of targets which the player would have to shoot to progress through the level.

I decided to add these targets into my game, because it adds an objective to help the player progress. In some of the commercial games which I researched, I noticed that this 'shooting a target' idea was used frequently, so players might expect this as a mechanic in the level.


How the code works:
I use two different classes during this process. I use the Level Blueprint to allow me to access the target game objects, and I use the individual target blueprints to run the Destroy event.

In the Target Blueprint class, I use an Event AnyDamage to check if the target has taken any damage. If so, then destroy itself (DestroyActor).

In the Level Blueprint, I use an Event Tick to add the rotation onto the targets. These targets are attached to a parent cube (which is an actor, to allow it to move). Each delta second of Event Tick will be multiplied by a rotation speed, changing the rotation on the Z-axis. This is then applied to the actor using AddActorLocalRotation. When the two targets are destroyed, I run the OnDestroyed event to run a custom function - OpenDoor.

The OpenDoor custom method will get the door which I choose to open, and change the object's position (SetActorLocation) and rotation (SetActorRotation).


Level Blueprint Code (use right-click and drag):

*Please note, the OnDestroyed methods in this class would link up to 'Target1' and 'Target2', instead of 'None'.

Target Blueprint Code:


OpenDoor custom method:



Final Mechanic:


What I have learnt:
I have been able to understand that you can use multiple blueprints to create one mechanic. In this mechanic, I used two different Blueprint classes, because I needed to access different game objects within the level, while also changing the state of the game objects (destroying them).

I was happy that I was able to make the targets rotate, as it helped add a bit of a challenge to the gameplay, instead of using a single static target.

If I did this in the future, I would attempt to change the custom method by creating one method, instead of creating two separate methods. I could do this by creating one method, and pass a series of parameters between them. I feel that this is bad coding practice to create two individual methods.

Game - Static lasers which kill the player

In my Unreal game, I added a series of static lasers which would kill the player on collision. These were added in to allow the player to use the jumping and crouching mechanic in-game.

How the code works:
To detect the collision, the Blueprint class would use the Event ActorBeginOverlap. The code checks to see if the other actor is the player (OtherActor == GetPlayerController). It uses a Branch function to check if the condition is true. If so, the game will display a game over screen widget (Create Game Over Widget), add it to the viewport (Add To Viewport), display the mouse course (Set ShowMouseCursor to false) and disable the input (Disable Input). We will also play a sound to confirm that the player has died, with Play Sound2D.

Blueprint Code (use right-click and drag):


Final laser:


What I have learnt:

From this mechanic, I have been able to produce a basic collision detection set up, which I could copy in other different mechanics in Unreal games. In comparison to Unity, this feels easier to access to check collisions to the player, as 'Get Player Controller' exists. This is a method which Unreal does not specifically have for the player. 

I was happy with the outcome of this, because it felt simple to set up, and it gave me the result which I wanted.

Saturday, 8 December 2018

Game - Health pick-up item

In my Unreal game, I added a prefab pick-up object which allowed the player to gain health if they took damage throughout the level.

How the code works:
The pickup object had a specific blueprint class which added health, and would run if the player hit the item.

If an actor collided with the health item, which was run with the Event ActorBeginOverlap, it would first compare if the other actor was the player character. If this is true, the code would access the player class (Cast To FirstPersonCharacter...), and add an integer of 10 onto the player's health. Then, the health item would be destroyed, and a sound effect to indicate the pickup would play once.

Blueprint Code:


Final health item:


What I have learnt:

From this mechanic, I have been able to understand the process of accessing variables between different Blueprint classes. In the code, I accessed and set the health variable of the player class, from the Health Item class.

Game - Enemy boss

To complete my Unreal game, the player will need to defeat a boss, in order to complete the level.

The enemy boss performs a series of mechanics, using the Sequence function.

  1. Rotates to face the player
  2. Shoots projectiles at the player
  3. Randomly chooses a new location from three points and moves towards that location

How the code works:
Step one of the Sequence set's the rotation of the boss to face the player. Then, it fires a projectile in that direction.

To rotate towards the player, the boss uses PawnSensing event to recognize if the player is within a close proximity. If this is true, then the boss sets the look rotation (using FindLookAtRotation, starting at the boss's location with GetActorLocation, and targeting the new rotation to be towards the player's location with GetActorLocation).

To fire the projectile, the Blueprint checks a boolean to see if a projectile can be spawned. If not, a projectile will be spawned (SpawnActor), and an impulse (AddImpulse) towards the forward vector (GetForwardVector) multiplied by a large speed will fire it. It will then set the boolean to false and add a delay.

The boolean acts as a cool down mechanic to avoid an overload of projectiles to be fired. If there was an overload of projectiles, it would cause the game to lag, therefore making it difficult to play.

To move to a new location, the boss will lerp between the boss's current position (GetActorLocation) and a random point. This random point is determined in a custom function named GetRandomLoc, which randomly chooses a random integer from the patrolPoints array, and stores it in a variable (currentPatrolPoint).

The patrolPoints array is used to store static gameObjects, which act as positions for the boss to move towards. Within the Blueprint code on the start of the game (Event BeginPlay), the code retrieves the world locations of the three positions (GetWorldLocation), makes an array from it (MakeArray), and sets it to the patrolPoints array, and chooses a random location.

To take damage from the player, the Blueprint code uses the Event AnyDamage to recognize if it has taken a hit, and subtracts 3 health points from the health variable. If the health variable goes below 1, it will be destroyed.

To show the end screen, the Blueprint code uses the Event Destroyed to check if the boss has been defeated, and then setsup a heads-up display (HUD) widget to display the end screen, and adds it to the view port. We also disable the input and display the mouse cursor to allow the user to click on the buttons. (Create EndGame WidgetAdd To Viewport > Disable Input > Set ShowMouseCursor to true)


Different Game Objects to show positions for the Patrol Points array:



Blueprint Code (use right-click and drag):




Final Boss:


What I have learnt:

From this mechanic, I have learned how to use some different coding features in the Unreal engine, such as arrays, randomness and adding my own functions.

With arrays in UE4, the software allow you to store different types of variables within them. For my instance, I stored game objects which acted as positions for the boss's movement mechanic. The functionality of arrays in UE4 work as I expected and remain similar to arrays in other programming languages - such as being able to get the array's length.

With randomness in UE4, the software allowed me to randomly determine an item in an array with RandomInteger (seen in the GetRandomLoc function). This felt easy to set up as it was just a single function to add in. Compared to retrieving a random integer in other programming languages (such as C# in Unity), this felt easier as I did not need to pre-define any random classes beforehand. In C#, you would need instantiate the Random class, before going Random.Next(minimum, maximum). 

I added a custom function in this boss mechanic named GetRandomLoc. This included the randomness factor. This was useful to repeat the same step as one function, as it made the code look tidier, and it is an example of good programming practice. 


Conclusion
In this mechanic, I was happy to be able to incorporate the idea of arrays and custom functions into the code, as it helped me understand the software, and continue to use regular programming features in a new software.

If I approached this boss mechanic in the future, I could make a change to the PatrolPoints array, where this array could be predefined in the engine, instead of defining it in the code. This could tidy up the code. However, I would have to change the array type to store vectors, instead of game objects.