top of page

APART

Team

Project Length

Roles

Engine

Plateform

8 persons

8 months

Unity

PC

Gamplay programmer,

2D Artist

Apart is the game I’m currently working on, it’s 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’m in charge of part of the gameplay, the camera system but also concept art.

APART_Affiche.png

The game cover

capture1.png
capture.png

In-game screenshots

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

Caméra

 

Le premier point que je souhaiterais détailler sur ce projet est le système de caméra.

En effet, le but étant de créer une expérience contemplative, la caméra est un élément central de notre jeu.

Il nous fallait une caméra très discrète mais également suffisamment autonome afin de pouvoir accompagner le joueur dans son exploration sans le gêner.

Une de mes principales inspirations pour ce système est la caméra de Journey (ThatGameCompany), notamment pour sa mise en valeur de l'environnement et sa gestion des obstacles.

Toutefois, contrairement à Journey, notre jeu comporte plusieurs protagonistes : le berger, les moutons et le chien. Il m'a donc fallut adapter les point de focus de la caméra en fonction des situations et de nos besoins.

Le jeu étant développé sur Unity, j'ai décidé d'utiliser les outils Cinemachine disponibles afin de mettre en place une caméra FreeLook, c'est-à-dire libre autour du personnage, paramétrable sur 3 niveaux.

Afin de "smoother" les transitions de hauteur de caméra, j'ai mis en place un simple script modifiant la vitesse de déplacement sur l'axe Y en fonction de cette hauteur. Ainsi, le changement de distance semble plus dynamique et plus réactif.

camera_freelook.gif

Déplacements de la caméra tout autour du personnage

Le second élément est probablement le plus important de part son étroite liaison avec notre gameplay.

Il s'agit d'intégrer les moutons autant que possible aux plans de caméra.

En effet, comme le but de notre jeu est de guider avec succès le troupeau à travers la montagne, le joueur doit pouvoir à la fois garder vue sur son personnage mais aussi sur ses moutons.

Pour cela, j'ai utilisé le TragetGroup de Cinemachine en venant y apporter certaines modifications via script.

J'update le poids du troupeau en fonction de la direction dans laquelle regarde la caméra. Par exemple, si la camera regarde dans la direction générale du troupeau, son poids augmentera. En revanche, si la caméra tourne le dos au troupeau, le poids de ce dernier sera nul pour ne pas gêner. 

Comme le poids du berger reste constant, le cadrage du plan s'adapte donc dynamiquement.

camera_targetGroup.gif

Update du weight du troupeau en fonction de la direction de la caméra

Un autre élément particulièrement important d'un système de caméra est sa gestion des collisions et des obstacles.

En ce qui concerne les collisions, le component Cinemachine Collider est utilisé pour gérer les collisions avec les limites invisibles du niveau. Toutefois, les collisions avec le terrain sont gérées par un système custom à base de raycast tiré vers le sol.

Enfin, notre niveau comporte un certains nombre d'obstacles derrière lesquels le berger pourrait disparaître et qui pourraient gêner la vue. J'ai donc mis en place un système d'anticipation d'obstacles.

schémas_raycast-cam.png

Raycasts tirés depuis la caméra vers les côtés du berger

Pour cela, 4 raycasts sont lancés de chaque côté de l'avatar, en partant de la caméra vers le berger, pivotant à chaque fois de 5°, comme sur le schéma ci-contre.

Ainsi, il est possible de détecter un obstacle sur un côté du personnage.

Si ce dernier se dirige vers cet obstacle, la caméra peut anticiper ce mouvement en venant tourner d'elle-même pour éviter que le berger ne disparaisse derrière.

camera_onstacle.gif

Anticipation d'obstacle et transparence de l'objet quand disparition - sans input sur la caméra

Afin de compléter ce système, si le berger disparaît tout de même derrière un objet, comme un arbre par exemple, ce dernier vient changer momentanément de matériau afin de pouvoir passer en transparence.

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 bellow

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

Enfin, en ce qui concerne les tâches autres que la programmation sur lesquelles je travaille, j’ai réalisé un certain nombre de concepts arts pour le projet dans le cadre de la préproduction.


En effet, lorsque le projet était encore à l’état de concept, il fallait donner des visuels pour l’ambiance générale du jeu mais également pour les artistes 3D afin de définir précisément la DA.

C’est pour cela que j’ai réalisé différentes planches de concept pour les assets d’environnement mais également les personnages du berger et du chien.

J'ai également eu l'occasion de réaliser l'affiche pour notre jeu.

Quelques dessins que j'ai pu réaliser pour le projet

bottom of page