Free Roam Racer Prototype

Hello all!

Free Roam Racer Prototype
I picked up UE4 exactly a week ago after spending the summer trying to make a racing game in Unity and failing due to various hilarious engine bugs. However due to that I have various free models and textures as well as bits of code laying around. I have programmed before, but that was in Lua, and casts and types in C#/C++ get me all the time, so blueprints are a godsend for me.

To be frank, my rig is not a monster machine (Dell Vostro 3450 [Radeon 6630M] upgraded to 8 GB RAM) so I will not focus on graphics, instead working on procedural generation and AI.

Dev log - or what can be done in a week with UE4

I used [UPDATED 5/16] A.I. Templates - Bot, Car, & +Flying AI - Programming & Scripting - Unreal Engine Forums as a starting point.

I don’t have any spare money to spend, so I have to make my own functions or find free examples, so no road plugin or any of that stuff involved.

Links below lead to short webm clips.

Monday WIP, imported a road texture I had laying around

Yesterday evening, each AI has its own lane but they cut corners
FYI The lane points are generated based on the spline control points - it is all a single handplaced spline plus a bunch of blueprints


This morning - AI detecting turns. Blue debug text is because I was testing raycasting down at the same time

This evening, just before posting - the AI only brakes in turns and speeds up on straights
A reminder: all of the stuff is generated based on the single spline

Sharing & future
The game has a repo on gitlab, but set to private for now because I’m using assets from vehicle template. For the cars, I have that idea of using magicavoxel/voxelshop and making voxel cars with interchangeable bits and pieces (inside decor, brakelights, spoilers, door, window shapes etc.).
I understand that when (in the future) I manage to get rid of the template assets, I will be able to make the game open-source? Or does using blueprints make that impossible?

The plan for the nearest future is to procedurally generate static meshes along the road (test cubes for now, standing in for buildings, street lamps etc.). The AI also needs collision avoidance, and of course the game needs more roads. After that, the game needs actual races in addition to free roaming.

Any feedback is welcome! If you ask, I can also share screenshots of blueprint parts that you’d like to see.

How do your cars drive? Are they twitchy, weighty or drifty?

I would say fairly drifty for now. I used the default settings from the vehicle template (the simple one, not the advanced one) and only changed the differential to Front Wheel Limited Slip instead of 4WD Limited Slip. I’m trying to recall if NFS cars are mostly FWD or RWD…
Once I get a couple of cars in, I might make some this way and some that. However getting more cars in will have to wait until I figure out how to replace the default mesh with something else, I mean voxel-based, while retaining the skeletal mesh (the bones).

I will be tuning them better once I figure out how to do it - for now I’ve focused on AI and generating the roads.

I do like the way your AI is shaping up now but I feel you should approach your game in a different order. If you end up working on driving mechanics after your AI, then your AI might start misbehaving again, like say sliding all over the place (drift setup) or over-turning (grip) and you’re essentially back to square one (OK, maybe I was exaggerating a bit there, but you get the point). This order is just a personal preference but I get the feeling that you would better off working your AI after you’ve fine-tuned your driving model, which is, after all the very base an arcade racer rests on.

You are right, however the problem is, I don’t understand the intricacies of the wheeled vehicle component well enough yet to tinker with it.

Progress since the 4th Nov

Integrated the time of day system from [TUTORIAL] Quick Time-of-Day Setup - Community & Industry Discussion - Epic Developer Community Forums

7c102f720f6debe7d8ec0c9a8c7e16a7f73e5269.gif
Sunset

7c102f720f6debe7d8ec0c9a8c7e16a7f73e5269.gif
Predawn light

AI racing line is no longer a debug line, but particles


Testing a construction script to place test cubes around the road

A simple minimap based on a tutorial
Also, the AI can now detect a car ahead and brake if there is one - it won’t prevent crashes if the other car is completely stationary, but for moving cars it works well enough

AI now have a name label above them (currently ‘AI car’) and a debug display showing their current speed

