Comment construire un système de retour rapide dans le style Prince-of-Persia, première partie

Ce que vous allez créer

Dans ce tutoriel, nous allons construire un jeu simple où le joueur peut rembobiner progrès dans l’Unité (il peut également être adapté pour fonctionner dans d’autres systèmes). Cette première partie abordera les bases du système et la prochaine partie le précisera et le rendra beaucoup plus polyvalent..

Tout d’abord, examinons quels jeux l’utilisent. Ensuite, nous examinerons les autres utilisations de cette configuration technique avant de créer finalement un petit jeu que nous pouvons rembobiner, ce qui devrait vous donner une base pour votre propre travail..

Une démonstration de la fonctionnalité de base

Pour ce faire, vous aurez besoin de la dernière version de Unity et vous devez avoir une certaine expérience de ce logiciel. Le code source est également disponible au téléchargement si vous souhaitez vérifier vos progrès par rapport à celui-ci..

Prêt? Allons-y!

Comment cela a-t-il été utilisé auparavant??

Prince of Persia: les sables du temps est l'un des premiers jeux à intégrer véritablement un mécanisme de remontage du temps dans son gameplay. Lorsque vous mourez, vous ne devez pas simplement recharger, vous pouvez plutôt rembobiner le jeu pendant quelques secondes pour retrouver votre vie, et réessayer immédiatement..

Prince de Perse, les sables oubliés. le Sables Du Temps Trilogy intègre parfaitement le rembobinage du temps dans son jeu et évite les recharges rapides en immersion..

Cette mécanique est non seulement intégrée au gameplay, mais également au récit et à l'univers, et est mentionnée tout au long de l'histoire..

D'autres jeux qui utilisent ces systèmes sont Tresser, par exemple, qui est également centré sur le remontage du temps. Le héros Tracer dans Overwatch a un pouvoir qui la réinitialise à une position il y a quelques secondes, essentiellement rembobinage son temps, même dans un jeu multijoueur. le LA GRILLE-La série de jeux de course comporte également un mécanisme d’instantané, dans lequel vous disposez d’un petit groupe de rembobinages pendant une course, auxquels vous pouvez accéder en cas de chute critique. Cela évite la frustration provoquée par des accidents en fin de course, ce qui peut être particulièrement exaspérant..


Lorsque vous avez un accident mortel dans LA GRILLE vous avez la possibilité de rembobiner le jeu jusqu'à un point avant le crash.

Autres utilisations

Mais ce système ne peut pas seulement être utilisé pour remplacer une économie rapide. Une autre façon de l'utiliser est le fantôme dans les jeux de course et le mode multijoueur asynchrone.

Rediffusions

Les rediffusions sont un autre moyen amusant d’utiliser cette fonctionnalité. Cela peut être vu dans des jeux comme TRÈS CHAUD, la Vers séries, et à peu près la majorité des jeux de sport.

Les rediffusions de sports fonctionnent de la même manière qu’elles sont présentées à la télévision, où une action est montrée à nouveau, éventuellement sous un angle différent. Pour cela, non pas une vidéo est enregistrée, mais plutôt les actions de l'utilisateur, ce qui permet à la relecture d'utiliser différents angles et plans de caméra. Les jeux Worms utilisent cela de manière humoristique, où les exploits très comiques ou efficaces sont montrés dans un Instant Replay.

SUPERHOT enregistre également votre mouvement. Lorsque vous avez fini de jouer, toute votre progression est rejouée, montrant les quelques secondes de mouvement réel qui s'est passé..

Super Meat Boy l'utilise de manière amusante. Lorsque vous avez terminé un niveau, toutes vos tentatives précédentes sont rediffusées, votre point final étant le dernier rang restant..

La relecture de fin de niveau dans Super Meat Boy. Chacune de vos tentatives précédentes est enregistrée puis lue en même temps.

Fantômes d'essai

Fantômes de course est une technique dans laquelle vous concourez pour le meilleur temps sur une piste vide. Mais en même temps, vous courez contre un fantôme, qui est une voiture fantomatique et transparente, qui conduit exactement de la même manière que vous avez couru auparavant. Vous ne pouvez pas entrer en collision avec elle, ce qui signifie que vous pouvez toujours vous concentrer sur le meilleur temps.

Au lieu de conduire seul, vous arrivez à rivaliser contre vous-même, ce qui rend les courses contre la montre beaucoup plus amusantes. Cette fonctionnalité apparaît dans la majorité des jeux de course, de la Besoin de vitesse série à Diddy Kong Racing.

Racing un fantôme dans Trackmania Nations. Celui-ci a la difficulté d'argent, ce qui signifie que je vais obtenir la médaille d'argent si je les bat. Notez le chevauchement dans les modèles de voiture, montrant que le fantôme n'est pas corporel et peut être conduit à travers.

