Page 1 sur 1

[C#] New SeekSteer

Publié : 04 Mars 2017 21:11
par ZJP
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 :mrgreen: ) 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);
		}
	}
}


Re: [C#] New SeekSteer

Publié : 05 Mars 2017 12:39
par Franck
Merci JP. :)

Re: [C#] New SeekSteer

Publié : 06 Mars 2017 06:14
par ZJP
Franck a écrit :Merci JP. :)
A ton service. ;-)

Re: [C#] New SeekSteer

Publié : 08 Mars 2017 00:46
par E3DStef
yess ! +1