[DB-AL] Déplacement d'une limace (C#)

Pour les scripts écrits en C#
Règles du forum
Merci de respecter la NOMENCLATURE suivante pour vos TITRES de messages :

Commencez par le niveau de vos scripts
DB = Débutant
MY = Moyen
CF = Confirmé

Puis le domaine d'application
-RS = Réseau
-AL = Algorithmie

Exemple :

[DB-RS] Mouvement perso multijoueur
casp3r97417
Messages : 21
Inscription : 23 Août 2016 13:30

Re: [DB-AL] Déplacement d'une limace (C#)

Message par casp3r97417 » 30 Août 2016 08:44

Bonjour,

je vais essayer d'apporter des conseils :-D

cela me rapelle un bug que j'ai du régler sur un jeux 2d, j'avais un Sprite dans le mauvais sens, je l'ai attacher à un game objet, appliquer un déplacement et ensuite j'ai tourner le game object et la droite n'était donc plus à droite

essaye donc de tagger les murs et en cas de collision de passer le mouvement "forward" en "up" pour essayer? :)

Georgi
Messages : 7
Inscription : 26 Août 2016 05:07

Re: [DB-AL] Déplacement d'une limace (C#)

Message par Georgi » 31 Août 2016 06:52

Non, ce n'est pas un problème de direction.

Toutefois, par manque de temps, j'ai dû confier la tâche à un développeur.
Il fait quelque chose à base de raycast et de physique et apparemment, il s'en sort bien.

Je vous redirais ça.

Moi 1971
Messages : 727
Inscription : 29 Sep 2015 13:38

Re: [DB-AL] Déplacement d'une limace (C#)

Message par Moi 1971 » 31 Août 2016 10:54

Georgi a écrit :...j'ai dû confier la tâche à un développeur.
C'est une bonne décision,avec la structure et le code sous les yeux ça va aller vite.
Georgi a écrit :Je vous redirais ça.
Ça c'est sympa pour les suivants qui se trouveront dans le même cas. ;-)

Georgi
Messages : 7
Inscription : 26 Août 2016 05:07

Re: [DB-AL] Déplacement d'une limace (C#)

Message par Georgi » 05 Sep 2016 15:08

Je reviens pour vous donner la solution que l'on a appliquée.

