Freelance Felons 2

About the Project

Freelance Felons 2 is a spiritual successor of a past unity project of mine designed to test everything I have learnt to far in unreal engine and C++. It will be a story game with missions and cutscenes, where the character plays a fixer, someone without any affiliations that people with problems can employ. This could be a simple collection or a contract killing, as long as the price is right, and these missions can be played out among a bustling tropical island full of life and fully explorable. This is of course all with the help of a huge fleet of drivable vehicles and arsenal of weapons to use however players desire, as long as they’re willing to face the legal consequences of the unforgiving police department.

 

 

All of the code for this project can be found on my Github here.

Dev Log

Cars Day 9 - Suspension

10/05/26

Today I wanted to get suspension working on my car, so I started by learning the basic calculation for the spring force of suspension, which is spring strength, times compression, minus dampening, multiplied by the magnitude of the vertical velocity of the car. After learning this I just had to work out which values should be uproperties, like strength and dampening, and which needed calculating per wheel per frame. Once this was all working I spend a while fine tuning these spring and dampening values at first just to stop the car from bunny hopping but then to ensure it looked correct when driving. This was very difficult with the visual aid of the wheels which were still static so that needed fixing. To achieve this I simply set the wheel to the impact point of the ground trace, then added the cars up vector by a uproperty offset. These combined finished the vehicle suspension however it wasn’t the difficulty of the maths that took all the time up, it was the endless test driving different values to fine tune and go crazy over miniscule differences. Once I was happy, I decided to get the handbrake input I had already set up working. This meant checking each of the rear wheels was on the ground, then finding the dot product of the velocity at the wheel to the cars forward vector. That was then multiplied by the cars negated forward vector and a uproperty handbrake force and added as a force at each grounded wheel. After tuning the this handbrake force, and making it so the car didn’t catapult backwards or drive like nothing was happening, it was time to make this a more entertaining feature. I wanted to make the handbrake a tool for drifting around corners making exploring the island way more fun as well as adding a slight skill gap to learn to driving within the game. To do this I made the handbrake set a bool that’s checked in the lateral friction function, where if true, it reduces the lateral friction of the rear wheels by a uproperty multiplier. This gave me a lot of different qualities to be testing for on my test drives, trying to balance the floatiness of high speeds with the too much steering with too much friction to control drifts. Tuning these values led me to realise that my steering angle needed to change depending on my speed, which I achieved using a mapped range from speed to angle, and this combined with fine tuned lateral friction values at low and high speeds, combined with a good handbrake force and friction modifier has led to a very enjoyable driving experience. I am sure I will end up fine tuning these values in future however right now the car is in a very good feeling state, only really needing the wheels to spin before it looks polished. Then its time to make 23 different looking and feeling cars before the rest of the game in the next four months. One last ting I did today as well was reduce the engine power the closer the vehicle gets to a uproperty max speed to stop them from accelerating forever making the car much more controllable to drive on long straight roads without reaching uncontrollably high speeds or letting go of ‘w’.

Cars Day 8 - Tuning

07/05/26

I started my day walking into a car accidentally and seeing that it moved a little, before realising I could literally push the car round in circles. After checking through the vehicles mass settings which were set to 1000kg, I was confused and decided to look through the character movement component, thinking it must be walking too strongly. This is when I found a variable called push force factor which once turned from 750,000 down to 500, the car didn’t budge as intended. Now I want to make some adjustments to the steering because at low speeds it feels too slippery and unresponsive but at high speeds its uncontrollably grippy. My idea to achieve this is to adjust the lateral friction factor, making it inversely scale with speed. This was done using a mapped range value clamped with an input speed from 0 to 55 mph against an output friction of two  uproperty values for min and max friction. Then I simply input the 2D size of the vehicles velocity and it returns an appropriate lateral friction value. This made the car nice enough to properly drive for the first time allowing me to drive it around the entire island. Now I have to fine tune these values until it feels right, not to slippery / grippy at high speed or low speeds by tuning the min and max friction values until it feel right.

