[CF-AL] [RESOLU] Véhicule Physique Raycast (Mario Kart, Wipeout, CTR..)

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
Cyril5
Messages : 42
Inscription : 03 Juin 2012 14:51
Localisation : Tours
Contact :

[CF-AL] [RESOLU] Véhicule Physique Raycast (Mario Kart, Wipeout, CTR..)

Message par Cyril5 » 28 Nov 2017 01:47

Bonjour, :hello:

Je suis en train de développer un système de conduite à la Mario Kart, Wipeout...
Ce système n'utilisent pas de composants Wheel Collider mais des raycasts qui permet de soulever le véhicule lorsque ces derniers touchent la route (même principe qu'un déplacement d'une voiture volante style Wipeout).

Vidéo Explicative : https://www.youtube.com/watch?v=LG1CtlFRmpU

Pour le développement je me suis basé sur ces deux tutoriaux : La voiture ou le kart est juste un cube pour sa collision qui contient 4 raycast vers le bas comme si c'était les suspensions de nos 4 roues.

Image

Voici le code actuellement

Code : Tout sélectionner

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RaycastCar : MonoBehaviour {

    Rigidbody m_rigidBody;
    public Transform m_centerOfMass;

    public float m_forwardAcceleration = 10000f;
    public float m_reverseAcceleration = 2500f;
    public float m_turn = 300f;
    public float m_groundedDrag = 3f; // rigidbody drag on grounded (same on rigidbody drag at start)

    public LayerMask m_layerMask;
    public float m_hoverHeight = 1f;
    public float m_hoverForce = 900f;
    public List<Transform> m_hoverPoints;

    public float m_maxSpeed = 180f;

    float m_deadZone = 0.1f; //make the controller not so sensitive to small movements.Basically any input below the deadZone threshold is ignored.

    float m_currThrust;
    float m_currTurn;

    void Awake()
    {
        m_rigidBody = GetComponent<Rigidbody>();
    }

    void Start()
    {
        m_rigidBody.centerOfMass = m_centerOfMass.localPosition;
    }

    void Update () {

        m_currThrust = 0f;
        float vertical = Input.GetAxis("Vertical");
        if (vertical > m_deadZone) // on appuie vers le haut
            m_currThrust = vertical * m_forwardAcceleration;
        else if (vertical < -m_deadZone)
            m_currThrust = vertical * m_reverseAcceleration;

        // Controle pour tourner
        m_currTurn = 0f;
        float horizontal = Input.GetAxis("Horizontal");
        if(Mathf.Abs(horizontal) > m_deadZone)
        {
            m_currTurn = horizontal;
        }

	}
	
	void FixedUpdate () {

        //print(m_rigidBody.velocity);

        // Avant/Arrière
        if (Mathf.Abs(m_currThrust) > 0)
            m_rigidBody.AddForce(transform.forward * m_currThrust);

        //Tourner 
        if(m_currTurn > 0)
        {
            m_rigidBody.AddRelativeTorque(Vector3.up * m_currTurn * m_turn);
        }else if(m_currTurn < 0)
        {
            m_rigidBody.AddRelativeTorque(Vector3.up * m_currTurn * m_turn);
        }

        // Limit max velocity
        if (m_rigidBody.velocity.sqrMagnitude > (m_rigidBody.velocity.normalized * m_maxSpeed).sqrMagnitude)
        {
            m_rigidBody.velocity = m_rigidBody.velocity.normalized * m_maxSpeed;
        }

        RaycastHit hit;
        bool grounded = false;

		foreach(Transform hoverPoint in m_hoverPoints)
        {
            Debug.DrawRay(hoverPoint.position, -Vector3.up * m_hoverHeight, Color.green);

            if (Physics.Raycast(hoverPoint.position, -Vector3.up,out hit,m_hoverHeight,m_layerMask))
            {
                Debug.DrawRay(hoverPoint.position, -Vector3.up * m_hoverHeight, Color.red);
                float compressFactor = (1f - (hit.distance / m_hoverHeight)); // Spring compression
                m_rigidBody.AddForceAtPosition(Vector3.up * m_hoverForce * compressFactor, hoverPoint.position);

                grounded = true;
            }
            else
            {
                // Self levelling - returns the vehicle to horizontal when not grounded
                if (transform.position.y > hoverPoint.transform.position.y)
                {
                    m_rigidBody.AddForceAtPosition(hoverPoint.transform.up * m_hoverForce, hoverPoint.transform.position);
                }
                else
                {
                    m_rigidBody.AddForceAtPosition(hoverPoint.transform.up * -m_hoverForce, hoverPoint.transform.position);
                }
            }
        }

        if(grounded)
        {
            m_rigidBody.drag = m_groundedDrag;
        }
        else
        {
            m_rigidBody.drag = 0.1f;
            m_currThrust /= 100f;
            m_currTurn /= 100f;
        }
    }
}

