09/10/2023 – Cybersurfer Update

Happy 11th birthday to the blog. It’s not that important of a milestone compared to last year, but worth noting nonetheless.

But let’s get to the real news:

I did mention this partial rewrite in the last blog post as the last post took so long to write (I was busy with stuff, not that the post was long) that some of the work was done. But now I can get into more detail.

The hoverboard is now a model on top of a collider, an upright capsule collider to be exact. Propulsion works in more or less the same way, but is currently fully controlled by the player. Furthermore, in my last iteration of the hoverboard, when turning, I had a part of the script that would animate the board’s model to tilt it when moving, giving it a more believable look. I’m just adding a smooth damp value to the model’s rotation based on the input. Here’s a code snippet:

Vector3 newRot = hoverboardModel.transform.localRotation.eulerAngles;
if (grounded)
{
    newRot.z = Mathf.SmoothDampAngle(newRot.z, input.x * rollTurnRotAngle, ref rollRotVelocity, turnRotSeekSpeed);
    //newRot.x = Mathf.SmoothDampAngle(newRot.x, slopeAngle, ref pitchRotVelocity, 0.05f);
    newRot.y = Mathf.SmoothDampAngle(newRot.y, 180f + (input.x * yawTurnRotAngle), ref yawRotVelocity, turnRotSeekSpeed);

hoverboardModel.transform.SetLocalPositionAndRotation(hoverboardModel.transform.localPosition, Quaternion.Euler(Vector3.Lerp(hoverboardModel.transform.eulerAngles, newRot, playerTurnTorque * Time.deltaTime)));
}

(I’ve highlighted the code because it’s hard to see with the dark theme)
I’ve continued with that feature and made further additions to it, which gives it a lot more of a snowboard turning look. That said, I’m not finished with it.

I played more games for research during the process of rewriting the code, and one of the games I played was Extreme G Racing. An interesting thing to note about the behaviour of that game is that the player has a very large turning circle. So large in fact, that it is very difficult to get the player to face the wrong direction as you’re more likely to collide into the sides than get the vehicle to turn around on the track. I might change the behaviour to match that at some point.

In regards to the physics, I do mention this in the video at the top: the player’s gravity is relative to them and not the global value. This is set to the normal of the surface they’re on. In theory, it helps keep the player connected to the surface they’re on a lot better and gives me more flexibility in terms of track design. Previously, I couldn’t create loops as the physics driven system I had previously would break and push the player away from the ground. And now I can make corkscrew and loop sections of track without issue.

Loop section.
Corkscrew section.

I’m really looking forward to making some new tracks with these mechanics; it’s certainly more interesting to look at than a flat track.

The big new thing is rails, and I didn’t really cover this in detail in the video, so I’ll be going into more depth about building it now.

My first attempt at this new version of rails involved making rails in Blender and then importing them into Unity, including even more CSV files with vertex points, and lining them up. As you can imagine this got very tedious extremely quickly and I began looking for alternatives.

Nothing to do with the text, I just thought this bug was funny.

I then updated Unity and began using its built-in spline tools to create the rails. As I said in the video, this worked great. But then I tried to use it with spline animate to have the player move on the things, and that’s where it fell apart. The camera was a jittery mess and the whole thing wasn’t smooth at all. So I deliberately made the splines linear instead of curves, then made a script that got all the waypoints on the line and used Vector3.MoveTowards to get the player to move along the rail path.

And it worked… Until I tried getting back on the rail to go in the opposite direction. This is when the trouble began. I had to figure out what direction the player was coming in from and their position on the rail. Plus some edge cases on top of that. This led to a lot of if statements, which I am not too happy with.

But as you can see, it did work. What came next was figuring out loop-de-loop rail sections. Which required further code changes and even more pain.

As you can see, the biggest issue was keeping the player upright properly while going through the loop. Unfortunately, I don’t really have a good solution for that problem with the system I’ve built. Someone did suggest to me pointing them up towards a point in the centre of the loop, but considering I’m going to arbitrarily build and place these rails, it seems like a lot of work, plus even more additional work if I edit anything thereafter.