Cars Day 7 - Steering

05/05/26

Today I want to get the car steering which should in theory be a very simple job with the lateral friction I set up yesterday. All I need to do is rotate the wheel mesh in the inputted direction by the inputted amount and it should work. To achieve this I made a function called once per input to avoid having movement logic in the input section of my class. This function however just called a utility function that rotates the wheel mesh of a provided wheel data struct using set relative rotation, passing in a rotator with the pitch and roll zeroed and the right input multiplied by the max steering angle for the yaw. This max steering angle is a tuneable uproperty which allows for easy future adjustment to steering angle. This function was then called twice in the previous apply steering function, passing in the right input and the structs for both front wheels, and this is when I spotted an issue. To reduce the amount of static meshes and streamline the process of putting the car pieces together, the same wheel mesh is used on all four wheels, and is rotated 180 in yaw in order to work. This meant that my steering logic would flip the front wheels the wrong way round which meant I had to find a simple way to differentiate these flipped wheels. This lead to the addition of a if statement in the rotate wheel mesh function that checked the pre rotation relative rotation yaw, and if it was above 90 or below -90, this must be one of the flipped wheels therefore 180 was added to the yaw of the new rotator. This created a working steering system first try, also meaning that the untested lateral friction works too, however it looked wrong with the wheels snapping to full lock with any movement input. This lead to a slight change in the steering input. I created a member variable that is set to the inputted steering, and reset to zero when there is no steering input, and then moved the call for the apply steering function into the tick passing through delta time. Then a final input float is created, using interpolation from the member variable current steer input, the frequently updated target steer angle and a tuneable steering speed uproperty. The current steer input member variable is then updated and this all works to create much better smoother steering.

Cars Day 6 - Lateral Friction

04/05/26

Today I Added a drive train enum that allowed each car to be easily changed between FWD, RWD and 4WD. This is achieved by a switch statement on the enum that specifies which wheels to add the force to. I then realised that it went way to fast on 4WD so created a function that divides the engine power float by the number of driving wheels float to allow for easy consistent power. This will allow different classes of vehicles to feel different in how they use their power, as well as providing actual offroad and driving benefits using Unreal’s physics engine. Then to prepare to add steering into the game, I implemented lateral wheel friction, which led to the creation of a wheels array. This replaced the wheel data struct member variables and is filled with grounded check hit results within the struct of wheel data every frame. Now I have an easy to access and updated impact point for every wheel every frame anywhere in the class for only one trace per wheel. Iterating through this array every frame allowed me to get the linear velocity at each impact point, which could be compared to the wheel’s right velocity and a friction force could be applied in the opposite direction. This should all stop wheels from sliding sideways and favour forward by a tuneable value, meaning that when I start rotating wheels for steering, the car should go in the direction of the meshes already.

Cars Day 5 - Movement

03/05/26

Its finally time to get the cars moving and after a lot of thinking and planning the past few days, I think I have a plan. I replaced the scene component root with a box component root with simulate physics enabled and only blocking world static for now to avoid falling through the floor, and I made the body query only. This was to enable the car to interact with the engine’s physics and was the first step to physics based vehicle movement. Next I created a struct that held both the mesh and a trace point for each wheel, saving one for each wheel as a member variable, before creating a function designed to check if a given wheel struct was on the ground. This function traced down from the trace point in the struct by a uproperty float, and returned the hit result. This function was then called in another function, where the returned hit result is then checked for a blocking hit meaning the wheel is on the ground, before calling add force at location at the impact point if there is one. This force is the vehicle’s forward vector, multiplied by a float input passed into the function, multiplied by a uproperty float for the engine force to tune how powerful and fast each car is. This function is called in the move input function for each driving wheel manually, passing in the inputted forward axis. 

Cars Day 4 - More Animations

30/04/26