Since Tuesday, the AI has gained an ability to detect obstacles (test cubes) along the road. It doesn’t do much with the knowledge, though :stuck_out_tongue:

Also I have successfully came up with a proof of concept for modular vehicles (used Blender to remove the mesh from the template car in order to have a working bones setup). This took nearly a day because of this problem (I think it’s UE4’s fault) - and then I had to solve the issue with the wheels slowly sinking into the ground (removing collisions on the static mesh fixed this). The other half of the day was trying to understand custom channels (see above). For said modular vehicles, I already mentioned voxels, so I downloaded MagicaVoxel and VoxelShop and have been familiarizing myself with them.

Yesterday evening, I had a working proof of concept using an untextured voxel mesh… and then decided to rename some files. I committed the changes since they seemed to work, but upon restarting, UE4 decided to play havoc with the materials. I tried to git rebase, but it didn’t want to work. Thankfully I had a manual backup so I just spent two hours restoring the project to the working state (set up a completely new git repo, set up a blank project, copy backup files into it, fix input assignments, push to the new repo, fire the old one so that I’m not confused by similar names).

To avoid such incidents in the future, I’ve reminded myself how to set up git branches. So any renaming I do, as well as the modular voxel stuff, will go on separate branches to avoid stuffing up the master branch.

The upside to the new repo is that it has less commits and the new project also slimmed in size, from 980 MB to 200 MB. I can still see some opportunities to slim it down (duplicated materials and the like) but will be extra careful now!

Keep up the work! Looking forward to you making it public for people to contribute. I am interested in helping out, as a good racing template would be awesome!

Thanks for the kind words! Public repo will happen as soon as I replace the template cars with voxel cars for good, I guess. What is the stance on Automobile Materials, Content Examples and/or other Epic content? If they’re forbidden, I might make the repo anyway but mark the folder as ignored…

Progress since the git mess up on our Independence Day (11/11)

Links go to gfycat, as usual.

A voxel car proof of concept, with two bumper types (randomly determined by construction script)

Better gif of the above, you can see the bumper change but on untextured model

The voxel cars is a test branch on git for now. I also learned how to make child blueprints to avoid having incompatible changes between dev branch and voxel branch

Improvements to rain efffect - no longer just particles, now the sky, clouds and lighting change to match!
Having the lighting change work properly required switching off the auto exposure

Also I just updated to 4.14 and saw no issues.

Hard to believe I shelved my main project (non-UE4) and haven’t been missing it :stuck_out_tongue: Weird feeling since I’ve been working on it in some form almost nonstop for three years.

So it’s been two weeks working on the prototype. More progress:

Player headlights on/off and a test streetlight in the background

Headlights off, streetlight automatically turns off at dawn to conserve resources (but turns back on if raining)

Improved the road tool to get rid of mesh stretching (have smoother turns at the expense of somewhat blurry textures in the distance) and to auto-generate sidewalks
P.S. The road you can see in the lower right corner of the top view is procedurally generated from point A to point B but fairly uninteresting so far, just a straight

EDIT: Thanks to 0lento for helping out with the road tool.

I spent two days fighting performance problems. Kind people on Discord told me how to use the profiler but it still took me two days to wise up to what was causing RAM usage through the roof and startup taking a lot of time. The answer was the grid visualization, I had to tie it to a bool and switch it off for playing…


The source of the problem - works fine in editor, stuffs up physics when starting game. It’s all Instanced Static Meshes. Thin blue squares are from testing the intersection placeholder mesh

The grid was made so that I could do this:


*Blue squares are a placeholder mesh for intersections. Those are placed on a per-grid basis. The placer supports random seeds, by the way. *

Test driving the shortest road above
Numbers need some more tweaking, but the basics are there

