Professional Projects
Project Leeroy

Professional Role : Programmer, C#, XR, Quest, Multiplayer Fusion 2, Unity 3D
During the Develoment of Leroy I have Created and owned several mini-games.
Contributing to the creation of innovative systems and tools that enhance both functionality and user experience.
created a tunable, network-safe, and consistent XR Object Throwing system, which was consistant across different platforms and performance levels.
I also created components and tools to empower designers to develop and network mini-games without the need for coding.
Additionally, a network-safe, recursive, physics-based building system was Implemented , along with a multi-spline-based tool for constructing prefab based splines.
Tin Hearts

Professional Role : Programmer, C#, XR, PSVR, Quest, Index, Unity3D
Implemented XR support for core game interactions , mechanics and user interfaces, ensuring compatibility across multiple platforms and controllers. Integrated achievement support for various storefronts, enhancing the user experience across different ecosystems.
Developed tools to assist designers and streamline debugging within the XR environment, and implemented comfort settings to improve user accessibility and overall experience in XR.
Galacticare

Professional Role : Programmer , C#, Job System, Unity3D
Worked on the development of Level Editor Tools and a Level Loading System, alongside building a Camera system and a Quest System. Additionally, created UI components integrated with Multi-Threaded Entity Component System backends, and implemented I18n Translation Tooling for ease of internationalization.
Personal Projects
Battle of Mustafar

Showcased at develop Brighton
Battle of Mustafar is a wave survival game where the player must survive waves of drones by deflecting blaster bolts back at the attacking drones.
Spatial Skydiving

Totally Realistic Racing

Shinobi Swipe

Spire

Aquatic Rush

Cat Attack

AGS RACER

Network Multiplayer, UNet, Web-sockets, Split Screen, procedurally Generated, Racing, C#, python, Keras, Convolutional neural networks, Playstation 4, PC, Made with Unity
Showcased at develop Brighton
My idea behind creating AGS Racer was t o make a racing game where no player knows what track layout will be, as usually in a racing game you need to learn a track to know what to expect.
The race track consists of a starting line , a finish line and an assortment of track pieces.
Each piece of the track I modelled in 3DS MAX to create prefabs with a defined curvature going left, right, up, down and straight.These track pieces are then automatically aligned based on alignment nodes defining the start and end of each part.
The following code shows the process of choosing creating the parts of the race track so that the direction is biased to avoid the track intersecting with itself excluding the starting and finishing line.
void CreateParts ()
{
Transform endPoint;
Transform startPoint;
trackDirection = Vector3.zero;
int randomTrackNum;
if (Currentpart < trackLength - 1) {
endPoint = Track [Currentpart - 1].transform.Find ( "End" ).transform;
do { // when creating new part check trackpartprefabs direction if direction is to larger try new track part
randomTrackNum = Random .Range (0, TrackPartPrefab.Length); //creates a random number
} while
(trackDirection.x + TrackPartPrefab [randomTrackNum].angle.x > maxangle ||
trackDirection.x + TrackPartPrefab [randomTrackNum].angle.x < -maxangle ||
trackDirection.y + TrackPartPrefab [randomTrackNum].angle.y > maxangle ||
trackDirection.y + TrackPartPrefab [randomTrackNum].angle.y < -maxangle ||
trackDirection.z + TrackPartPrefab [randomTrackNum].angle.z > maxangle ||
trackDirection.z + TrackPartPrefab [randomTrackNum].angle.z < -maxangle);
//end of do while loop conditions
trackDirection += TrackPartPrefab [randomTrackNum].angle; // sets new track direction
startPoint = TrackPartPrefab [randomTrackNum].part.transform.Find ( "Start" ).transform; // sets the start point of the current track piece
//Instantiates track part in the end point position of the previous track object
Track [Currentpart] = Instantiate (TrackPartPrefab [randomTrackNum].part,
endPoint.position, endPoint.rotation, StartingPoint.transform)
as
GameObject ;
Track [Currentpart].transform.Translate (-startPoint.position);
Currentpart++;
} else if (Currentpart == trackLength - 1)
{
built = true ;
buildingtrack = false ;
BuildTrack ();
}
}
During the time I took this game to display at the Kingston University booth during the Brighton develop Conference, I learnt about PID controllers and realised that it would improve how the racers hovered above the track by reducing hover oscillation, so by the next day I had researched and implemented the following code.
[SerializeField] private float PIDproportion = 1; //initial force
[SerializeField] private float PIDintegral = 0; //time taken
[SerializeField] private float PIDderivative = 0.1f; //damper
private float previousError;
private float P, I, D;
float PIDoutput( float currentError, float DeltaTime)
{
P = currentError;
I += P * DeltaTime;
D = (P - previousError) / DeltaTime;
previousError = currentError;
return (P * PIDproportion + I * PIDintegral + D * PIDderivative);
}
Neural Network AI addition
A 2D convolutional network was trained using 38,000 images with controller inputs and time stamps.
the ai works by having unity send a picture of what the car sees to a python server via web-sockets, this then uses a 2D convolutional neural network to evaluate the picture and send inputs back to unity. The neural network used in this video was created from 30 minutes of gameplay
PeaceMan Pat

In this game the player goes around 'informing' the uninformed armies of red and blue to stop fighting as otherwise the armies will eventually kill each other.
Ravenous Cities

Gold Runner
Glider Flight

X[i] = (1 - cos(((i - 1) * 90 / loops - 1)* 3.14 / 180));
// calculates the thickness of the air-foil based upon the thickness variable and x position
Y_T[i] = (thickness / 0.2)*((0.2969*pow(X[i], 0.5)) - (0.16*X[i]) - (0.3516*(pow(X[i], 2))+ (0.2843*(pow(X[i], 3))) - (0.1015*(pow(X[i], 4))));
// calculates the camber location and camber intensity of the air-foil
Y_C[i] = (camber / (pow(camberlocation / 10, 2)))*((2 * (camberlocation/10 )*X[i]) -pow(X[i], 2));
// stores the Y coordinates for the upper and lower lines of the air-foil
upper[i] = (Y_C[i] + Y_T[i]);
lower[i] = (Y_C[i] - Y_T[i]);