[WIP] Super 23 Racing

I’m creating this post to show the progress of my latest game, get feedback, perhaps get a bit of a following ready for launch and hopefully get help when I’m stuck with certain aspects during development. I’ll be trying to do an update at least once a week.

Super 23 Racing is a top down racing game, being developed for the PC (hopefully Steam) where players compete to earn points, money and unlock more tracks and cars. Points earn money, more points = more money, money is used to repair the player’s car and purchase weapons.

There are 4 cups to compete in, 3 include 5 tracks and the last cup includes 8 tracks (more to be added after launch, assuming all goes well). In between some tracks the player is taken to certain departments who will ask them questions, depending on the answers to these questions the player will receive extra money.

I’ve shared a few videos of progress on my YouTube channel, here.
The latest video embedded here

To do (ever changing and not yet complete):

  • Cars

  • Tweak each car so their stats are different

  • Weapons

  • Everything

  • Cups

  • Cup Management

  • Cup names

  • Race Management

  • TBD

  • Game Manager

  • Track car unlock progress

  • Track cup unlock progress

  • Multiplayer (to do near the end of development)

  • Splitscreen multiplayer for 2, 3 and 4 players

  • Controls

  • Improve the control system to be more robust and customisable for up to 4 players

  • U.I.

  • Decide on an art style

Done so far:

  • Cars

  • 14 car prefabs

  • Improved collision/ fix rotation on slopes

  • Added scriptable objects to manage the cars and their unique stats

  • Player Cars

  • Player can now fire forwards and backwards

  • Added respawning

  • Player can now select which car to use

  • A.I.

  • Movement around the track.

  • Checkpoints

  • Paths/ nodes

  • Enemies can now fire forwards and backwards

  • Added respawning

  • Characters

  • Added scriptable objects to manage the characters and their unique stats

  • Player can now select which character to use (currently has no in-game affect)

  • Race Management

  • Lap progress

  • Track car positions

  • Pass finishing positions over to the race finished screen

  • Finish creating the spawner, to place cars in the correct starting position

  • Create respawner, to place cars on the track when needed

  • Save finishing positions, and assign their points

  • Pass info to the cup manager

  • Camera

  • Make the camera dynamic, so that the player can see farther ahead depending on their direction

  • Environment

  • Improved the look of the water

[Edit: The solution to this is to give the two axis, that aren’t under player control, a lower value

goRigidbody.inertiaTensor = new Vector3(1e3f, 1e5f, 1e3f);

]

In this video, you can see that when a car collides with something it rotates in an annoying/ unnatural way.

It was suggested to me that I use

goRigidbody.inertiaTensor = new Vector3(1e5f, 1e5f, 1e5f);

Which makes the collisions work great, if not perfectly, however this introduces another problem, the cars no longer rotate properly when going up/ down a slope.

I’ve only really tried upping the gravity (from -9 to -50), I’m lost at what else to try, would really like some input and assistance on this particular problem!

Looks good! I’ve always liked top-down racing games

Looks fun! The game seems to be on the right path.

The physics do look a bit “floaty” and slippery in the video especially right in the beginning when the car is launched into the air. I don’t think I can help you out with the physics problem as I really haven’t messed with the physics system that much (most of the time I end up making custom physics, no need for complex physics in most of my games so far). I personally don’t think that it is a good idea to change the gravity to fix the problem, I feel like there is a better way. Are the colliders on the car and track lining up correctly? Maybe an axis is being limited in a direction. Sorry I can’t be of much help here.

neat. These kind of games can be fun … provided the control system works well and it doesn’t turn into a frustrating nightmare trying to just get around the track… why is is the camera centered toward the bottom of the screen, rather than giving enough look-ahead distance?

Thanks!

Using ‘inertiaTensor’ fixes the floatiness, and crappy collisions, but then introduces the other issue mentioned. The rigidbody is setup correctly to allow for rotating on the axis - the issue only occurs when I’m setting ‘inertiaTensor’.