I’ve been looking at the way other people and other games have built their rail grinding stuff, and more recent things seem to be using something similar to the spline animate system that the spline tools have built-in. So I may need to give it another chance and perhaps that’ll solve the issue.

One thing I am mostly happy with is the rail switching mechanic.

This took a lot longer to figure out, but the solution is quite simple in theory. When I’m on the rail and lean left or right, I shoot out a sphere cast (Spherical raycast) within a certain range to the left or right of the player. If it hits a rail, I then draw an arc from the player’s position to the hit position (Note that I said hit position, not spline track position). If the player then presses the jump button, I do a slerp using a sin wave to give it a curved arc. Here’s the code for that slerp:

private IEnumerator MoveToNextRail(RailSplineScript nextRailScript, Vector3 hitPoint)
{
    float timer = 0;
    float step = jumpTime / linePoints; //Line points refers to the number of points on the arc being drawn. More points = smoother arc.
    int i = 0;
    float progress = 0;
    Vector3 startPos = transform.position;
    while (progress < 1) //Should be using time progress, not number increments
    {
         progress = timer / jumpTime;
         transform.position = Vector3.Slerp(startPos, hitPoint, progress) + (transform.up * (jumpHeight * Mathf.Sin(progress * Mathf.PI)));
         timer += Time.deltaTime;
         yield return null;
    }
    transform.position = hitPoint;
    currentRailScript = nextRailScript;
    CalculateAndSetRailPos(); //Sets up some stuff for the spline points system mentioned earlier
    onRail = true;
}

It works pretty well; it’s not the smoothest looking thing in the world, but it does work. Although I suspect some of the issues with the smoothness have to do with the camera, which I will probably fix soon anyway. Another issue is just the positioning of the player themselves when they switch rails. They’re off-centre. It is a problem that eventually corrects itself as they keep going on the thing, but it is annoying.

But yeah, that’s the new stuff out of the way. As for improvements and what’s next, well here’s a list:

  • Fix the camera on rails
  • Change the rail system again and see if I can get spline animate working
  • Create tracks using the spline tool, minimising Blender usage for level creation
  • Create some levels using all the existing tools and mechanics (Demo!)
  • New character animations
  • Better foot placement on the board
  • Overhaul the trick system

I’m probably giving myself a lot more work to do than I’d like, but hopefully it works out. I really want this idea to work out. I’ve put so much time into it, and it’s really fun to just move around.

What Else Is Going On?

Well I did the WWII COD Marathon and it went alright. I gained some new followers out of it and some of them have hopped back into chat and such since. Wasn’t a massive gain, but whatever. The COD games I’ve never played before will be mentioned in the year end “ADMAN’s Den” post along with my usual top 10s, but I will say that I enjoyed WWII more than I thought I would, but it’s definitely got some issues.

I do want to do a highlight video for it, but honestly, after looking through the highlights for the first COD game, it’s very difficult to find clips that are worth putting in a video. I could make a death counter video, but I don’t think it would be that entertaining. So maybe what I’ll do is grab clips from all the games and shove them into one video instead of doing a video per game. More time spent in prep, but less time editing.

As I mentioned in the video at the top, Unity did something stupid, and now I’m finally in a position where I’m thinking of changing engines. But I want to do a video about the experience of learning new tools. However, since making the video, I’ve come to realise just how busy I am with all the videos I need to make and all the work that Cybersurfer still requires, and I think I might need to delay the original timeframe I wanted to work on it.

On that note, Rotaction needs to be updated soon, or it’s going to be pulled from the Google Play Store. Or at the very least, unavailable to download on modern phones. It will continue to be available on Itch.io, so don’t worry there. The deadline is November 1st, so I need to deal with that soon.

Another thing is back-porting the new hoverboard code into SandSurfer, and changing it to be an actual sand surfing board without all the hoverboard stuff. It’ll take some work, but hopefully it’ll be better than it currently is. But I have no idea when I’ll get a chance to work on it.

But that’s your update. Sorry for the radio silence, but that’s just how it is sometimes. I’ll probably post again once the demo is available for Demo Day. If I can get it working by then. Till next time.

-Adam