top of page

APART

Team

Project Length

Roles

Engine

Platform

8 people

8 months

Unity

PC

Game Designer, Gameplay programmer, 2D Artist

Apart is the game I worked on as my end-of-studies project at ESMA.
 

This is a contemplative game experience where the player is a young shepherd who embarks on his very first transhumance with his new dog and sheep herd.

 

I was in charge of thinking through and developping part of the gameplay along with the camera system. I also worked on concept art.

APART_Affiche.png

The game cover

capture1.png
capture.png

In-game screenshots

------------------------

Camera

 

The first point I would like to detail about this project is the camera system.

The goal being to create a contemplative experience , the camera is a central element of our game.

We needed a very discreet camera but also one that would be autonomous enough to accompany the player in their exploration without disturbing them .

One of my main inspirations for this system is the camera from Journey (ThatGameCompany), particularly for its environmental enhancement and obstacle management.

However, unlike Journey, our game features multiple protagonists : the shepherd, the sheep, and the dog. So I had to adapt the camera's focus points based on the situations and our needs.

The game being developed on Unity, I decided to use Cinemachine tools in order to set up a FreeLook camera. It is a camera moving freely around the character, configurable on 3 levels of height.

To smooth out the camera height transitions, I implemented a simple script that changes the Y-axis movement speed based on the distance to the player.

For example, the closer the camera gets to the player, the slower it moves. In contrary, the farther it gets, the faster it moves. This makes the distance change appear more dynamic and responsive.

camera_freelook.gif

Camera movements around the character

The second element is probably the most important because of its close connection with our gameplay.

It's about integrating the sheep into the camera shots as much as possible.

As the goal of our game is to successfully guide the flock through the mountain , the player must be able to keep an eye on both his character and his sheep at the same time.

For this, I used Cinemachine's TragetGroup and made some modifications via script.

I update the weight of the herd depending on the direction the camera is looking. 

For example, if the camera is looking in the general direction of the herd , its weight will increase . On the other hand, if the camera is facing away from the herd , the herd's weight will be zero so as not to get in the way.

As the shepherd's weight remains constant, the framing of the shot adapts dynamically.

camera_targetGroup.gif

Update of the herd weight based on the camera direction

Another particularly important element of a camera system is its collision and obstacle management.

Regarding collisions , the Cinemachine Collider component is used to handle collisions with the invisible boundaries of the level. However, collisions with the terrain are handled by a custom system based on raycasts fired towards the ground.

Finally, our level has a number of obstacles behind which the shepherd could disappear and which could obstruct the view. So I implemented an obstacle anticipation system .

schémas_raycast-cam.png

Raycasts fired from the camera to the sides of the shepherd

To achieve this, 4 raycasts are launched on each side of the avatar , starting from the camera towards the shepherd, rotating each time by 5°, as in the opposite diagram.

Thus, it is possible to detect an obstacle on one side of the character.

If the latter moves towards this obstacle , the camera can anticipate this movement by turning itself to prevent the shepherd from disappearing behind.

camera_onstacle.gif

Obstacle anticipation and object transparency when disappearing - without input

To complete this system , if the shepherd still disappears behind an object, such as a tree for example, the obstacle will momentarily change material in order to become transparent .

The thing I would especially like to detail here is the flowfield system developed for our AI.

Its main purpose is to influence character’s movement in special cases.

Indeed, our sheep and dog move according to a navmesh. We give them a destination and the intermediate positions are automatically calculated.
 

However, there were situations where the characters had to follow a specific path.
 

A good example is the sheep fence passage.
When sheep get close enough to a fence, they get attracted to it depending on their distance. That way, we can subtly help the player in their herd control.

Flowfield_gif.gif

Herd following the flowfield below

In the first instance, I created a gameobject grid, each positioned at regular intervals to set up the area of effect. The forward direction of each gameobject corresponds to the direction it will give back.

That way, each gameobject can be oriented to give the overall movement to the grid.

grid_apart.gif

(The arrow sprites are only used for debug)

Then, I created a script to manage all those vectors.

At initializing, the script runs through each object, gets its position floored to the closest int as well as the forward vector and stores them both in a dictionary.

 

To make position comparison (between the sheep and the grid cell) easier, every position is converted into a Vector2Int.

Indeed, because our terrain is especially hilly and there’s no superimposed levels, there’s no need for the Y value. The X and Z values are stored into a 2 dimensions vector, with values rounded down to the nearest whole number.

Therefore, if the rounded vectors are the same, the sheep is indeed on the cell, whatever its exact position on it is.

 

There’s multiple contexts where AI must follow a flowfield : 

  • Specific area related to the terrain (fence, topology…)

  • Situation related to orders given to the dog that can trigger anywhere (dog following the herd, stopping the sheep…)

fence_gif.gif

Fence flowfield

The flowfield activation can be triggered by a collider (specific area) but also by changing state into the StateMachine (order).

 

In both cases, when the AI starts following a flowfield, it will look for its own rounded down position into the grid dictionary. If the position does exist, it will return the associated direction vector and update the navmesh agent destination.

------------------------

------------------------

Concept Art

Finally, I have also worked on other tasks besides game design and programming.

During preproduction, I've done various concept arts for the project.


Indeed, when the project was still in the concept stage, it was necessary to provide visuals for the overall atmosphere of the game but also for the 3D artists.

That's why I created different concept boards for the environment assets as well as character design for the shepherd and dog.

I also had the opportunity to create the game poster !

Some drawings that I was able to make for the project

bottom of page