Raycast Vert : Suspension Relâchée (Extended)
Raycast Rouge (au sol) : Suspension Compressée

Le système fonctionne plutôt bien pour des voitures volantes, vaisseau (Wipeout) ... avec hoverHeight > 1 :super:
Cependant quand j'essaye de faire un voiture (hoverHeight = 0.5f par exemple) qui roule sur des routes penchées et loopings, la voiture ne suit pas la courbure de la route et les suspensions sont relachées :

Image

Est-ce que vous auriez un conseil ou des solutions afin de donner l'impression que l'on conduit une voiture type kart ? Please :)

En attendant j'espère que ce script peut vous être utile si vous voulez faire des prototype de jeux de courses.
Dernière édition par Cyril5 le 05 Déc 2017 01:56, édité 1 fois.

Avatar de l’utilisateur
ZJP
Messages : 5748
Inscription : 15 Déc 2009 06:00

Re: [CF-AL] Véhicule Physique Raycast (Mario Kart, Wipeout, CTR..)

Message par ZJP » 28 Nov 2017 17:39

Avec cela ?

Code : Tout sélectionner

 // Self levelling - returns the vehicle to horizontal when not grounded
 if (transform.position.y < hoverPoint.transform.position.y)
 {
         m_rigidBody.AddForceAtPosition(hoverPoint.transform.up * -m_hoverForce, hoverPoint.transform.position);
 }               }
 
Cela fonctionne sur le projet original (meilleurs, car pas de LIST<>, soit dit en passant :mrgreen: )

Cyril5
Messages : 42
Inscription : 03 Juin 2012 14:51
Localisation : Tours
Contact :

Re: [CF-AL] Véhicule Physique Raycast (Mario Kart, Wipeout, CTR..)

Message par Cyril5 » 28 Nov 2017 19:58

ZJP a écrit :
28 Nov 2017 17:39
Avec cela ?

Code : Tout sélectionner

 // Self levelling - returns the vehicle to horizontal when not grounded
 if (transform.position.y < hoverPoint.transform.position.y)
 {
         m_rigidBody.AddForceAtPosition(hoverPoint.transform.up * -m_hoverForce, hoverPoint.transform.position);
 }               }
 
Cela fonctionne sur le projet original (meilleurs, car pas de LIST<>, soit dit en passant :mrgreen: )
Non la voiture monte dans le ciel à l'infini :/

Avatar de l’utilisateur
ZJP
Messages : 5748
Inscription : 15 Déc 2009 06:00

Re: [CF-AL] Véhicule Physique Raycast (Mario Kart, Wipeout, CTR..)

Message par ZJP » 30 Nov 2017 00:15

Code : Tout sélectionner

using UnityEngine;
using System.Collections;

public class HoverCarControl : MonoBehaviour
{
	Rigidbody body;
	float deadZone = 0.1f;
	public float groundedDrag = 3f;
	public float maxVelocity = 50;
	public float hoverForce = 1000;
	public float gravityForce = 1000f;
	public float hoverHeight = 1.5f;
	public GameObject[] hoverPoints;

	public float forwardAcceleration = 8000f;
	public float reverseAcceleration = 4000f;
	float thrust = 0f;

	public float turnStrength = 1000f;
	float turnValue = 0f;

	public ParticleSystem[] dustTrails = new ParticleSystem[2];

	int layerMask;
	//private float acceleration;
	private bool moving;

	void Start()
	{
		body = GetComponent<Rigidbody>();
		body.centerOfMass = Vector3.down;

		layerMask = 1 << LayerMask.NameToLayer("Vehicle");
		layerMask = ~layerMask;
	}

	// Uncomment this to see a visual indication of the raycast hit points in the editor window
	void OnDrawGizmos()
	{

		RaycastHit hit;
		for (int i = 0; i < hoverPoints.Length; i++)
		{
			var hoverPoint = hoverPoints [i];
			if (Physics.Raycast(hoverPoint.transform.position, -Vector3.up, out hit, hoverHeight, layerMask))
			{
				Gizmos.color = Color.blue;
				Gizmos.DrawLine(hoverPoint.transform.position, hit.point);
				Gizmos.DrawSphere(hit.point, 0.5f);
			} else
			{
				Gizmos.color = Color.red;
				Gizmos.DrawLine(hoverPoint.transform.position, hoverPoint.transform.position - Vector3.up * hoverHeight);
			}
		}
	}
	