Roads are placed using a fairly simple idea:

  1. specify the road actor’s location to be point A (first point of the spline) and the end point of the spline to be B
  2. spawn a specified number of spline points evenly spaced along the spline
  3. every road that is supposed to attach to a crossing has an enum (N/S/E/W) specifying the side of the intersection it starts/ends at
  4. knowing the size of the intersection mesh, I offset the points A and B by half the intersection mesh’s size in positive/negative x/y, depending on the enum
  5. adjust spline point number 1 and n-2 (where n is the last point of the spline) -> 2nd and 2nd to last in layman terms <- to be located at a specified world position. I get the specified points from the N/S/E/W enum mentioned above, by offsetting by a further variable value in the same direction I originally offset

Today is 3 weeks since I picked up UE4!

Since last post:


Road ends are now perfectly aligned to intersection - I had to adjust spline point number 2 and n-3 the same way as 1 and n-2, too, so that the tangent between 0/1 and n-1/n-2 remained constant regardless of other points, so that the end remains straight regardless of the rest of the spline


Improving the new minimap - red blip where the player is and more range

Today was supposed to be about improving the AI’s performance (as the road now stores the information whether it’s a turn or not), but the AI blueprint needed much cleanup first.

December just started, so I’m only a few days short of hitting a month of using UE4.

Progress has been slowed by working on AI in a separate branch (and then deleting a ton of files because they don’t work, and trying again, and again, and again…). Basically I have binned Peter Newton’s code apart from the MoveTo task he wrote, and rewritten the AI from scratch in hopes of making it better.

AI speeding away on a long straight
The AI also learned to avoid collisions a bit better, too thanks to using hit normal

Glow-in-the-dark road paint

Apart from AI and a couple of tricks, I have also replaced the test meshes with the actual assets I had acquired over the summer…


Moonrise in the city

Testing an effect for hot spots - race meeting spots, garage entrance, etc.


The road system now smooths the corners created by enforcing the ‘straight road ends’ rule - compare with post #11

Minimap now shows NPCs
The minimap is an orthographic camera positioned at a static z coord of -500 and the player’s x and y coords. It also inherits only yaw, so that it points down no matter what crazy spins the player might pull off.


The road system now removes all buildings that are either on road or collide with other buildings - it isn’t perfect but works for most cases

I also went back to static meshes instead of HISM for the buildings in the interest of performance (HISM seemed better for drawing but made it take too much time on physics/occlusion). Number of tris reported by stat engine dropped from 5,5 mil to 3,5 mil.
Game remains GPU-bound either way but it can get to 20+ fps instead of 15+.

Implemented a basic damage system
There are some problems to fix, so it’s player-only now. Mostly, it needs a cooldown so that repeated rubbing against stuff (or the AI trying to drive into you) don’t kill you

Basic main menu screen, random picture from the net included

f6bb1d0dd6f95760bd973b4a684977610c1ff51c.jpeg
Basic game over screen, random picture from the net

750f2eef7dfbdb57b30101d641c6471c11e58e5b.jpeg
The player now picks two Japanese characters to make his name, then the game displays the romanized version above the health bar and the kanji version on the nameplate

Someone pointed out that the blocks of flat are too small, so I upscaled them (adjusting road generation parameters accordingly)
Driving along the road with skyscrapers

Roads now have randomized names displayed above the minimap
Note: if you’re wondering about the white panels with arrows, they are a stopgap solution. Adding them improved the performance a bit because they occlude stuff behind. I recently swapped them out for a proper fence mesh.


New road layout - based on the same intersection layout as before, but the roads are laid out differently
Took me more time than I expected because the turn smoothing had to be updated to account for some configurations/directions.

Next week, next devlog :slight_smile:


Doubled the size of the grid so the roads are twice as long

Procedural guardrails on the hill
Bonus: no more floating buildings next to the hill

588188b7ceaee630153e7384fee7e838e6927ded.jpeg
Splines, splines, more splines. Seriously, why can’t I change the color of code-created splines to something other than PINK?!

I’ve spent the last three days working on AI exclusively. I am now printing a ton of stuff to screen, as well as showing even more debug markers (spheres, lines and cylinders). They tank my FPS but are very useful.

