[C#] HomingMissile.cs - Script de missile à tête chercheuse

Cette section est destinée aux scripts partagés par la communauté. Chaque post est destiné à un script. Suivez bien les recommandations.
Avatar de l’utilisateur
Alesk
Messages : 2303
Inscription : 13 Mars 2012 09:09
Localisation : Bordeaux - France
Contact :

[C#] HomingMissile.cs - Script de missile à tête chercheuse

Message par Alesk » 19 Juil 2014 18:26

-NOM DU SCRIPT : HomingMissile

-AUTEUR(S): Alesk

-DESCRIPTION : Script de missile à tête chercheuse

-UTILISATION : Placer le script sur un objet missile et lui assigner une cible


Paramètres :
Target : la cible à suivre
Speed : la vitesse du missile
Angular Threshold : intensité de virage maximale, plus la valeur est élevée (proche de 1) et plus le missile ira droit sur la cible
Angular Threshold Random Offset : valeur aléatoire ajoutée à l'intensité de virage pour ne pas avoir tous les missiles sur la même trajectoire
Craziness : (mon préféré) intensité du chemin chaotique suivi par le missile
Craziness Random offset : valeur aléatoire ajoutée à crazyness pour ne pas avoir tous les missiles sur la même trajectoire
Crazyness Frequency : interval de temps pour appliquer la valeur de crazyness à la trajectoire
Straight launch time : temps durant lequel le missile va partir tout droit, en allant graduellement vers la cible
Life Time : durée de vie du missile

Ici, pour la démo, la fonction Start lance directement le missile, mais il vaut mieux commenter cette ligne et contrôler le lancement du missile en utilisant la fonction Launch() sois-même au moment voulu.
La taille de la cible servant à détecter l'impact est calculée automatiquement à partir d'une approximation grossière du mesh.
Il faudrait peut-être adapter la détection d'impact avec des colliders, en fonction des cas...

Une fois la cible atteinte ou le missile arrivant en fin de vie, celui-ci est désactivé (cf. fonction Kill() ), et non complètement détruit.
Il peut ainsi être recyclé pour un nouveau lancement.

Vu que nous avons maintenant trois script différents de missiles sur ce forum, je me propose de faire un mix des trois si les auteurs concernés sont d'accord :mrgreen:

Code : Tout sélectionner

// HOMING MISSILE - Alexandre Labedade - alesk@alesk.fr
// free release for http://www.unity3d-france.com

using UnityEngine;
using System.Collections;

public class HomingMissile : MonoBehaviour {
	private Transform _transform;
	
	public Transform target; // object to follow
	public float speed = 1f; // missile speed
	
	public float angularThreshold = 0.05f; // how much the missile can turn
	public float angularThresholdRandomOffset = 0.01f; // random offset added to the missile turn value
	
	private float _angularThreshold = 0.05f;
	
	public float craziness = 0.2f; // how chaotic the path of the missile will be
	public float crazinessRandomOffset = 0.1f; // random offset added to the craziness value
	private float _craziness = 0.1f;
	
	public float crazinessFrequency = 0.05f; // how often the craziness will occur along the trajectory
	private float crazynessFreqElapsed = 0f;
	
	public float straightLaunchTime = 2f; // how long the missile is moving straight forward at launch (smoothly fading to seek path)
	public int lifeTime = 5; // how long the missile will live
			
	private Vector3 launchDirection;
	private float targetRadius = 1f;
	
	[HideInInspector]
	public Vector3 moveVector = Vector3.forward; // current moving vector of the missile
	
	[HideInInspector]
	public float age = 0f; // age of the missile
	
	public void Awake(){
		_transform = transform;
	}
	
	public void Start(){
		Launch (_transform.position,_transform.forward,this.target);
	}
	
	public void Launch(Vector3 startPosition, Vector3 startDirection, Transform targetToFollow, float missileSpeed = 10f){

		// reset some variables

		_transform.position = startPosition;
		moveVector = startDirection;
		launchDirection = startDirection;
		_angularThreshold = angularThreshold + Random.Range(0,angularThresholdRandomOffset);
		_craziness = craziness + Random.Range(0,crazinessRandomOffset);
		crazynessFreqElapsed = 0f;
		age = 0f;
		
		speed = missileSpeed;
		target = targetToFollow;
		
		targetRadius = 1f;
		// guess target radius automatically
		if(this.target){
			if(this.target.renderer){
				Vector3	sz = this.target.renderer.bounds.size;
				targetRadius = (sz.x+sz.y+sz.z)/6;
			}
		}
		
		// align the missile to it's starting direction
		_transform.forward = startDirection;
		
		// activate the gameObject to see the missile
		gameObject.SetActive(true);
		
		// activate this script
		this.enabled = true;
	}
	
	void Update () {
			
			float delta = Time.deltaTime;
			
			Vector3 direction;
			float distance = 1000;
			
			if(target == null){
				// no target defined, the missile go straight forward
				direction.x = launchDirection.x;	
				direction.y = launchDirection.y;
				direction.z = launchDirection.z;
			}else{
				if(_angularThreshold == 0){
					direction.x = launchDirection.x;	
					direction.y = launchDirection.y;
					direction.z = launchDirection.z;
				}else{
					direction = target.position - _transform.position;
				}
				distance = direction.sqrMagnitude;
			}
			
			crazynessFreqElapsed += delta;
			age += delta;
			
			// launch the missile straight forward, and gradually orient it to its target
			if(age < straightLaunchTime){
				direction = direction * age/straightLaunchTime + launchDirection * (1f-age/straightLaunchTime);
			}
			
			// define the movement vector toward the target
			moveVector = (moveVector + direction * _angularThreshold * delta).normalized;
			
			// randomize trajectory
			if(_craziness!=0 && crazynessFreqElapsed >= crazinessFrequency){
				moveVector += Random.insideUnitSphere * _craziness;
				crazynessFreqElapsed = 0f;
			}
			
			// align the missile to its path
			_transform.forward = moveVector.normalized;
			
			// move the missile
			if(age > 0) _transform.position += _transform.forward * speed * delta;
			
			// kill the missile if it's too old or have reached the target
			if(age > lifeTime || distance <= targetRadius) Kill();
	}
	
	public void Kill(){
		// disable the gameObject to hide the missile
		gameObject.SetActive(false);
		
		// disable this script to stop the Update() function
		enabled = false;
	}
	
	public bool ReadyForRecycle(){
		// return true if the missile is ready to be reused
		return age >= lifeTime;
	}
}

Avatar de l’utilisateur
yoyoyaya
Messages : 1656
Inscription : 30 Mai 2011 13:14
Localisation : PAAAAARTOUUUU
Contact :

Re: [C#] HomingMissile.cs - Script de missile à tête cherche

Message par yoyoyaya » 03 Août 2014 04:35

Juste un petit post au cas où ça pourrait servir à certains en plus du travail d'alesk.
En fouillant mes stocks de vieux liens qui moisissaient depuis des années, je suis tombé sur cette vidéo de youtube qui n'est pas répertoriée.
Je ne sais pas trop ce que ça vaut, l'effet final semble plutôt assez propre. A vous d'en faire ce que vous souhaitez.
ImageImage

Avatar de l’utilisateur
Aslan85
Messages : 326
Inscription : 10 Déc 2013 08:01

Re: [C#] HomingMissile.cs - Script de missile à tête cherche

Message par Aslan85 » 24 Oct 2014 05:29

Je viens juste de tester le script donne par Alesk et ca marche plutot pas mal.

Dans ce que tu as donne, le code contient des erreurs probablement du a un mauvais copier/coller :
- Lors de la declaration en [HideInspector], c'est ecris &#91;HideInInspector&#93
- Lors de la condition de la trajectoire en random il est ecris if(_craziness!=0 && crazynessFreqElapsed >= crazinessFrequency) au lieu de if(_craziness!=0 && crazynessFreqElapsed >= crazinessFrequency)

J'ai aussi teste le script donne dans la video youtube linke par yoyoyaya.
Je me dis autant faire profiter tout le monde et je rajoute le scripte de Homing que j'ai traduit en C#:

Code : Tout sélectionner

public class HomingMissileNew : MonoBehaviour {
	public float speed;
	public float turn;
	void Update () {
		GameObject[] targets = GameObject.FindGameObjectsWithTag("Target");
		GameObject closest = targets[0];
		float closestDist = Mathf.Infinity;

		foreach (GameObject Target in targets){
			float dist = (transform.position - Target.transform.position).sqrMagnitude;

			if (dist < closestDist){
				closestDist = dist;
				closest = Target;
			}
		}
		transform.rotation = Quaternion.Slerp (transform.rotation, Quaternion.LookRotation (closest.transform.position - transform.position), turn * Time.deltaTime);
		transform.position += transform.forward * speed * Time.deltaTime;
	}
}
Je suis souvent dans l'erreur et j'attends avidement que l'on me contredise.

Avatar de l’utilisateur
Alesk
Messages : 2303
Inscription : 13 Mars 2012 09:09
Localisation : Bordeaux - France
Contact :

Re: [C#] HomingMissile.cs - Script de missile à tête cherche

Message par Alesk » 24 Oct 2014 10:27

Aslan85 a écrit :Je viens juste de tester le script donne par Alesk et ca marche plutot pas mal.

Dans ce que tu as donne, le code contient des erreurs probablement du a un mauvais copier/coller :
- Lors de la declaration en [HideInspector], c'est ecris &#91;HideInInspector&#93
- Lors de la condition de la trajectoire en random il est ecris if(_craziness!=0 && crazynessFreqElapsed >= crazinessFrequency) au lieu de if(_craziness!=0 && crazynessFreqElapsed >= crazinessFrequency)
Houuuuu alors ça, c'est certainement causé par le changement de librairie d'affichage du code dans le forum :/
ça veut dire que potentiellement tous les exemples postés avant risquent d'avoir ce genre de coquilles ...

Avatar de l’utilisateur
Max
Messages : 8772
Inscription : 30 Juil 2011 13:57
Contact :

Re: [C#] HomingMissile.cs - Script de missile à tête cherche

Message par Max » 24 Oct 2014 10:47

Alesk a écrit :ça veut dire que potentiellement tous les exemples postés avant risquent d'avoir ce genre de coquilles ...
oui apparement. En regardant vite fait dans cette seule section, sur un autre de tes codes par exemple, on trouve ce genre de chose:

Code : Tout sélectionner

float&#91;&#93; e = new float&#91;3&#93;;
:?
Image
Pas d'aide par MP, le forum est là pour ça.
En cas de doute sur les bonnes pratiques à adopter sur le forum, consulter la Charte et sa FAQ

Avatar de l’utilisateur
Alesk
Messages : 2303
Inscription : 13 Mars 2012 09:09
Localisation : Bordeaux - France
Contact :

Re: [C#] HomingMissile.cs - Script de missile à tête cherche

Message par Alesk » 24 Oct 2014 10:53

J'ai prévenu Krys pour qu'il regarde ça...

Pour info, mes codes sont directement copiés/collés depuis mono à chaque fois... à priori ce sont les crochets [] qui sont mal interprétés.

Avatar de l’utilisateur
Max
Messages : 8772
Inscription : 30 Juil 2011 13:57
Contact :

Re: [C#] HomingMissile.cs - Script de missile à tête cherche

Message par Max » 24 Oct 2014 10:56

A titre d'info, c'est juste un bug à l'affichage apparement. Si tu 'quote' le code, la syntaxe reste bonne. bizarre.
Alesk a écrit :-NOM DU SCRIPT : HomingMissile

-AUTEUR(S): Alesk



Code : Tout sélectionner

// HOMING MISSILE - Alexandre Labedade - alesk@alesk.fr
// free release for http://www.unity3d-france.com

using UnityEngine;
using System.Collections;

public class HomingMissile : MonoBehaviour {
	
	private Transform _transform;
	
	public Transform target; // object to follow
	public float speed = 1f; // missile speed
	
	public float angularThreshold = 0.05f; // how much the missile can turn
	public float angularThresholdRandomOffset = 0.01f; // random offset added to the missile turn value
	
	private float _angularThreshold = 0.05f;
	
	public float craziness = 0.2f; // how chaotic the path of the missile will be
	public float crazinessRandomOffset = 0.1f; // random offset added to the craziness value
	private float _craziness = 0.1f;
	
	public float crazinessFrequency = 0.05f; // how often the craziness will occur along the trajectory
	private float crazynessFreqElapsed = 0f;
	
	public float straightLaunchTime = 2f; // how long the missile is moving straight forward at launch (smoothly fading to seek path)
	public int lifeTime = 5; // how long the missile will live
			
	private Vector3 launchDirection;
	private float targetRadius = 1f;
	
	[HideInInspector]
	public Vector3 moveVector = Vector3.forward; // current moving vector of the missile
	
	[HideInInspector]
	public float age = 0f; // age of the missile
	
	public void Awake(){
		_transform = transform;
	}
	
	public void Start(){
		Launch (_transform.position,_transform.forward,this.target);
	}
	
	public void Launch(Vector3 startPosition, Vector3 startDirection, Transform targetToFollow, float missileSpeed = 10f){

		// reset some variables

		_transform.position = startPosition;
		moveVector = startDirection;
		launchDirection = startDirection;
		_angularThreshold = angularThreshold + Random.Range(0,angularThresholdRandomOffset);
		_craziness = craziness + Random.Range(0,crazinessRandomOffset);
		crazynessFreqElapsed = 0f;
		age = 0f;
		
		speed = missileSpeed;
		target = targetToFollow;
		
		targetRadius = 1f;
		// guess target radius automatically
		if(this.target){
			if(this.target.renderer){
				Vector3	sz = this.target.renderer.bounds.size;
				targetRadius = (sz.x+sz.y+sz.z)/6;
			}
		}
		
		// align the missile to it's starting direction
		_transform.forward = startDirection;
		
		// activate the gameObject to see the missile
		gameObject.SetActive(true);
		
		// activate this script
		this.enabled = true;
	}
	
	void Update () {
			
			float delta = Time.deltaTime;
			
			Vector3 direction;
			float distance = 1000;
			
			if(target == null){
				// no target defined, the missile go straight forward
				direction.x = launchDirection.x;	
				direction.y = launchDirection.y;
				direction.z = launchDirection.z;
			}else{
				if(_angularThreshold == 0){
					direction.x = launchDirection.x;	
					direction.y = launchDirection.y;
					direction.z = launchDirection.z;
				}else{
					direction = target.position - _transform.position;
				}
				distance = direction.sqrMagnitude;
			}
			
			crazynessFreqElapsed += delta;
			age += delta;
			
			// launch the missile straight forward, and gradually orient it to its target
			if(age < straightLaunchTime){
				direction = direction * age/straightLaunchTime + launchDirection * (1f-age/straightLaunchTime);
			}
			
			// define the movement vector toward the target
			moveVector = (moveVector + direction * _angularThreshold * delta).normalized;
			
			// randomize trajectory
			if(_craziness!=0 && crazynessFreqElapsed >= crazinessFrequency){
				moveVector += Random.insideUnitSphere * _craziness;
				crazynessFreqElapsed = 0f;
			}
			
			// align the missile to its path
			_transform.forward = moveVector.normalized;
			
			// move the missile
			if(age > 0) _transform.position += _transform.forward * speed * delta;
			
			// kill the missile if it's too old or have reached the target
			if(age > lifeTime || distance <= targetRadius) Kill();
	}
	
	public void Kill(){
		// disable the gameObject to hide the missile
		gameObject.SetActive(false);
		
		// disable this script to stop the Update() function
		enabled = false;
	}
	
	public bool ReadyForRecycle(){
		// return true if the missile is ready to be reused
		return age >= lifeTime;
	}
}
Image
Pas d'aide par MP, le forum est là pour ça.
En cas de doute sur les bonnes pratiques à adopter sur le forum, consulter la Charte et sa FAQ

Avatar de l’utilisateur
krys64
Fondateur unity3d-france
Fondateur unity3d-france
Messages : 471
Inscription : 26 Nov 2009 00:08

Re: [C#] HomingMissile.cs - Script de missile à tête cherche

Message par krys64 » 24 Oct 2014 12:01

C'est les brackets qui partent en sucettes, je jette un oeild'ici ce soir.

Avatar de l’utilisateur
krys64
Fondateur unity3d-france
Fondateur unity3d-france
Messages : 471
Inscription : 26 Nov 2009 00:08

Re: [C#] HomingMissile.cs - Script de missile à tête cherche

Message par krys64 » 24 Oct 2014 12:35

C'est bizarre, j'ai édité ton post et republié et c'est rentré dans l'ordre ?!?
Bon faut que je regarde en profondeur, en attendant, j'ai enlevé la fonction colorisation

Répondre

Revenir vers « Scripts »