	void Update()
	{
		// Get thrust input
		thrust = 0.0f;
		float acceleration = Input.GetAxis("Vertical");
		
		if (acceleration > deadZone) thrust = acceleration * forwardAcceleration;
   	 	else if (acceleration < -deadZone) thrust = acceleration * reverseAcceleration;

		// Get turning input
		turnValue = 0.0f;
		float turnAxis = Input.GetAxis("Horizontal");
		if (Mathf.Abs(turnAxis) > deadZone) turnValue = turnAxis;
		moving = (Mathf.Abs(acceleration) > 0.02f);
	}

	void FixedUpdate()
	{
		//  Do hover/bounce force
		RaycastHit hit;
		bool  grounded = false;
		for (int i = 0; i < hoverPoints.Length; i++)
		{
			var hoverPoint = hoverPoints [i];
			if (Physics.Raycast(hoverPoint.transform.position, -Vector3.up, out hit,hoverHeight, layerMask))
			{
				body.AddForceAtPosition(Vector3.up * hoverForce* (1.0f - (hit.distance / hoverHeight)), hoverPoint.transform.position);
				grounded = true;
			}
			else
			{
				// Self levelling - returns the vehicle to horizontal when not grounded and simulates gravity - ZJP modif
				if (transform.position.y < hoverPoint.transform.position.y)
				{
					body.AddForceAtPosition(hoverPoint.transform.up * -gravityForce, hoverPoint.transform.position);
				}
			}
		}
			
		var emissionRate = 0;
		if(grounded)
		{
			body.drag = groundedDrag;
			emissionRate = 10;
		}
		else
		{
			body.drag = 0.1f;
			thrust /= 100f;
			turnValue /= 100f;
		}

		for(int i = 0; i<dustTrails.Length; i++)
		{
			var emission = dustTrails[i].emission;
			emission.rate = new ParticleSystem.MinMaxCurve(emissionRate);
		}

		// Handle Forward and Reverse forces
		if (Mathf.Abs(thrust) > 0.02f) body.AddForce(transform.forward * thrust);

		
		if (moving) // ZJP ajout
		{
			// Handle Turn forces
			if (Mathf.Abs(turnValue) > 0.02f) body.AddRelativeTorque(Vector3.up * turnValue * turnStrength);
		}

		// Limit max velocity
		if(body.velocity.sqrMagnitude > (body.velocity.normalized * maxVelocity).sqrMagnitude)
		{
			body.velocity = body.velocity.normalized * maxVelocity;
		}
	}
}

Pas ce souci ici. Bizarre... :?

Cyril5
Messages : 42
Inscription : 03 Juin 2012 14:51
Localisation : Tours
Contact :

Re: [CF-AL] Véhicule Physique Raycast (Mario Kart, Wipeout, CTR..)

Message par Cyril5 » 01 Déc 2017 02:36

D' accord tu as modifié le script du tuto, Je vais essayer ton script et je te tiens au courant.
A tu utilisé des réglages particulier ?

Avatar de l’utilisateur
ZJP
Messages : 5748
Inscription : 15 Déc 2009 06:00

Re: [CF-AL] Véhicule Physique Raycast (Mario Kart, Wipeout, CTR..)

Message par ZJP » 01 Déc 2017 16:36

Cyril5 a écrit :
01 Déc 2017 02:36
A tu utilisé des réglages particulier ?
Non. Seulement touché a ce script par rapport au projet original. ;-)

Cyril5
Messages : 42
Inscription : 03 Juin 2012 14:51
Localisation : Tours
Contact :

Re: [CF-AL] Véhicule Physique Raycast (Mario Kart, Wipeout, CTR..)

Message par Cyril5 » 04 Déc 2017 19:45

C'est cool ça fonctionne merci :) ça marche mieux quand on utilise gravityForce pour la stabilisation du véhicule

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

Re: [CF-AL] Véhicule Physique Raycast (Mario Kart, Wipeout, CTR..)

Message par Max » 04 Déc 2017 22:11

Bonsoir,

si effectivement tu as solutionné ton soucis, passe ton sujet en résolu (édition du premier post, et au niveau du tire, ajouter[RESOLU]). Merci ;)
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

Répondre

Revenir vers « (C#) CSharp »