When the AI’s improved enough, I plan to unlink the print strings and change the debug markers to particles, as I noticed particles are more performant (especially since it would just be a beam particle for a line or a simple circle sprite for the others).

Anyway, what I achieved:

  • the AI can now predict it’s position after a second (current position plus it’s current speed in units per second)
  • the AI knows the angle between the predicted position and target position. It slows down (throttle 0.0) if the angle’s increasing

Note: I got those two ideas from here

  • Force a minimum throttle of 0.2 to prevent throttle being like, 0.0000012 due to floating point stuff (I don’t understand the exact throttle calculations since they are not mine, they were done in the free car AI project I used as a base. Something something to a power of something, ew…)

  • Noticed an AI on the right side of the road wasn’t set to use the right lane, which meant it swerved across the road to get to its lane. Fixed.

  • Print reversing status to screen

  • Steering values are obtained by mapping a range from -180 to 180 to a range of -1 to 1. Very small angles can then result in a steering value of 0.000023 or something which then fluctuate wildly. To prevent that, I made the AI altogether ignore the steering values smaller than 0.002

  • I tracked down excessive swerving to the AI obtaining the steering value close to the target. When not in line with the target, the angle could be very sharp (exceeding 50 degrees), which would then lead to a steering value of over 0.3. I made the AI ignore the value if the angle is over 45 degrees and the distance to target is less than 300 units (the car being 500 units long, so 250 units from origin point in the middle to the front).

  • Instead of having a big array of vectors for both driving lanes, I made a separate array for left lane and a separate array for right lane. Then I made a spline from each array. The end result looks ugly in editor but it works!

  • Since I’m using splines now, I made a function to get the closest point on the spline. (This would probably have been impossible for the ‘array of vectors’ approach) Unfortunately there’s no built-in version and no ‘get distance at location’ either :frowning: The thing only works for the control points, but I figured out how to use it for the AI to figure out it’s location along the spline effectively. Basically it gets the closest control point to its origin, but also to it’s back and front. I know it seems a little excessive, but it seems like a simple way to figure out if the AI is turned the wrong way (if the control point in front has a lower index than the one in the back, we’re facing the wrong way).

  • The closest control point thing seems to have allowed me to have a working check for ‘did we overshoot our target?’ at long last. At least, debugging the results of comparing the target index and closest index works as expected.

Bonus: a ton of blueprint cleanups (yes, I’m doing it all in blueprints for now - I’ve attempted Wednesday to get vs/ue4 working, but I still can’t get the required workflow. One or the other doesn’t see the files as added/changed)

