Le SeekSteer du Wiki est l'un des scripts de WayPoint le plus connu.
Cependant, après l'avoir essayé, j'y ai trouvé quelques manques (cela reste après tout une version minimaliste ) du point de vu performance et fonctionnalité. Le script présenté (tout en restant une version de base) est une évolution/amélioration du script original.
- NOM DU SCRIPT : NewSeekSteer
- AUTEUR : ZJP (voir la version original pour le "concept")
- DESCRIPTION : Script de déplacement par WayPoints, plus options de détection d'une "cible" en fonction de son angle de vue, sa distance et d'un obstacle présent. (Usage de RotateTowards à la place du Lerp.)
Le script intègre aussi la notion de délai de réaction du perso avec pour effet secondaire de réduire le nombre de calculs effectués.
- UTILISATION :
a) Coller le script sur un GO (avec ou sans RigidBody)
b) Ajouter un GO cible.
c) Ajouter une série de GO Waypoints.
d) Mettez à jour les paramètres du script.
Code : Tout sélectionner
// NewSeekSteer.cs
using UnityEngine;
using System.Collections;
public class NewSeekSteer : MonoBehaviour {
public Transform[] waypoints;
public float waypointRayonDetection = 1.5f;
public bool moveMe = true;
public Transform myTarget;
[Range (1,10)] public int delaiReaction = 10; // delai du "temps reaction" du perso
[Range (20.0f,180.0f)] public float AngleDeVue = 90.0f; // Angle de vu. 20 à 180 degrés
[Range (1.0f ,200.0f)] public float DistanceDeVue = 100.0f;
private int timeReaction = 0;
public float speed = 2.0f; // Vitesse de progression
public float rotSpeed = 2.0f; // Vitesse de rotation
private int targetwaypoint;
private Transform xform;
private Vector3 TargetDir = new Vector3(0.0f,0.0f, 0.0f);
private float DetectAngle = 0.0f;
private float waypointDistance = 1.0f;
private bool seeYou = false;
// private Rigidbody rigBody;
protected void Start() {
//rigBody = GetComponent<Rigidbody>();
xform = transform;
if(waypoints.Length <= 0){
Debug.Log("Pas de waypoints");
enabled = false; // déactivation du script
}
targetwaypoint = 0;
}
protected void FixedUpdate()
{
if(waypoints.Length <= 0) return; // pas de WP
if (!moveMe) return;
timeReaction++;
if (timeReaction > delaiReaction) // en plus d'ajouter un temps de reaction au perso , permet de reduire le nombre de calculs effectués
{
TargetDir = waypoints[targetwaypoint].position - xform.position;
//TargetDir.y = 0.0f; // peut être figé !!!
TargetDir = Vector3.RotateTowards( xform.forward, TargetDir, rotSpeed * Time.fixedDeltaTime, 0.0f );
// version Transform !!! *********************************************************************
xform.rotation = Quaternion.LookRotation(TargetDir);
// version Physic !!!! ***********************************************************************
//rigBody.MoveRotation(Quaternion.LookRotation(TargetDir));
// Changement de WayPoint *******************************************************************************
waypointDistance = Vector3.Distance(xform.position, waypoints[targetwaypoint].position);
if(waypointDistance <= waypointRayonDetection)
{
targetwaypoint++;
if(targetwaypoint >= waypoints.Length) targetwaypoint = 0;
//targetwaypoint = (targetwaypoint + 1) % waypoints.Length;
}
// Changement de WayPoint *******************************************************************************
// cible en vue?! ***************************************************************************************
seeYou = false;
if ( DistanceDeVue > Vector3.Distance(xform.position, myTarget.position) ) // Bonne distance
{
DetectAngle = 1.0f - Vector3.Dot( xform.forward, ( myTarget.position - xform.position ).normalized);
if (DetectAngle < AngleDeVue / 2.0f * 0.0111f) // Bon angle de vue
{
if (!Physics.Linecast( xform.position, myTarget.position )) seeYou = true; // Pas d'obstacle
}
}
// cible en vue?! ***************************************************************************************
timeReaction = 0;
}
xform.position = xform.position + xform.forward * Time.fixedDeltaTime * speed; // version transform
//rigBody.MovePosition(xform.position + xform.forward * Time.fixedDeltaTime * speed ); // version physic
}
// draws red line from waypoint to waypoint
public void OnDrawGizmos() {
Gizmos.color = Color.red;
if(waypoints == null) return;
for(int i = 0; i < waypoints.Length; i++){
Vector3 pos = waypoints[i].position;
if(i > 0){
Vector3 prev = waypoints[i-1].position;
Gizmos.DrawLine(prev,pos);
}
}
Gizmos.DrawLine(waypoints[0].position , waypoints[waypoints.Length-1].position);
// ligne entre NPC et Cible
if (seeYou) {
Gizmos.color = Color.white;
Gizmos.DrawLine(xform.position, myTarget.position);
}
}
}