Fantômes multijoueurs

Le mode multijoueur asynchrone est un autre moyen d’utiliser cette configuration. Dans cette fonctionnalité rarement utilisée, les matchs multijoueurs sont réalisés en enregistrant les données d’un joueur, qui envoie ensuite sa course à un autre joueur, qui peut ensuite combattre. contre le premier joueur. Les données sont appliquées de la même manière qu'un fantôme de contre la montre, sauf que vous affrontez un autre joueur..

Une forme de ceci apparaît dans le Trackmania-jeux, où il est possible de courir contre certaines difficultés. Ces coureurs enregistrés vous donneront un adversaire à battre pour une certaine récompense.

Montage de film

Peu de jeux proposent cela dès le départ, mais bien utilisé, il peut être un outil amusant.Team Fortress 2 offre un éditeur de replay intégré, avec lequel vous pouvez créer vos propres clips.

L'éditeur de relecture de Team Fortress 2. Une fois enregistré, un match peut être vu de n'importe quelle perspective, pas seulement celle du joueur..

Une fois la fonctionnalité activée, vous pouvez enregistrer et regarder les matchs précédents. L'élément essentiel est que tout est enregistré, pas seulement votre vue. Cela signifie que vous pouvez vous déplacer dans le monde du jeu enregistré, voir où tout le monde se trouve., et avoir le contrôle du temps.

Comment le construire

Afin de tester ce système, nous avons besoin d'un jeu simple où nous pouvons le tester. Créons un!

Le joueur

Créez un cube dans votre scène, ce sera notre personnage-joueur. Puis créez un nouvel appel en script C # Player.cs et adapter le Mettre à jour()-fonction à ressembler à ceci:

void Update () transform.Translate (Vector3.forward * 3.0f * Time.deltaTime * Input.GetAxis ("Vertical")); transform.Rotate (Vector3.up * 200.0f * Time.deltaTime * Input.GetAxis ("Horizontal")); 

Cela gérera les mouvements simples à l'aide des touches fléchées. Attachez ce script au cube du joueur. Quand vous frappez maintenant, vous devriez déjà pouvoir vous déplacer.

Puis inclinez la caméra pour qu’elle voie le cube d’en haut, avec un espace sur le côté où on peut le déplacer. Enfin, créez un avion pour agir en tant que sol et assigner des matériaux différents à chaque objet, de sorte que nous ne le déplaçons pas à l'intérieur d'un vide. Ça devrait ressembler à ça:

Essayez-le et vous devriez pouvoir déplacer votre cube en utilisant le WSAD et les touches fléchées.

Le TimeController

Maintenant, créez un nouveau script C # appelé TimeController.cs et l'ajouter à un nouveau GameObject vide. Ceci gérera l'enregistrement réel et le rebobinage ultérieur du jeu..

Afin de faire ce travail, nous allons enregistrer le mouvement du personnage du joueur. Lorsque nous appuierons ensuite sur le bouton de rembobinage, nous adapterons les coordonnées du joueur. Pour ce faire, commencez par créer une variable pour contenir le lecteur, comme ceci:

joueur public GameObject;

Et affectez l'objet joueur à l'emplacement résultant sur TimeController, afin qu'il puisse accéder au joueur et à ses données..

Ensuite, nous devons créer un tableau contenant les données du joueur:

public ArrayList playerPositions; void Start () playerPositions = new ArrayList (); 