I started today by fixing the exit function, which turns out was only missing the enabling of the characters colliders before working perfectly. It was then time to start improving the entry animations my making the doors open along with the character animations. I decided that perfectly syncing the animations was a lot of work that I don’t think I have the time for with the scope of this project, so I decided to just line up the animations as much as I could and accept the slight gap between the hand and door handle. With attaching the characters hand to a door handle socket now out of the question, I had to decide how to animate the static mesh components for the doors. Considering they had no skeletons, actual animations were out of the question, along side the fact I also didn’t think making almost fifty individual door animations was a good use of my time either. This lead me to the idea of using a timeline blueprint node that could be easily adjusted, that returns a float that becomes the yaw of a rotator, that is applied to the door every frame of the timeline. Whilst this was achieved in blueprint I believe it was the cleanest solution to achieve the adjustability I required whilst also being a time and performance efficient solution. Finally to correctly trigger this blueprint function, I added an anim notify to the character animations for when they’re about to open the door, this then calls a function on the anim instance class that follows the same path to the vehicle class as the possession notify, calling a blueprint implementable function. As some finishing touches to make sure this all lined up correctly, I added a couple of scene components positioned in front of the doors to position the character to before the animations leading me to another decision, so I snap or lerp. Whilst lerping would be theoretically cleaner, it would have to be so quick it would be hardly noticeable and with the distance and position checks before entry, snapping would result in a similar effect for less cost or timing difficulty. And then I did pretty much the same but in reverse for getting out of the car. When I press to open the door and its successful, the vehicle state is set to transition and the door opens, which on completion calls a separate function to show the player, enable its collision and play the exit animation. That function also possesses the character and corrects the input context and sets the vehicle state to parked while the animation is playing until it triggers a notify, which causes the door to close in time with the animation.

Cars Day 3 - Animations

28/04/26

Now for my least favourite process to begin, animations. And shocker, they are not going smoothly at all. I started by finding some animations for getting in and out of a car, mirrored them using UE5.6s new modifiers and added them to a montage which I am trying to play, however have been hitting repeated walls. My collision isn’t turning off, my root motion isn’t working properly, my montage wasn’t jumping to the right sections and now isn’t playing animations but it playing the root motion. Now I have it playing the right animation, after learning more about animation slots and fixing the animation selection logic, that was checking an incorrect enum, its time to start work on possession timing. I decided to achieve this with an anim notify. To achieve this I call a function on the anim instance, which calls a function on the player controller, which gets the most recently interacted with vehicle from the player and calls the original posses vehicle function. This avoids the character and vehicle classes having to include each other which shouldn’t be needed as they are independent, only relying on the player controller, which should know about the pawns it possesses. Now I just have to fix my exit function next time as the player doesn’t reset properly, unable to move and without animations but still rotating in the direction of input and able to get back in the car.

Cars Day 2 - Possession

27/04/26

After taking a few days off around my birthday I was back to get the character getting in and out of the car. I started today by adding the possession logic to the vehicle class, possessing the car pawn, before attacking the character to a empty ‘socket’ scene component positioned outside the drivers door in blueprint. The character is then hidden with its collision disabled and the vehicle state is set to player, confirming the player has successfully entered the vehicle. Finally the input needed to be added for vehicles to allow camera movement, getting out and eventually vehicle movement. To achieve this cleanly with the enhanced input system I moved all input context related logic to a new player controller where a base and on foot context are added at the start of the game. A public function on the player controller can then be called to switch the on foot context for a vehicle context and vice versa. With this working I then copied the camera movement function from the player and set up callbacks for other inputs I knew I would be adding in future, filling them with logs for testing. Finally I completed the exit function I created last time so that it first checked for obstacles outside the drivers side door, using the same function as for getting in, before adjusting the vehicle state to transition, possessing the most recent instigating character, telling the player controller to change input back to on foot and detach the character. The Character is then made visible with collision enabled outside the drivers door. Animation for all of this will be the next step however I have set up the switch and if statements that differentiate between vehicles with NPC drivers and without, as well as which door the player is entering, all that’s left is the player entering montage, player exit animation and the eventual addition of an exiting NPC when they are added. I started this blog to highlight the issues I face day to day but have been extremely lucky, facing nothing more than some missed parenthesis or some flipped logic in an if check, for which I am both grateful and proud. 

