[C#] New SeekSteer
Publié : 04 Mars 2017 21:11
Salut,
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.
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);
}
}
}