Address
304 North Cardinal St.
Dorchester Center, MA 02124
Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM
We use cookies to ensure that we provide you with the best possible experience on our site.
Votre source incontournable sur Unity et le développement web
Votre source incontournable sur Unity et le développement web
Sur Unity, la méthode statique MoveTowards de la structure Vector3 nous permet de déplacer notre GameObject avec un effet smooth vers une position cible en spécifiant une distance maximale à parcourir par trame.
Table des matières
MoveTowards renvoie un Vector3 et a trois paramètres : une position de départ (généralement la position de votre GameObject), une position cible à atteindre, et enfin, une distance maximale à parcourir.
Le Vector3 retourné prend la position de départ et se rapproche de la position cible avec la distance maximale spécifiée.
Exemple avec 2 positions:
var position = Vector3.MoveTowards(Vector3.zero, new Vector3(0f, 5f, 0f), 1f);
// position = new Vector3(0f, 1f, 0f)
MoveTowards est parfait pour cette tâche ; nous devons simplement l’implémenter dans une fonction Update :
using UnityEngine;
public class MoveCharacter : MonoBehaviour
{
[SerializeField]
private GameObject _targetGameObject;
private float _speed = 3f;
private void Update()
{
transform.position = Vector3.MoveTowards(transform.position, _targetGameObject.transform.position, Time.deltaTime * _speed);
if (Vector3.Distance(transform.position, _targetGameObject.transform.position) < 0.001f)
{
// Notre GameObject a atteint la cible
}
}
}
Remarque : Cet exemple peut être amélioré en référençant directement le Transform de notre cible.
Time.deltaTime nous permet de synchroniser indépendamment des fps :
Pour obtenir une accélération dépendante de la trame, nous devons multiplier la vitesse à ajouter avant et après MoveTowards en la divisant par 2 :
using UnityEngine;
public class MoveCharacter : MonoBehaviour
{
[SerializeField]
private GameObject _targetGameObject;
private float _speed = 3f;
private void Update()
{
float vitesseIncrementale = 0.1f;
_speed += vitesseIncrementale * Time.deltaTime * 0.5f;
transform.position = Vector3.MoveTowards(transform.position, _targetGameObject.transform.position, Time.deltaTime * _speed);
_speed += vitesseIncrementale * Time.deltaTime * 0.5f;
}
}
Pour plus de détails sur les accélérations et Time.deltaTime en général, je recommande cette vidéo :
Youtube – Jonas Tyroller – Dear Game Developers, Stop Messing This Up!
Pour accomplir un déplacement sur une durée définie, bien que MoveTowards soit une option viable, je recommande d’utiliser Lerp à la place, comme indiqué immédiatement après cette approche.
Au lieu d’entrer une distance, nous optons pour insérer une vélocité par trame (frame), en suivant ces étapes :
using System.Collections;
using System.Threading.Tasks;
using UnityEngine;
public class MoveByDuration : MonoBehaviour
{
[SerializeField]
private Vector3 _position;
private void Start()
{
StartCoroutine(MovetowardsDuration(3f));
// si vous préférez async
// MoveAsync(3f);
}
private IEnumerator MovetowardsDuration(float duration)
{
float distance = Vector3.Distance(transform.position, _position);
float distanceBySeconds = distance / duration;
float startTime = 0;
while (startTime < duration)
{
transform.position = Vector3.MoveTowards(transform.position, _position, distanceBySeconds * Time.deltaTime);
startTime += Time.deltaTime;
yield return null;
}
}
// async
private async void MoveAsync(float duration)
{
float distance = Vector3.Distance(transform.position, _position);
float distanceBySeconds = distance / duration;
float startTime = 0;
while (startTime < duration)
{
transform.position = Vector3.MoveTowards(transform.position, _position, distanceBySeconds * Time.deltaTime);
startTime += Time.deltaTime;
await Task.Yield();
}
}
}
Dans ce contexte, je préfère utiliser la méthode Lerp. L’interpolation linéaire qu’elle effectue nous permet d’obtenir directement notre position en fonction du temps écoulé.
Pour cela, nous avons seulement besoin d’incrémenter un compteur de temps avec Time.deltaTime à chaque trame (frame), puis diviser ce compteur par la durée pour obtenir une valeur de temps entre 0 et 1.
using System.Collections;
using System.Threading.Tasks;
using UnityEngine;
public class LerpTest : MonoBehaviour
{
[SerializeField]
private Vector3 _positionTarget;
private void Start()
{
StartCoroutine(Lerp(3f));
}
private IEnumerator Lerp(float duration)
{
float start = 0;
var startPosition = transform.position;
while (start < duration)
{
transform.position = Vector3.Lerp(startPosition, _positionTarget, start / duration);
start += Time.deltaTime;
yield return null;
}
}
// Si vous préférez async
private async void LerpAsync(float duration)
{
float start = 0;
var startPosition = transform.position;
while (start < duration)
{
transform.position = Vector3.Lerp(startPosition, _positionTarget, start / duration);
start += Time.deltaTime;
await Task.Yield();
}
}
}
Cette alternative offre une transition toute trouvée vers le sujet suivant :
De plus, MoveTowards est principalement utilisé pour les déplacements, tandis que Lerp est utilisé dans tous les aspects du gameplay, permettant des transitions, des changements de direction, et plus encore.
Pour conclure, la méthode MoveTowards d’Unity offre un outil polyvalent pour obtenir des mouvements d’objets fluides avec des limites de vitesse spécifiées. On peut noter aussi que la compréhension des nuances entre Lerp et MoveTowards est une étape importante dans Unity.
Merci d’avoir lu et bon codage !