With the setup used in the video, it can be frustrating to get around the track, until I use ‘inertiaTensor’ then it becomes super fun.

At the moment controls are simple and just wasd, but keeping the controls easy, intuitive and fun will be a focus - I’m planning to add support for control pads (Steam + XBox tested).

As for the camera, I haven’t done anything with that yet other than just set it up to follow the player and then gotten used to how it was. That obviously needs to be more dynamic, giving you more of a view ahead depending on which direction you’re heading.

1 Like

looks like a fun game, would love to try a demo!

Small update:

  • I fixed the issue I was having with cars going up hills, and edited the post in this thread with the fix.
  • I’ve now moved onto implementing some weapons, damage and respawning.

Here’s a new video of the weapons in development:

I’m showing two bugs in this video.
1- The wheels are left behind when a car is destroyed.
Due to the hierarchy of the car models, the mesh collider is a child object three deep from the parent, so disabling GameObject didn’t disable the entire car

I was using this.

GameObject parentGO = (GameObject) gameObject.transform.parent.gameObject;

To be able to disable the car completely, I had to disable the grandparent - is this an appropriate way to do it? Or is there a better way?

GameObject parentGO = (GameObject) gameObject.transform.parent.parent.gameObject;

2- The rockets rotate around with the car when the player turns. This is because when the rockets are instantiated, they spawn as a child object of the car they were fired from and then I’m using Physics.IgnoreCollision so the rocket doesn’t destroy that car, but consequently this means the rockets will rotate around the center of the car when the car rotates.

I haven’t fixed this yet, any suggestions on what to do?

Yea, but you may have to do each step separtely, so a couple get parent lines, or alternatively you could just assign a refference to the proper parent in the inspector

I’ve been away for a while, so haven’t been working on S23R, started developing it again recently. The updates aren’t very visual per se, so no screenshots/ video this time.

I now have a basic flow through the game. Menu → Cup select → race 1 → results → race 2 (grid positions based on previous race finishing positions) → results. I was stuck with this for quite a while, as I was unsure of how to:

  • give and store scores
  • add to the running total of scores
  • use the finishing order from the previous race to set the starting positions on the next race (finish first → start last OR finish last → start first)

I’m now using scriptable objects to achieve this, which was new to me. I’ll do a better write up of this in another post.

Today though, I fixed a bug I was having where if 1 AI car got had wheels off the ground, so wouldn’t move any more… ALL the AI cars would stop moving.
It was a silly mistake, I was using

    public static bool groundedL;
    public static bool groundedR;

Static variables used by all cars, d’oh. Now this has been changed, I haven’t observed this behaviour again.

I’ve also started looking into how to do the camera movement, following the car around but with the player car being closest to the edge it’s moving away from. Currently no idea how to do this … if anyone has any suggestions/ tutorials, I’d be most appreciative!

If you only need driving up/down slight slopes (not deep …hills) you can do this by just using the road-colliders normals at this point.

Also, when doing this you could switch from 3d physics to box 2D, faster :slight_smile:

I’m not quite sure what you mean @Dennis_eA , I’m also not sure I’ve made it clear what I’m trying to do. Hopefully this crudely drawn picture will demonstrate it better.

So, we have X at the center of the screen (pretend that it is…). I’d like to have the camera move slightly ahead of the car, no matter which direction it’s heading, so the player can see ahead of them.

1 is heading downwards, so becomes closer to the camera along the top of the screen.
3 is heading upwards, so does the opposite of 1, and gets closer to the bottom of the screen.
Same for 2 and 4, they’re close to the edge they’re heading away from.

Not got a clue how to achieve this atm.

I assume you use rigid bodies (3d) and your car in - in my example - is the transform object.

Create a GameObject called “CamTarget” - this will be the (main)cameras parent. I assume you want a simple top down camera - so the (local) position of the main camera* would be something like x0 y50 z0 Rot: x90 y0 z0
(* inside / parented to CamTarget)

Now, CamTarget.position = transform.position would tie the camera fixed (but floating above it) to the car (the transform in this case)

