Derek Lau Yiok Teik

Unity 3D Prototype Game (2022 WIP)

Highlight

A custom first-person RigidBody player controller with frame-by-frame custom physics calculation.

The controller is unique in that its main controller script is the only Unity component and, aside from a few helper scripts, the rest of the controller-related scripts are all ScriptableObject-based, such as its State Machine, Raycast probe, and Event system.

The main focus of the controller is to create a controller that is modular and scalable with the least amount of class coupling possible.

Utilising ScriptableObject for its modular plug-and-play nature and its ease of gameplay balance by allowing any changes made during runtime to persist beyond the play mode.

Developing a custom controller from the ground up provides the freedom of implementing custom complex State behaviour logic, a more robust understanding of how the system works internally, and providing the developer full control over the behaviour of physics such as gravity and friction.

Established a consistent naming convention for class, field, property, function, parameter, and local variable within the codebase.

Unity 3D Prototype Game Detailed Information

The State Machine currently consists of 10 different States :
- Idling
- Walking
- Running
- Jumping
- DoubleJumping
- Falling
- WallRunning
- WallJumping
- Surfing
- SurfJumping


The State behaviour logic and Raycast probe logic heavily utilised Unity Vector3 functions such as cross product, dot product, vector projection, and vector projection on plane to procedurally calculate the player’s orientation and direction without any prior hardcoded knowledge of the player’s surroundings.

Raycast is used to detect the player’s surroundings during runtime for information such as surface normal, surface transform, and Raycast hit point.

Each State is designed to be as modular as possible, via Interface Polymorphism and ScriptableObject, to ensure the least amount of logic coupling or at the very least to ensure that each referenced property or function has a single unified point of declaration that any change made there will instantly reflect across the whole codebase, instead of scouring through the codebase just to implement the very same change again and again at every single place that it is referenced.

All the individual movement states are inherited from a common IState interface that provides a unified structure of property and function implementations. Thus, the Raycast and player controller logic can interact with a generic IState type without any precise knowledge of which state they are interacting with nor how the aforementioned state’s behaviour logic works internally.

Since all of the states are ScriptableObject-based, their internal state selection logic and behaviour logic are completely encapsulated within that particular State class. Thus, by limiting its exposure to other classes and vice versa, it is easier to trace and pinpoint the bug within its isolated logic flow.

Based on the player behaviour, state selection logic is optimised via prioritisation and omission of other states’ entry conditions, thus skipping or reserving the most expensive condition operation for the very last possible moment.
  In Walking State, the system prioritises Ground-based Movement States condition checks over Air-based Movement States as the player is more likely to continue moving on the ground than falling off the ground and into the air.
  In WallRunning State, the system omits the DoubleJumping State condition check as it is logically impossible to double-jump while wall-running without wall-jumping first.

The custom gravity system logic is completely decoupled from individual States’ behaviour logic, thus, regardless of which state the player is in, the gravity will always rotate the player's orientation independently via DOTween and Quaternion calculation.

To preserve the “Fun” of high momentum-based movement, DoubleJumping needs to be able to preserve the player’s momentum in the air while still providing precise air movement control. The player needs to rapidly change their direction in the air without sacrificing too much of their initial momentum, but the player still needs to put a dead stop in their air movement to land precisely on top of a target.

Whenever the player does a 180° directional change in momentum, we need to drastically reduce their momentum to stop precisely in mid-air. However, the left to right and vice-versa DoubleJump unfortunately also fit the description of 180° directional change in DoubleJumping, thus we need to make another condition check to exclude the left to right DoubleJump from the drastic momentum loss.

However, granting the left to right and vice-versa DoubleJump to preserve momentum results in an unnatural jump in which the DoubleJump changes its direction too rapidly that it breaks the immersion of believable air movement. The root cause was the lack of inertia during momentum preservation. And thus, a new requirement is added for momentum preservation in which it requires a small momentum loss and directional angle loss to represent the inertia of momentum directional change which I will classify such DoubleJump behaviour as low momentum loss.

Now, for the high momentum loss DoubleJump that puts a dead stop in mid-air, the basic gist of how it works is the closer the non-left-to-right momentum directional change gets to 180°, the higher the momentum loss will be, with a maximum of 100% momentum loss linearly or non-linearly.

Thus, DoubleJumping State behaviour logic is branched into 2 types of momentum loss :
  Low momentum loss with a small momentum loss and directional angle loss.
High momentum loss that scales linearly or non-linearly.

Surprisingly, DoubleJumping State has more lines of code than Surfing State which is an omnidirectional movement, which honestly is quite a big surprise to my initial expectation.

Surfing State recreates and modifies Source Engine Strafe movement which instead of being relative to the player's GameObject forward direction, is relative to the player's RigidBody velocity forward direction. By separating the strafe control from the player and camera orientation and combining it with the RigidBody velocity direction, this creates a more beginner-friendly Surfing control as the player can freely look around without worrying that the camera orientation will impact their Surfing momentum.

Strafing in mid-air will also impact how much air movement control the player will get, the air movement control will scale linearly from a lower bound baseline value to an upper bound maximum value. Thus, allowing the player to make a sharper turn at a higher momentum.

Despite being physically unrealistic, it is more interesting to give the player better air control while the player is moving with a high momentum to negate the greater inertia that comes along with it. As it makes a thrilling moment when the player barely makes the turn to land on a sharply-angled Surf Ramp rather than just having the Player helplessly hurled far away from the Surf Ramp course by the inertia.

Aside from the Unity primitive meshes, all prototype models were personally designed, modelled, and animated by myself via Blender.

The sea of clouds background shader was created via Unity Shader Graph, while the cloud particle VFX was created via Unity VFX Graph.

Whenever a moving GameObject touches the sea of clouds on the ground, a cloud particle VFX will be dynamically spawned at the trigger collider's closest point on its bounding box via ScriptableObject-based Object Pooler to reduce runtime VFX GameObject instantiation overhead.

Mobirise

Sticker AR Effect in display

UOW Final Year Project AR App (Unity Engine) (2021)

Sentiful is an augmented reality gift customization app.

For this project, I had developed various features for the Sentiful app in Unity Engine such as:

- GIF & Sticker Library powered by GIPHY API and GIF & Sticker AR display in Vuforia

- VFX AR display prototype with Unity AR Foundation

- Basic iPhone and iPad platform support via Xcode

AR Project Demonstration

Mobirise

GIF Library

Mobirise

Multiple Explosion VFX AR Effects in display

"Drowning Depth" Rigging and Animation (2021)

The model is then rigged and animated in VoxEdit.

Contact me

dereklau612@gmail.com

(+61)4 2458 3307

Github           LinkedIn

Designed with Mobirise website maker