Cars Day 1 - Entry Checks

23/04/26

I did a lot today and am very happy with the results. To start with I created a vehicle class and set it up with all of the various mesh components, that could then be positioned within the blueprint editor. I then created an interact interface that would allow character input to call functions in other classes without casting or includes. This interface was then linked to an interact input action in the character class, that would get all interactable actors within a given range, then find the closest in that array before calling an interact function on the interface. Then on the vehicle, after receiving this interact input from the interface, it would determine whether the player was trying to enter or exit the vehicle using an enum on the vehicle called vehicle state. So far exit does nothing however the enter case goes on to verify if the character can actually enter the vehicle. It starts by checking if the character is actually stood by a door, rather than just by the car using a distance check, before using a single box trace to check for any obstacles in front of the door that would block any entry animations. Provided there are no obstacles, an enter function is then called.

Car Models Day 3

17/04/26

It was just a little more practise after work splitting up the car models today. By far the most tedious part of this process is fixing the normals to make sure that my edits don’t allow the player to see through the car models. I don’t really want to put much more time into this yet before testing out my ideas of how to bring these cars to life, to make sure that no more edits need to be made in order for these cars to work. Right now the things I have planned for are fixing the pivot points on the wheels allowing them to rotate around the centre and spin properly and I have been separating and correcting the pivot point of the car doors allowing them to easily open. I’m hoping I can get away without separating the callipers and that the player wont notice them being static e.g. if I add suspension  and when I start turning the front wheels. 

Car Models Day 2

15/04/26

Today I started the tedious process of altering all of the car models allowing thinks such as the wheels to spin and the doors to open, before creating their materials. This meant re-familiarizing myself with Blender to separate the models into separate pieces and fix their origins. This took a long time to figure out and learn how to do by teaching myself and googling shortcuts that I learnt whilst making a doughnut over a year ago. at the end of the day I am two of twenty three cars down, however I at least now know the method that should hopefully speed up future days. I also bought some more metahuman clothes for when its time to design an array of NPCs and story characters as there was a sale on.

Character Movement Day 7

14/04/26

I started my day getting the sneaking animations working, creating a separate blend-space along with a state machine in my animation blueprint. I then switched between a locomotion and sneak state based on a bool in my anim instance that checks if my characters locomotion state is equal to sneak. I’ve also got the jump animations working, with jump up, loop and down in separate states and the anim instance checking the character movement components IsFalling bool as well as if its in the jump state. One thing I am struggling with is deciding whether to go back to the pre jump state like sprinting or sneaking or just to automatically boot the character back to walking.

Character Movement Day 6

12/04/26

Today I got imported and retargeted some locomotion animations, before creating an animation blueprint to show a blend-space. Then, to feed my characters speed to the animation blueprint I created an anim instance class that accesses a speed getter on the player. I also fixed a bug where the pitch of the camera and controller impacted the speed of the player, where looking at the floor would set the speed to almost zero as well as adding auto cancel sprint for if the character stops moving or hits an obstacle.

Car Models Day 1

11/04/26

Today I found a very good and diverse car pack with high quality models, however I have struggled a lot to import them to UE as only FBX files were provided. This will mean individually creating and assigning materials with the provided textures. Also in future I may have to edit these models in blender to separate the doors for when the player gets in and out as phasing through a closed door with definitely break immersion. For now I will just leave the car models until I have some finished car mechanics and have more insight into how they will work, but al least I have seen the models and can envision my next steps now.

Character Models Day 2