La limace traverse parfois les murs, reste rigide dans ses déplacements (parce que l'on a pas utilisé les bones) et ne peut avancer que devant elle sur un mur mais l'essentiel, c'est que j'ai pu rendre un jeu jouable dans les temps.

Ceci dit, je pense que le programmeur a fait une solide base qu'il est toujours possible d'améliorer.

Voici ce qui a été fait (en gros) :

La hiérarchie de la limace a été légèrement modifiée :
Image
(RaycastTarget est un gameobject vide)

Ce physic material a été appliqué sur la limace :
Image

Ici l'inspector de la limace pour les détails :
Image

Deux layers ont été ajoutés dans le physic manager (ground et slug) :
Image
Slug est appliqué au prefab, au mesh et au RaycastTarget de la limace.
Ground est appliqué aux piliers sur lesquelles la limace doit se mouvoir.

Voici le code appliqué aux piliers :

Code : Tout sélectionner

using UnityEngine;
using System.Collections;

public class ColumnB : MonoBehaviour
{
	bool isMoving;

	void Start ()
	{
		isMoving = false;
	}

	public void Move (bool state)
	{
		isMoving = state;
	}

	void OnTriggerStay (Collider other)
	{
		if (isMoving)
			other.transform.GetComponent<SlugB> ().IsFalling (true);
		else
			other.transform.GetComponent<SlugB> ().IsFalling (false);
	}
}
Et voici le code sur la limace :

Code : Tout sélectionner

using UnityEngine;
using System.Collections;

public class SlugB : MonoBehaviour
{
	public enum PlayerNum
	{
		playerOne,
		playerTwo
	}
	//References
	public Rigidbody thisRB;
	public Transform raycastBase;

	//Internal variables
	public PlayerNum currentPlayer;
	Vector2 currentInput;
	public bool canMove = true;
	public float movSpeed = 0.3f;
	public float movCycleSpeed = 5;
	public float delayBetweenMov = 0.3f;
	float timerBetweenMov;
	public float distanceToChangeDirection = 0.1f;
	public LayerMask groundMask;
	//Vector3 startPos;

	//Walking flags
	public bool isBelowEmpty;
	public bool isAheadEmpty;
	public bool isWalkingHorizontally = true;

	bool isFalling;

	void Start ()
	{
	//	startPos = this.transform.position;
	}

	void FixedUpdate ()
	{
		//Update inputs
		if (currentPlayer == PlayerNum.playerOne)
			currentInput = new Vector2 (-Input.GetAxis ("Horizontal"), Input.GetAxis ("Vertical")).normalized;
		//else
		if (currentPlayer == PlayerNum.playerTwo)
			currentInput = new Vector2 (-Input.GetAxis ("Horizontal2"), Input.GetAxis ("Vertical2")).normalized;

		timerBetweenMov -= Time.deltaTime;

		if (canMove)
			MoveSlug (currentInput);

		//Smooth velocity
		if (Vector3.Distance (thisRB.velocity, Vector3.zero) > 0.3f)
			thisRB.velocity -= thisRB.velocity * 0.1f;

		//Check for save !
//		if (this.transform.localPosition.y < 100) {
//			//Reset slug
//			isAheadEmpty = true;
//			isBelowEmpty = false;
//			isWalkingHorizontally = true;
//			this.transform.position = startPos;
//			this.transform.rotation = Quaternion.identity;
//		}

	}

	/// <summary>
	/// Moves the slug using inputs.
	/// </summary>
	/// <param name="newInputs">New inputs.</param>
	void MoveSlug (Vector2 newInputs)
	{
		//Have the slug rotate towards the current input, but always face the wall

		if (Mathf.Abs (newInputs.x) > 0.1f || Mathf.Abs (newInputs.y) > 0.1f) {
			if (isWalkingHorizontally) {
				this.transform.forward = Vector3.Lerp (this.transform.forward, new Vector3 (newInputs.x, 0, newInputs.y).normalized, 0.125f);
				ClampAngleTo90 (false, true, false);

			} else {

				//Check which side it's on : front of side of wall
				if (Vector3.Distance (Vector3.right, this.transform.up) < 0.1f || Vector3.Distance (-Vector3.right, this.transform.up) < 0.1f) {
					this.transform.forward = Vector3.Lerp (this.transform.forward, new Vector3 (0, newInputs.x, newInputs.y).normalized, 0.125f);
					ClampAngleTo90 (false, false, false);

				}
				if (Vector3.Distance (Vector3.forward, this.transform.up) < 0.1f || Vector3.Distance (-Vector3.forward, this.transform.up) < 0.1f) {
					this.transform.forward = Vector3.Lerp (this.transform.forward, new Vector3 (newInputs.x, newInputs.y, 0).normalized, 0.125f);
					ClampAngleTo90 (false, false, false);
				}

				if (Physics.Raycast (raycastBase.position, this.transform.up, 0.2f, groundMask))
					this.transform.Rotate (new Vector3 (0, 0, 180), Space.Self);
				else if (Physics.Raycast (raycastBase.position, -this.transform.right, 0.2f, groundMask))
					this.transform.Rotate (new Vector3 (0, 0, -90), Space.Self);
				else if (Physics.Raycast (raycastBase.position, this.transform.right, 0.2f, groundMask))
					this.transform.Rotate (new Vector3 (0, 0, 90), Space.Self);
			}
		}
		
		//Apply movements
		//this.thisRB.MovePosition (thisRB.position + this.transform.forward * (Mathf.Abs (newInputs.normalized.x) + Mathf.Abs (newInputs.normalized.y)) * movSpeed * Mathf.Abs (Mathf.Sin (Time.time * movCycleSpeed)) * Time.deltaTime);
		this.thisRB.MovePosition (thisRB.position + this.transform.forward * (Mathf.Abs (newInputs.normalized.x) + Mathf.Abs (newInputs.normalized.y)) * movSpeed * Mathf.Abs (Mathf.Sin (Time.time * movCycleSpeed)) * (isWalkingHorizontally ? 1 :0.4f)* Time.deltaTime);
		//Check both below the slug and ahead of the slug.
		isBelowEmpty = !Physics.Raycast (new Ray (raycastBase.transform.position, -this.transform.up), distanceToChangeDirection, groundMask);
		isAheadEmpty = !Physics.Raycast (new Ray (raycastBase.transform.position, this.transform.forward), distanceToChangeDirection, groundMask);

		if (((isAheadEmpty && isBelowEmpty) || (!isAheadEmpty && !isBelowEmpty)) && timerBetweenMov < 0)
			RotateSlug ();
	}

	void RotateSlug ()
	{
		timerBetweenMov = delayBetweenMov;
		ClampAngleTo90 ();


		if (isAheadEmpty && isBelowEmpty) {
			//Retardation test
			/*if (Physics.Raycast (new Ray (raycastBase.transform.position, this.transform.forward), 999, groundMask))
				return;*/

			//Rotate first
			this.transform.Rotate (Vector3.right * 90);

			this.transform.position += this.transform.forward * 0.1f;
			this.transform.position += this.transform.up * 0.5f;

			//Put slug against wall
			RaycastHit stuffHit;
			Physics.Raycast (new Ray (raycastBase.transform.position, -this.transform.up), out stuffHit, 999, groundMask);
			this.transform.position = stuffHit.point + this.transform.up * 0.1f;
			this.transform.position -= this.transform.forward * 0.2f;

		} else if (!isAheadEmpty && !isBelowEmpty) {
			//This case is called for corners where there's a wall below and in front of the slug

			//Put slug against wall
			RaycastHit stuffHit;
			Physics.Raycast (new Ray (raycastBase.transform.position, this.transform.forward), out stuffHit, 999, groundMask);
			this.transform.position = stuffHit.point + this.transform.forward * -0.1f;
			//Rotate slug
			this.transform.Rotate (-Vector3.right * 90, Space.Self);

			this.transform.position += this.transform.forward * 0.05f;
		}

		isWalkingHorizontally = (Vector3.Distance (this.transform.up, Vector3.up) < 0.1f);
	}

	void ClampAngleTo90 ()
	{
		ClampAngleTo90 (false, false, false);
	}

	void ClampAngleTo90 (bool exceptX, bool exceptY, bool exceptZ)
	{
		Vector3 outputRot = this.transform.rotation.eulerAngles;

		//Clamp each value
		if (!exceptX) {
			if (outputRot.x < 0)
				outputRot.x += 360;
		
			if (outputRot.x > 70 && outputRot.x < 110)
				outputRot.x = 90.05f;
			if (outputRot.x > 160 && outputRot.x < 200)
				outputRot.x = 180.05f;
			if (outputRot.x > 250 && outputRot.x < 290)
				outputRot.x = 270.05f;
			if (outputRot.x > 340 && outputRot.x + 360 < 380)
				outputRot.x = 0.05f;
		}

		if (!exceptY) {
			if (outputRot.y < 0)
				outputRot.y += 360;
		
			if (outputRot.y > 70 && outputRot.y < 110)
				outputRot.y = 90.05f;
			if (outputRot.y > 160 && outputRot.y < 200)
				outputRot.y = 180.05f;
			if (outputRot.y > 250 && outputRot.y < 290)
				outputRot.y = 270.05f;
			if (outputRot.y > 340 && outputRot.y + 360 < 380)
				outputRot.y = 0.05f;
		}

		if (!exceptZ) {
			if (outputRot.z < 0)
				outputRot.z += 360;
		
			if (outputRot.z > 70 && outputRot.z < 110)
				outputRot.z = 90.05f;
			if (outputRot.z > 160 && outputRot.z < 200)
				outputRot.z = 180.05f;
			if (outputRot.z > 250 && outputRot.z < 290)
				outputRot.z = 270.05f;
			if (outputRot.z > 340 && outputRot.z + 360 < 380)
				outputRot.z = 0.05f;
		}

		this.transform.rotation = Quaternion.Euler (outputRot);
	}

	/// <summary>
	/// Make the slime fall (or make it stop falling)
	/// </summary>
	/// <returns><c>true</c> if this instance is falling the specified newState; otherwise, <c>false</c>.</returns>
	/// <param name="newState">If set to <c>true</c> new state.</param>
	public bool IsFalling (bool newState)
	{
		if (isFalling == newState)
			return isFalling;

		isFalling = newState;
		canMove = !newState;
		thisRB.isKinematic = !newState;
		thisRB.useGravity = newState;
		currentInput = Vector2.zero;
		if(newState)
		Debug.Log ("SLKDNFSLKDFNDS");

		return isFalling;

	}

	void OnDrawGizmos ()
	{
		Gizmos.color = Color.blue;
	
		Gizmos.DrawRay (raycastBase.transform.position, -this.transform.up);
	
		Gizmos.color = Color.cyan;
	
		Gizmos.DrawRay (raycastBase.transform.position, this.transform.forward);
	}
}
Je ne peux pas expliquer le code en détails puisqu'il n'est pas de moi et surtout que je ne comprend pas tout.
Cependant, je pense que ça pourrait toujours aider quelqu'un d'un peu expérimenté qui chercherais à faire
quelque chose de similaire.

Merci à vous pour m'avoir aidé !

Au plaisir !

Avatar de l’utilisateur
Iwa
Messages : 1131
Inscription : 25 Avr 2012 16:20
Contact :

Re: [DB-AL] Déplacement d'une limace (C#)

Message par Iwa » 27 Sep 2016 11:00

Hello,

merci pour le partage de ta solution. N'oublie pas de basculer ton sujet en [RESOLU] si tout est bon pour toi. Il suffit d'éditer ton premier post.

Merci à toi.
"N'est stupide que la stupidité Monsieur..." - Forest Gump
... sauf si tu lis pas ça :)

Si tu as tout ce qu'il te faut, merci de penser à basculer ton sujet en [RESOLU] en éditant ton tout premier post ;)

Répondre

Revenir vers « (C#) CSharp »