top of page

Car->Go

Car->Go is a physics-based single-player driving game set in an apocalyptic world where the player is the last delivery driver on earth, navigating crumbling terrain in a car that's barely holding together. It constantly accelerates, steers poorly at high speeds and has no brakes. So, to survive, the player must rely on a grappling hook modified to the car to steer, swing around corners and dodge obstacles on their way to their drop-off spot.

​

In this project, my main contributions included implementing the grappling hook mechanic, enemy AI and rating system; All built entirely in Unreal Engine 5.4.4 using primarily blueprint scripting.

Grappling Hook Mechanic
 

I developed a custom Blueprint Component that enables players to grapple onto valid targets detected within range and in view. During this time, the car physics was under heavy development, so having all the logic in a component rather than in the player pawn itself made it easier to maintain and edit in the group setting I was in.

​

Video of  targets appearing in front of the player. The closest targets to the player turn green while the furtherest one are red. Shows the player grappling onto the green targets.

Every tick, this component detects nearby grapple targets that are in a certain distance to the player using a collision sphere surrounding the player. It then checks each one to see if they are visible to the player with a line trace that starts from the player and ends at the targets' locations.

 

The purpose of the line trace is to check if there is any object (i.e. environmental assets) in-between the player and the target.

 

If there are multiple valid targets, it will compare them all based on their distances to the player before saving a reference to the closest one.

​

You can see in the video, the valid targets are green while the other surrounding targets are red!

​

When the player triggers the grapple function, the component spawns a physics constraint actor to anchor the player to the valid target.

 

The constraint actor has its' linear limits limited to the distance between the player and the target on spawn. This gives the realistic physical constraint expected when tying two objects together by a rope/grappling line.

Video of the player using the grappling hook mechanic. It shows the player being restricted by the grappling hook rope.

For visualization, a cable component actor and a mesh actor (with a mesh component of a grapple's hook and with Unreal Engine's Projectile Movement component, and to which we will call hook actor) was used to simulate visual feedback to when the player grapples. The hook actor uses the Projectile Movement component in order to freely choose how fast to "animate" the feedback.

​

Rating System
 

In order to give players a clear sense of achievement and encourages re-playability through performance-based feedback, I made a rating system which calculated their performance based on how long they took to complete a level plus how often of their food was stolen by enemies.

Calculating Rating
 

Image of the formula used to calculate the player's rating based on their food score and time score.

To calculate the star rating (a numerical value of 0 to 5), the above formulae was used.

 

The max level time is a float variable set beforehand that represents the maximum number of seconds expected for the player to be playing.

​

Food score, in this scenario, is a variable that is defaulted to 35(%). It serves similarly to a health point system where it goes down when being attacked by enemies and goes up when overlapping with health-saving items (destructible items in Car->Go's case). This variable is clamped between 0 to 35.

​

Example photo of the use of the rating formulae

In summary of the star rating formula:​

  1. It gets the percentage (out of 100%) of how long until the player reaches the max level time before converting it to out of 65% to get the "Time score".

  2. Adds the "Time score" with the "Food score" to get the "Total Score".

  3. Divides the total score into 6 parts before rounding down (Unreal Engine 5 automatically rounds up. We needed it to round down, hence the "- 1" after rounding.) to get the final numerical rating (0 to 5).

Enemy AI
 

To include more dynamic obstacles, I implemented a simple enemy AI that controlled hostile cars whose sole objective is to follow and ram into the player to negate their scores. Just like the player's car, they use Unreal Engine's Chaos Vehicles system

How It Works
 

Image of the Enemy's AI logic.

To achieve this behaviour, each enemy car checks every tick whether the player is within a certain distance. If the player is detected, the enemy car sets its throttle to maximum speed (input value to 1) and steers directly toward the player. When the player moved out of range, both the steering and throttle reset to zero, making the enemies still and unmoving.

​

Both the "Detect Player" and "LR Selection" nodes are custom functions I made in order to calculate the player detection and the direction of the steering.

Detect Player Function

Image of Detecting Player function's logic. 

To detect the player, I used a "Multi Sphere Trace By Profile" node to detect nearby actors. The results are fed into a "For Each Loop with Break" node, where each actor is checked to determine whether it is the player. If a match is found, the "Player Found" variable (Boolean variable) is set to true, and the loop breaks immediately (for efficiency).

​

​When making this function, I ran into an issue. Previously, this function utilized a "Sphere Overlap Actors" node, but it would fail to detect the player. I found that because the player uses a Chaos Vehicle setup, its collision and object type were being interpreted differently during overlap checks. This caused the node to treat it only as a generic actor. Switching to a trace-based detection method fixed the issue, ensuring consistent and reliable detection of the player vehicle.

​

LR (Left/Right) Selection Function

Image of LR (Left/Right) Selection function's logic.

To calculate the enemy's steering, each enemy car compares the player's distance from two sample points positioned 20 units to the left and right of the enemy car. Using a "Select Float" node, it compares the two distances (left and right) and, depending on which is smaller, it applies the corresponding steering value: -0.7 for left and 0.7 for right.

 

Because the AI only needed simple directional correction rather than precise tracking, using fixed steering values was an effective and efficient solution.

© 2025 BY Jenica Ghayyoori. Powered and secured by Wix

bottom of page