2.:
if (rigidbody.velocity.magnitude > 0.05) {
CamTarget.position = transform.position + rigidbody.velocity.normalized * 2.0;
}
would make the Camera look ahead in the players direction 2 meters / units.

if (rigidbody.velocity.magnitude > 0.05) {
CamTarget.position = Vector3.Lerp(CamTarget.position, transform.position + rigidbody.velocity.normalized * 2.0, Time.deltaTime * lerpSpeed)
}

for smooth movement

4.: you could easily alter this to make it look ahead more / or less based on the speed. This would make a nice effect together with a slight change in the cameras FOV. if you need help with this, just ask :slight_smile:

all this is pseudo code, and I use unity script - but: not tested :smile:
place all camera stuff inside LateUpdate();

get the newly instantiated transform or game object (the rocket) → SomeRocket.
SomeRocket.parent = null;

D’oh, so obvious!

I do not guarantee that …parent = null; is the fastest or most elegant way. dunno why, but hey I am not a pro or something.
but you should get rid of instantiating and use a pooling work flow any way :roll_eyes:=)

did the camera stuff work for you?

Working on it now, trying to figure out how to ignore the y axis and make it smooth.

I don’t understand where in your code you want to lock the y axis, but be aware that in most cases often it’s absolutely okay to work with Vector3s and re-center one axis, one line later in the code. This is something simple, I wasn’t aware of in the first years of scripting (doh) :wink:

Example:

somePositionOrAngle = SuperCoolVector
somePositionOrAngle.y = 0.0;

And because you Will run into one particular issue concerning angles, when coding camera-movement stuff if you are not aware of the existence: When lerping angles use Mathf./Vector3.Lerp__Angle__ :wink:

I am working on a topdown racer myself atm, so just ask if you need help.

Yeah, I’m aware of being able to change an axis of a Vector 3, I was having a slow day and trying to work out when to set it. Anyway, with the help of some other game devs (I was at a game dev dev day) and your help, I’ve got it working. Vid above to see it in action, and below is how I did it.

I had to use FixedUpdate, not LateUpdate, because the gameobject being followed (the player car) is moved in FixedUpdate. Having the car move via FixedUpdate and the camera move via LateUpdate caused a lot of jerky movement - I’m assuming/ guessing the two were out of sync with each other.

using UnityEngine;
using System.Collections;

public class CameraFollow : MonoBehaviour
{
    private GameObject player;
    private Rigidbody playerRigid;
    private Transform playerTransform;
    private Vector3 playerPos;

    public float lerpSpeed = 0.1f;

    public float followDist = 5.0f; // how close to the edge of the camera the player will be

    private Vector3 normVelocity;

    void Start ()
    {
        player = GameObject.FindGameObjectWithTag("Player");
        playerRigid = player.GetComponent<Rigidbody> ();
        playerTransform = player.transform;
        transform.position = playerTransform.position;
    }
  
    void FixedUpdate ()
    {
        float tweenPercent = 1f;
        float maxStartPercent = 10f;
        if (playerRigid.velocity.magnitude < maxStartPercent)
        {
            tweenPercent = playerRigid.velocity.magnitude /  maxStartPercent;
        }
            normVelocity = playerRigid.velocity.normalized;

        playerPos = new Vector3 (playerTransform.position.x + normVelocity.x * followDist * tweenPercent,
                                   playerTransform.position.y,
                                playerTransform.position.z + normVelocity.z * followDist * tweenPercent);

            transform.position = Vector3.Lerp (transform.position, playerPos, lerpSpeed);

    }
}

Great.

Please, test the following:

  1. In the rigidbodies inspector set interpolation to Interpolate AND put your camera stuff back into LateUpdate (this is were it belongs…)

  2. Modify the (Edit-> Time) Time Manager to 0.1666667 (for 60fps), max Step 0.1 Scale 1

(1.) alone should help and solve the jittering. If not, there is some problem which should NOT be solved by placing camera stuff inside Fixed Update IMO.