I’ve made a big step forward. I succeeded in getting the required workflow for cpp in vs/ue4 sometime two days ago (thanks to https://github.com/runeabrahams1/Unreal-Engine-4-Bicycle-Simulator-with-AI) and tested it on a spare project.

Therefore the Racer Prototype project is no longer 100% blueprints. C++ handles the actual movement now and I managed to make it blueprint callable, so integrating it was as simple as unlinking a ton of nodes and replacing them with a single node that represents the Movement(FVector Destination) function :smiley: I based the movement function on the code from the git hub project I linked to above, but with some changes so that it doesn’t rely on nav mesh and is easier to integrate (ActorComponents ftw!)

AI that doesn’t swerve as much
There’s a downside: the cpp has no reversing, so far

I am thinking of moving the maths- or structs-heavy functions to cpp, too. The first candidate would probably be the grid creator blueprint (structs and editor lag due to 1200 elements in an array of structs), the second, the basic spline creator that is the parent blueprint class to the road tool itself.

It’s New Year’s Eve, and I’m one week short of two months of using UE4.

The same cpp that drives AI movement takes care of debug drawing. Therefore I could keep some of the debug prints without noticeable impact on performance.
Perf test
It’s running at 18-20 FPS in the gif, so about normal for this project on my rig

The AI can change lanes to drive back on a road which is not a loop. Behavior on a looping road (such as the one in most of the pictures) is unchanged.

It’s high time to make it an actual racer. Pressing ‘H’ on a hot spot now actually spawns AI racers and checkpoints. The racers don’t move because I presumably need to adjust the AI somewhat so that they navigate to the checkpoints.


Added some more procedural props. The thing hanging from the cable is supposed to be a round Asian-style lantern, but the scale might be a bit off.

I spent two days wrangling cpp code that was supposed to be equivalent to the basic ‘draw a spline’ blueprint. Turns out I had the working code by the end of the first day, but it was interpreting world-space coordinates as local(relative)-space, therefore causing an offset. The farther away from 0,0,0, the bigger the offset. I found the culprit and fixed it, though.

Design: I am massively happy with how easy cpp in UE4 is. I figured out how to make a function accessible in blueprints on day one of having visual studio actually work for ue4. A huge blueprint condensed to 100 lines of cpp.

Yesterday I realized I have a massive advantage that comes from having ue4 source code on disk (I thought of unticking it at install, and then went ‘eh, it’s 100 MB, let’s keep it’). Said source is missing dependencies, so I wouldn’t be able to compile any changes, but since I have it, I can just right click a blueprint node -> ‘go to definition’ and hey presto, I now know the cpp equivalent (the names of the nodes and the functions are NOT necessarily the same).

I am going to keep porting stuff to cpp. Blueprints have their uses, as far as the UI and animations and simple things are concerned, but they fall apart where one or more of the three is involved:

  1. inheritance (child blueprints have a known bug where they sometimes lose values and/or fail to invoke parent functions in the right order)

  2. maths (a relatively simple math equation such as (a*b)+(c+d) could easily take 5 or 10 nodes if variables or functions were used instead of hardcoded values)

  3. structs. Doing anything with structs in blueprints involves having to wire ALL the outputs of break struct into make struct if you’re changing ONE of them, otherwise they all get reset to default. This might not sound like a lot, but if you’re doing it more than once in a single bp, it quickly becomes an unreadable mess. In cpp, you just do RoadData.isTurn = true and are happy

Two months in, hooray!

Finished porting the basic ‘make a road’ code to cpp. This includes the ‘make a spline’ code from last week, and places buildings, road signs and various other stuff. This involved spending 2,5 days trying to track down a bug which was caused not by the code, but by a typo in the parameters in the actual game :frowning: Replaced the old handplaced road with the cpp-based one. Adjusted all the AI functions so that they can access the array of waypoints

Racer cars now get the correct AI upon spawning, so they can move. Bad news is, there is still no custom waypoints for a race, so they just drive along the road as the regular AI does

Worked on a garage level
If you hold down rmb, you can orbit the cam around the car.

Reaching the garage
Getting to garage from the city(world) map and placing a single decal on the car.
Nb. the decal doesn’t yet stick if you go back to the game - the garage map has to use a fake player with no car and I need to figure out where/how to store the information that needs to remain between maps.

You can recolor the car in garage and the color change sticks (the decal does not, yet)
Added VSync and AA settings to the pause menu. Pause menu can be brought up in-editor

Changed the way the minimap works to get a FPS boost. It hits 27-24 instead of 18-17 now.
Discovered the cause of FPS not exceeding 20… It was the minimap camera doing a scene capture every frame. It was an accident, I made a minimap off switch and saw the FPS rise, I switched off the camera as a test and still saw the rise while the dots were being rendered, so I started investigating. Now I capture the scene once, save to a texture and then pan the texture as the player moves.
e3d246f93755767ba77001ac021e542d78d195f1.jpeg
Added more lanterns to the road

I experimented some with visualizing the grid I’m using to place the buildings and intersections. Finally gave up on visualizing the whole grid and decided to just mark the grids I can’t build on:

Racer AI now moves to checkpoints correctly

Unfortunately the AI blueprints became such a mess that I spent yesterday moving the code to c++ because they are basically a chain of if/elses (“am I going back? do stuff in reverse order. else am I a racer? go to checkpoint. else am I at road end? go back else am I on a turn? BRAKE. else go to next turn at full speed”). The move is halfway done, I need to move the behavior tree tasks today.