Sands Adrift

...

See the team and download the game on the official game page on Itch.io here

About

This game is made as part of a special semester called DADIU. DADIU is a program worth 30 etcs points and spans a whole semester. The goal of the program is to give students experience closer to what it would be like in a proper production environment. There are multiple teams which consist each of 15-20 students from diverse studies and with very different skillsets.
I chose this program to experience work in large groups, not something that happens often in a university environment. I also really wanted to be part of creating a more refined, complete game.

DADIU consist of 3 main phases.
The first two phases are the prototype phases and are around 7 days long each.
The purpose of the prototype phases is for one to accustom the team to each other but also to explore ideas for what game we would want to make in the last phase.
The last phase is the big phase going for around 6-8 weeks. This phase is where we our make the main game, which is in our case Sands Adrift.

My Part

With a long production time I have been involved with a couple of different parts, but I want to highlight two things I have worked on. First the movement of the vessel which is the part that were my main responsibility, then secondly the optimization of the spirits.

The movement

The movement was something I worked on in all 3 phases of DADIU. The goal of the movement was to create some sort of combination of a glider and surfboard. The vessel would gain speed, going downhill and lose speed going uphill. At some point, when the vessel gets enough speed it should be possible to glide in the air for some time. Throughout the development of the movement I collaborated closely with one of the designers on the team.

The first iteration
The first iteration of the movement was very exploratory since it was my first time working on something like this. With the first iteration I went in with the assumption that relying mostly on the physics system made sense. However, it led to a couple of big issues.
One issue was that the velocity was too hard to control and led to a very inconsistent experience. I tried to mitigate this with forcing a certain controlled max speed, but in the end, it was still not great.
Another issue was that small bumps or edges on the terrain could make the vessel flip out of control. For this one I tried a couple of things such as increasing the mass of the vessel and/or creating a downward force. It did help a bit but didn't ultimately stop it before I rewrote the movement in the final iteration.
The video shows my first version of our movement after phase 1.


The final iteration
With the learnings I took from the first iteration of the movement, I decided to remake the whole logic inspired by the tutorials here. Instead of applying force to the vessel and then rely on physics, I modify the velocity variable of the rigidbody instead.
This has some distinct advantages as it gives me more direct control over the movement of the vessels. I learned from the previous version that instead of relying purely on physics we want to be more in control, so it makes sense to more directly control velocity.
Another thing added were snapping to the ground. This were added mostly to avoid small bumps in the terrain sending the vessel flying, but it also allowed us in general to control the easiness of going into the air.

The video shows my second version of our movement after phase 3.

The new movement allowed for more consistent experiences and more control for the player. Also to allow the designers some freedom in customizing the movement I exposed a lot of variables in the inspector.
...


Optimization of spirits

A thing we really wanted for the game was to include spirits that sort of roamed the world. We also want it to interact both with the player whenever they were in the vicinity of each other, but also with the thread that the player places in the world as they go through the big checkpoints.
The spirits are based on the boids algorithm and where implemented by one of the other programmers on the team.
but we had an issue with having more than a couple thousand spirits active in the game at once, which is not enough to really fill out the world we had created. So, since both of us were interested in optimization, we grouped up to work on it.

We started out with rewriting the logic into using unity's job system.
This allowed us to parallelize most of the calculations, and thereby significantly cutting calculation time down.
However, we still had a big bottleneck. The only thing we couldn't parallelize is when trying to avoid collisions, this is a limitation on how the physics world normally works but we could still field more than 10-thousand spirits now.
To fix this bottleneck, I found that using Unity's entity component systems framework would allow to have multithreaded physics in their 'sub-worlds'. So, we rewrote our spirits to work in this new framework. The framework naturally worked well with multithreading and the way it stores information about entities and components where a lot more cache friendly than the traditional scene hierarchy. So this alone gave decent speed ups on performance, together with allowing for a multithreaded physics world. In the end we now had close to 40-thousand spirits in the game without performance issues.

Gameplay video