Par défaut, en utilisant le FPSController fourni par Unity, lorsque l'on saute sur une plateforme animée, le FPSController ne suit pas le mouvement de celle-ci ; il reste sur place alors que la plateforme subit des déplacements horizontaux (lors de déplacements verticaux, le problème ne se pose pas).
L'idée est qu'il faut "parenter" le FPSController temporairement à la plateforme. Il subira alors toutes les transformations de celle-ci (position, rotation, et même scale).
Un problème vient se poser alors : les seules informations dont nous avons besoin sont la position et la rotation. Nous allons devoir compenser le scale...
Plutôt que de longues explications, voici le script que nous allons pouvoir utiliser, accompagné de commentaires permettant de comprendre les calculs effectués :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
/* PlatefromGrip v1.2 * * * EDIT : 28/01/2017 * - Prise en charge du cas de contact simultané avec plusieurs plateformes * * * Lors de l'utilisation du FPSController dans un jeu de plateforme, nous sommes évidemment tenté de le faire sauter * sur des plateformes animées. * Sans ce script, le FPSController ne suit pas le mouvement de la plateforme et tombe pendant son animation (notamment * lors de translations horizontales). * * Ce script part de l'idée de parenter temporairement le FPSController à la plateforme touchée, lui transmettant donc * toute transformation (position, rotation & scale). * L'intérêt étant d'utiliser la position de la plateforme, il nous faudra donc en revanche compenser le scale et la rotation. * * Le FPSController est ensuite dé-parenté lorsqu'il quitte le contacte de la plateforme. * Mais une compensation de rotation doit êre maintenue ; il ne faut donc pas enlever ce script du personnage. * * Utilisation : * - Ce script doit se placer sur le Player (ou FPSController) * - Le gameObject Player doit être équipé d'un Trigger * - Ne pas oublié de donner le nom du tag utilisé pour les plateformes * - Les plateformes n'ont besoin que d'un simple collider * * * sylvain@oldtree.studio - 31/08/16 */ using UnityEngine; public class PlatefromGrip : MonoBehaviour { #region UNITY PART //Variables à renseigner via l'inspecteur public string plateformTag = "Plateform"; //Nom de tag utilisé ; initialisée à "Plateform" //Initialisation void Start () { InitCompensation (); } //Se passe APRES l'habituel Update de Unity void LateUpdate () { MaintainRotationOffset (); } //Lorsqu'un objet entre en contact avec le déclencheur void OnTriggerEnter ( Collider col ) { //Si c'est une plateforme if ( col.tag == plateformTag ) OnPlateformEnter ( col.transform ); } //Lorsque l'objet quitte le contact d'un déclencheur void OnTriggerExit ( Collider col ) { //Si c'est une plateforme if ( col.tag == plateformTag ) OnPlateformExit ( col.transform ); } #endregion #region INTERNAL LOGIC //Variables servant à la prise en charge du contact simultané avec d'autres plateformes private bool _isOnPlatform; //Savoir si le Player est actuellement en contact ou non avec une plateforme private Transform _actualPlateformTr; //Référence au Transform de la plateforme actuellement utilisée pour la compensation private bool _forcedExit; //Savoir si l'on a été obligé de de forcer la sortie d'une plateforme //(le cas lorsque le Player entre en contact avec une plateforme alors qu'il est déjà sur une autre) //Variable nécessaires aux calculs du script private Vector3 _rotationOffset; //Contiendra la compensation de rotation à maintenir de façon permanente private Vector3 _originalScale; //Sauvegarder le scale original du gameobject private Vector3 _parentScale; //Contiendra les données de scale de la plateforme /// <summary> /// Initialisation des variables de compensation /// </summary> private void InitCompensation () { _originalScale = this.transform.localScale; //Enregistrement du scale originale du FPSController _rotationOffset = Vector3.zero; //Mise à zéro de la compensation de rotation } /// <summary> /// Maintien de l'offset (à executer en continu sur le Player) /// </summary> private void MaintainRotationOffset () { this.transform.localEulerAngles += _rotationOffset; //Maintien permanent de la compensation en rotation } /// <summary> /// Lorsque le Player entre en contact avec une plateforme /// </summary> /// <param name="plateformTr">Transform de la plateforme contactée</param> private void OnPlateformEnter ( Transform plateformTr ) { if ( _isOnPlatform ) //Si le Player est actuellement sur une plateforme { UnparentFromPlatform ( _actualPlateformTr ); //Forcer le "dé-parentage" de clui-ci _forcedExit = true; //L'indiquer au script } //Puis, dans tous les cas... _actualPlateformTr = plateformTr; //Indiquer au script le transform que l'on va utiliser pour les calculs de compensation ParentToPlateform ( _actualPlateformTr ); //Initier le "parentage" du Player à cette plateforme } /// <summary> /// Lorsque le Player perd le contact avec une plateforme /// </summary> /// <param name="plateformTr">Transform de la plateforme quittée</param> private void OnPlateformExit ( Transform plateformTr ) { if ( !_forcedExit ) //Si aucun "dé-parentage" n'a été au préalable forcé UnparentFromPlatform ( plateformTr ); //Dé-parenter normalement le Player else if ( plateformTr != _actualPlateformTr ) //Sinon, si la plateforme actuellement quittée est différente de la plateforme sur laquelle le joueur est _forcedExit = false; //Ne rien faire, si ce n'est réinitialiser la variable d'état comme quoi le joueur //n'a pas été forcé de dé-parenter une plateforme } /// <summary> /// Parenter le Player à la plateforme /// </summary> /// <param name="plateformTr">Tranform de la plateforme à laquelle se parenter</param> private void ParentToPlateform ( Transform plateformTr ) { //Indiquer que le Player est actuellement en contact avec une plateforme _isOnPlatform = true; //Avant de parenter le Player à la plateforme, //Calcul de la compensation en scale à appliquer pour éviter toute déformation _parentScale = plateformTr.localScale; Vector3 newScale = new Vector3 { x = this.transform.localScale.x * ( 1 / _parentScale.x ), y = this.transform.localScale.y * ( 1 / _parentScale.y ), z = this.transform.localScale.z * ( 1 / _parentScale.z ), }; //Ajout de la valeur de rotation de la plateforme au vecteur de compensations de rotation AddRotationOffset ( -plateformTr.rotation.eulerAngles ); //Le Player est parenté à la plateforme this.transform.SetParent ( plateformTr ); //Application du scale précédemment calculé this.transform.localScale = newScale; } /// <summary> /// Dé-parenter le Player de la plateforme /// </summary> /// <param name="plateformTr">Transform de la plateforme de laquelle se dé-parenter</param> private void UnparentFromPlatform ( Transform plateformTr ) { //Indiquer que le Player vient de quitter le contact avec une plateforme _isOnPlatform = false; //Ajout de la valeur de rotation par rapport au monde 3D de la plateforme au vecteur de compensations de rotation AddRotationOffset ( plateformTr.rotation.eulerAngles ); //Dé-parenter l'objet this.transform.parent = null; //Application du scale d'origine this.transform.localScale = _originalScale; } /// <summary> /// Ajoute et régule le vecteur de compensation de rotation /// </summary> /// <param name="rotationToAdd">Valeur de rotation à ajouter</param> private void AddRotationOffset ( Vector3 rotationToAdd ) { //Remise à zéro de la rotation sur l'axe Z, dans le cas où il y en aurait une rotationToAdd.z = 0; //Ajout de la nouvelle valeur de rotation _rotationOffset += rotationToAdd; //Eviter que les valeurs d'angles Euler dépassent 360° if ( _rotationOffset.x > 360 ) _rotationOffset.x -= 360; if ( _rotationOffset.y > 360 ) _rotationOffset.y -= 360; } #endregion } |
Ce site a été conçu avec Jimdo. Inscrivez-vous gratuitement sur https://fr.jimdo.com
Écrire commentaire