Ce que nous ferons ensuite, c’est enregistrer continuellement la position du joueur. Nous allons enregistrer la position du joueur dans la dernière image, celle du joueur il y a 6 images et celle du joueur il y a 8 secondes (ou quelle que soit la durée pendant laquelle vous définissez l'enregistrement). Plus tard, lorsque nous appuierons sur un bouton, nous reculerons dans notre tableau de positions et nous l'attribuerons image par image, ce qui donnera une fonction de rembobinage dans le temps..

Premièrement, sauvegardons les données:

void FixedUpdate () playerPositions.Add (player.transform.position); 

dans le FixedUpdate ()-fonction on enregistre les données. FixedUpdate () est utilisé car il fonctionne à une vitesse constante de 50 cycles par seconde (ou quoi que vous configuriez), ce qui permet un intervalle fixe pour enregistrer et définir les données. le Mettre à jour()-la fonction fonctionne pendant ce temps en fonction du nombre d'images gérées par le processeur, ce qui rendrait les choses plus difficiles.

Ce code stockera la position du joueur de chaque image dans le tableau. Maintenant, nous devons l'appliquer!

Nous allons ajouter une vérification pour voir si le bouton de rembobinage a été enfoncé. Pour cela, nous avons besoin d'une variable booléenne:

public bool isReversing = false;

Et un chèque au Mettre à jour()-fonction pour le définir selon que nous voulons rembobiner le gameplay:

void Update () if (Input.GetKey (KeyCode.Space)) isReversing = true;  else isReversing = false; 

Pour que le jeu fonctionne en arrière, nous allons appliquer les données au lieu d'enregistrerLe nouveau code d'enregistrement et d'application de la position du joueur devrait ressembler à ceci:

void FixedUpdate () if (! isReversing) playerPositions.Add (player.transform.position);  else player.transform.position = (Vector3) playerPositions [playerPositions.Count - 1]; playerPositions.RemoveAt (playerPositions.Count - 1); 

Et l'ensemble TimeController-script comme ceci:

utiliser UnityEngine; using System.Collections; Classe publique TimeController: MonoBehaviour public GameObject player; public ArrayList playerPositions; public bool isReversing = false; void Start () playerPositions = new ArrayList ();  void Update () if (Input.GetKey (KeyCode.Space)) isReversing = true;  else isReversing = false;  void FixedUpdate () if (! isReversing) playerPositions.Add (player.transform.position);  else player.transform.position = (Vector3) playerPositions [playerPositions.Count - 1]; playerPositions.RemoveAt (playerPositions.Count - 1); 

En outre, n'oubliez pas d'ajouter un chèque à la joueur-classe pour voir si le TimeController est actuellement en train de rembobiner ou non, et ne bouge que s’il n’inverse pas. Sinon, cela pourrait créer un comportement buggy:

utiliser UnityEngine; using System.Collections; public class Player: MonoBehaviour private TimeController timeController; void Start () timeController = FindObjectOfType (typeof (TimeController)) en tant que TimeController;  void Update () if (! timeController.isReversing) transform.Translate (Vector3.forward * 3.0f * Time.deltaTime * Input.GetAxis ("Vertical")); transform.Rotate (Vector3.up * 200.0f * Time.deltaTime * Input.GetAxis ("Horizontal"));  

Ces nouvelles lignes trouveront automatiquement le TimeController-objet dans la scène au démarrage et vérifiez-le pendant l'exécution pour voir si nous jouons actuellement au jeu ou si nous le rembobinons. Nous ne pouvons contrôler le personnage que lorsque nous ne sommes pas en train d'inverser le temps.

Vous devriez maintenant pouvoir vous déplacer dans le monde et rembobiner votre mouvement en appuyant sur la touche espace. Si vous téléchargez le package de génération joint à cet article et ouvrez TimeRewindingFunctionality01 vous pouvez l'essayer!

Mais attendez, pourquoi notre simple joueur-cube continue de regarder dans la dernière direction dans laquelle nous les avons laissés? Parce que nous ne sommes pas parvenus à enregistrer également sa rotation!

Pour cela, vous avez besoin d’un autre tableau qui conserve ses valeurs de rotation, l’instancie au début, et qui enregistre et applique les données de la même manière que nous avons traité les données de position..

utiliser UnityEngine; using System.Collections; Classe publique TimeController: MonoBehaviour public GameObject player; public ArrayList playerPositions; public ArrayList playerRotations; public bool isReversing = false; void Start () playerPositions = new ArrayList (); playerRotations = new ArrayList ();  void Update () if (Input.GetKey (KeyCode.Space)) isReversing = true;  else isReversing = false;  void FixedUpdate () if (! isReversing) playerPositions.Add (player.transform.position); playerRotations.Add (player.transform.localEulerAngles);  else player.transform.position = (Vector3) playerPositions [playerPositions.Count - 1]; playerPositions.RemoveAt (playerPositions.Count - 1); player.transform.localEulerAngles = (Vector3) playerRotations [playerRotations.Count - 1]; playerRotations.RemoveAt (playerRotations.Count - 1); 

Essaye le! TimeRewindingFunctionality02 est la version améliorée. Maintenant, notre cube-joueur peut reculer dans le temps et ressemblera à ce qu'il était à ce moment-là..

Conclusion

Nous avons construit un prototype de jeu simple avec un système de remontage du temps déjà utilisable, mais c'est loin d'être terminé. Dans la prochaine partie de cette série, nous allons le rendre beaucoup plus stable et polyvalent, et ajouter quelques effets intéressants. 

Voici ce qu'il nous reste à faire:

  • N'enregistrez que toutes les 12 images environ et interpolez entre les images enregistrées pour économiser sur la charge de données considérable
  • Enregistrez uniquement les ~ 75 dernières positions et rotations de joueurs pour vous assurer que la matrice ne devient pas trop lourde et que le jeu ne plante pas

Nous verrons également comment étendre ce système au-delà du personnage du joueur:

  • Enregistrez plus que le joueur
  • Ajouter un effet pour indiquer que le rembobinage est en cours (comme le flou VHS)
  • Utilisez une classe personnalisée pour maintenir la position et la rotation du joueur au lieu des tableaux