10/04/26

Today I managed to import some clothing I found on Fab, making my character look more like a civilian. I also spent time making separate materials for every colour option for each piece of clothing. This all should allow the same basic outfit to have a huge amount of variation and bring much more of a lifelike feeling to the world. Now that I have a workflow that functions, I can spend time creating many more characters, and importing more clothing options from Fab until I am happy I have the variation for both NPCs and story characters.

Character Models Day 1

08/04/26

Today I have spent a lot of time learning how to make metahumans. I decided this would be the best approach to having a variety of faces in the world in order to make it feel realistic. I also spent a lot of time searching fab for various outfit options that could add even more variation. I feel as though characters are the type of thing I need to make feel lifelike in order to consider this game a success and I will therefore most likely spend a lot of time and money trying to get a big enough array of blueprint metahumans for the player character, story characters and NPCs. I also did a bit of research into how to animate these assets as well as looking around fab for some car models to use in future.

Character Movement Day 5

05/04/26

Today I finished the basic locomotion including sprint, sneak and jump. Whilst these are very basic actions, I want to keep to my goal of making robust, maintainable and well structured systems that could be expanded easily. This is when I had an idea that would eliminate the risk of overlapping contrasting inputs that would be problematic had I linked input directly to movement speed, that involved making an enum for locomotion state. To start with, the inputs for sprinting and sneaking would only be linked to a function to call the setter for the enum. This would pass in the opposite of whatever its current value was to replicate GTA’s iconic toggle sprint feel. Once the enum was set, the setter would call another function containing a switch statement that would only call the function for the most recent input which could then change the players speed. I was also shocked that this system I had designed worked exactly as intended first try.

Character Movement Day 4

03/04/26

Today I got the basic movement finished, allowing conventional third person movement. I found that my error yesterday was that I didn’t take into account the camera or controller direction. To fix this I used the kismet get forward and right vector functions, and multiplied those scaler value directions by the magnitude of the character input. This gave me a forward and right movement vector that took into account the players look direction and these two vectors could be added for a final movement vector.

Character Movement Day 3

02/04/26

After getting the Mouse inputs working yesterday, I started off by finding the settings that allowed my camera to follow them today, making looking around complete. Knowing the bools like bUseControllerDesiredRotation and bUsePawnControlRotation is something I foresee being one of the biggest challenges of this project. I also have some working movement, however it doesn’t take into account the controller / camera direction so I will have to make some adjustments.

Character Movement Day 2

01/04/26

Today I’ve been trying to add functionality to my look function from memory, rather than looking through old code and not testing myself. This has meant slow progress in the little time I have however will be much more beneficial long term which is the ultimate goal. So far horizontal looking is working however vertical is not, likely to do with controller or character movement settings rather than code, but still something I would like to solve without videos, AI or past code and instead with forums or ideally documentation.

Character Movement Day 1

31/03/26

This project has been very intimidating for me to start, I think “remake GTA” was a bit of an extreme scope, but you need to find your limits to push them I guess. For today I managed to get the Github repo setup with LFS so all my work would be backed up easily. I also managed to start work on the character input, using enhanced input to link a basic context to some functions that for now just prints debug logs. Also in an effort to future proof for when vehicles are added, I separated my inputs to two separate contexts to allow different inputs while walking and driving, along with a base context for looking and movement.

Hello World

29/03/26

One Day or Day One. I have finally got round to starting the project of my dreams. I’ve also got round to learning how to blog, hopefully. Here I will provide a timeline into the creation of this project, and a look into the day to day struggles and successes when trying to make a game with such a huge scope and not much experience. All I know is I am guaranteed to learn a lot over the next five months no matter this result. To start this project, I imported this FAB tropical island by F.S.S into a blank UE 5.7 project, after lots of issues migrating it over from 5.6 before just copying over the files in file explorer. Whilst probably not optimal or ideal this seemed to work and after a bit of a look around I called it a night.