[MY-AL] Adapter la rotation du rigidbody au terrain pour un fan game sonic ?

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
pikachuk
Messages : 9
Inscription : 19 Juil 2016 03:56

[MY-AL] Adapter la rotation du rigidbody au terrain pour un fan game sonic ?

Message par pikachuk » 27 Juin 2017 16:59

Bonjour, je réalise un fan game sonic, ça ressemble actuellement à ça
https://www.youtube.com/watch?v=DTcEw7bOXXE
j'aimerais pouvoir y ajouter des loopings comme les jeux sonic originaux
mais le probleme est qu'il faudrait que sonic adapte automatiquement sa rotation au niveau du sol sur lequel il est pour que son corps aussi fasse la rotation du looping s'il va assez vite
je pense qu'il faudra utiliser les raycast mais j'ai jamais utilisé les raycast, je ne saurais donc pas trop comment l'utiliser dans mon cas, j'utilise actuellement un trigger pour detecter si sonic est en l'air ou sur le sol

pourriez vous m'aider sur la façon dont je devrais m'y prendre ? merci d'avance

ps : sonic fonctionne par un rigidbody avec un capsule collider et le script actuel est :

Code : Tout sélectionner

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class TestCubeScript : MonoBehaviour
{
    public bool Dead;
    Vector3 forward;
    AudioClip Jump;
    public FloorDetection floorcollider;
    Vector3 right;
    public float forcejump;
    public Animation anims;
    public string idle;
    public string walk;
    bool normalstate;
    public GameObject Ball;
    public SkinnedMeshRenderer SonicRenderer;
    public Rigidbody rb;
    AudioClip GetRing;
 
    public float speed;
    float currentspeed;
    public bool isRunning;
    public float maxspeed;
    public RingsCounterScript ringcount;
    public float timejump = 1.5f;
    public string run;
    bool isJumping;
    public bool canmove;
    float derapage = 0f;
    Camera maincam;
   public float moveSpeed= 6; // move speed
float turnSpeed = 90; // turning speed (degrees/second)
float lerpSpeed = 10; // smoothing speed
float gravity = 70; // gravity acceleration
bool isGrounded;
float deltaGround= 0.2f; // character is grounded up to this distance
float jumpSpeed = 10; // vertical jump initial speed
float jumpRange = 10; // range to detect target wall
    CapsuleCollider col;
private Vector3 surfaceNormal; // current surface normal
private Vector3 myNormal; // character normal
private float distGround; // distance from character position to ground
private bool jumping = false; // flag "I'm jumping to wall"
    private float vertSpeed = 0; // vertical jump current speed
    // Use this for initialization
    public void SetNormalState()
    {
     
        normalstate = true;
        canmove = true;
    }
    void Start()
    {
        col = GetComponent<CapsuleCollider>();
        myNormal = transform.up; // normal starts as character up direction
        rb.freezeRotation = true; // disable physics rotation
                                     
        distGround = col.bounds.extents.y - col.center.y;  // distance from transform.position to ground
        Ball.SetActive(false);
      GetRing =  (AudioClip)Resources.Load("Sound Effects/Sonic Ring Sound");
 
        Jump = (AudioClip)Resources.Load("Sound Effects/Jump");
        currentspeed = speed;
        anims["JumpEnd"].speed = 4;
        anims[run].speed = 4;
        anims.Play(idle);
        Cursor.lockState = CursorLockMode.Locked;
        maincam = Camera.main;
        SetNormalState();
    }
    private void Update()
    {
     
     
            if (Input.GetButton("Submit") && !isJumping)
        {
            isJumping = true;
                StartCoroutine(jump(timejump));
                AudioSource aS = gameObject.GetComponent<AudioSource>();
                if (aS == null)
                {
                    aS = gameObject.AddComponent<AudioSource>();
                }
                AudioClip leclip = Jump;
                aS.clip = Jump;
                aS.Play();
            }
        if (floorcollider.floor)
        {
 
            isJumping = false;
 
        }
if (isJumping)
        {
 
            if (!anims.IsPlaying("BallLoop"))
            {
                normalstate = false;
                anims.CrossFade("BallLoop", 0.2f);
           
                SonicRenderer.enabled = false;
                Ball.SetActive(true);
            }
        }
        else
        {
            if (!normalstate)
            {
                canmove = false;
                anims.CrossFade("JumpEnd", 0.2f);
             
            }
            SonicRenderer.enabled = true;
            Ball.SetActive(false);
 
            isJumping = false;
        }
 
    }
    // Update is called once per frame
    void FixedUpdate()
    {
        rb.AddForce(0,-gravity * rb.mass,0 );
        forward = maincam.transform.TransformDirection(Vector3.forward);
        forward.y = 0;
        forward = forward.normalized;
        right = new Vector3(forward.z, 0, -forward.x);
        float h = Input.GetAxis("Horizontal");
        float v = Input.GetAxis("Vertical");
        float mag = Mathf.Clamp01(new Vector2(h, v).magnitude);
        if (mag > 0.1)
        {
derapage = mag;
            if (currentspeed < maxspeed && mag == 1)
            {
                currentspeed += 0.1f;
                anims[run].speed += 0.02f;
            }
        }
        else
        {
            derapage -= 0.03f;
            if (currentspeed > speed)
            {
                currentspeed = speed;
            }
            if (anims[run].speed > 1)
            {
anims[run].speed = 1;
            }
           
        }
        Vector3 moveDirection = Vector3.zero;
        if (mag != 0)
        {
            moveDirection = (h * right + v * forward);
        }
        else
        {
            moveDirection = transform.forward;
        }
        // moveDirection *= speed;
        anims[walk].speed = derapage * 8;
        if (derapage > 0.1 && derapage < 1 && !anims.IsPlaying(walk) && !isJumping && normalstate)
        {
            anims.CrossFade(walk, 0.2f);
        }
        else if (derapage == 1 && !anims.IsPlaying(run) && !isJumping && normalstate)
        {
            anims.CrossFade(run, 0.2f);
            isRunning = true;
        }
        else if (derapage < 0.1 && !anims.IsPlaying(idle) && !isJumping && normalstate)
        {
            anims.CrossFade(idle, 0.2f);
        }
        if (derapage > 0 && canmove)
        {
         
            if (mag != 0)
            {
                transform.rotation = Quaternion.LookRotation(moveDirection);
            }
            if (derapage > 0.1 )
            {
                rb.position += transform.forward * currentspeed * derapage * Time.deltaTime;
 
 
            }
       
 
 
 
 
 
 
        }
       
   
     
    }
 
    public void AddRing()
    {
        ringcount.ringcount += 1;
        AudioSource aS = gameObject.GetComponent<AudioSource>();
        if (aS == null)
            {
             aS = gameObject.AddComponent<AudioSource>();
        }
        AudioClip leclip = GetRing;
        aS.PlayOneShot(leclip, 1f);
    }
    IEnumerator jump(float time)
    {
 
        StartCoroutine(JumpAnims());
 
        while (Input.GetButton("Submit") && time > 0)
        {
       
            time -= Time.deltaTime;
            rb.AddForce(new Vector3(0, forcejump, 0), ForceMode.Impulse);
            yield return 0;
        }
 
 
 
    }
    IEnumerator JumpAnims()
    {
       
            anims.CrossFade("JumpStart00", 0.2f);
       
     
        yield return 0;
     
       
     
 
 
    }
}
 
(je n'ai pas encore changé le nom de la classe quand je testais sur un cube)

Avatar de l’utilisateur
boubouk50
ModoGenereux
ModoGenereux
Messages : 6262
Inscription : 28 Avr 2014 11:57
Localisation : Saint-Didier-en-Bresse (71)

Re: [MY-AL] Adapter la rotation du rigidbody au terrain pour un fan game sonic ?

Message par boubouk50 » 27 Juin 2017 17:24

Je serais également parti pour un raycast vers le bas du personnage (son Y-local) qui ne chercherai que le terrain et avec une distance limitée -> Ainsi, seul le terrain est détecté (layer) et si ton perso est trop loin du sol, il ne tourne pas (maxDistance).
La documentation est très claire sur le Raycast et les exemples à foison, ça ne sera pas trop difficile à mettre en place. C'est surtout la gestion des forces qui pourrait être difficile.

Une remarque sur ta vidéo, met tes animations de ring en linéaire ou bien fait le en script, parce que les béziers lissants en début et fin d'animation empêche la constance de la rotation. (Sauf si dans l'original il avait laissé ce comportement)
"Ce n'est pas en améliorant la bougie, que l'on a inventé l'ampoule, c'est en marchant longtemps."
Nétiquette du forum
Savoir faire une recherche
Apprendre la programmation

pikachuk
Messages : 9
Inscription : 19 Juil 2016 03:56

Re: [MY-AL] Adapter la rotation du rigidbody au terrain pour un fan game sonic ?

Message par pikachuk » 27 Juin 2017 17:35

boubouk50 a écrit :Je serais également parti pour un raycast vers le bas du personnage (son Y-local) qui ne chercherai que le terrain et avec une distance limitée -> Ainsi, seul le terrain est détecté (layer) et si ton perso est trop loin du sol, il ne tourne pas (maxDistance).
La documentation est très claire sur le Raycast et les exemples à foison, ça ne sera pas trop difficile à mettre en place. C'est surtout la gestion des forces qui pourrait être difficile.

Une remarque sur ta vidéo, met tes animations de ring en linéaire ou bien fait le en script, parce que les béziers lissants en début et fin d'animation empêche la constance de la rotation. (Sauf si dans l'original il avait laissé ce comportement)
Merci pour ton conseil au niveau des rings
sinon pour le raycast je comprends pas trop, mon probleme est surtout dans le fait de déterminer quelle rotation le personnage doit avoir dépendamment de comment le raycast réagit
comme je n'ai jamais utilisé de raycast je suis completement perdu

je vois que le raycast peut donner la distance précise entre l'objet d'origine et la collision avec la destination ainsi que la position mais je ne sais pas trop comment me servir de ces infos,

Avatar de l’utilisateur
boubouk50
ModoGenereux
ModoGenereux
Messages : 6262
Inscription : 28 Avr 2014 11:57
Localisation : Saint-Didier-en-Bresse (71)

Re: [MY-AL] Adapter la rotation du rigidbody au terrain pour un fan game sonic ?

Message par boubouk50 » 27 Juin 2017 17:42

Désolé, je t'ai donné une demie réponse, fin de journée, toussa...

Ton Raycast te sort un RaycastHit -> (out RaycastHit hitInfo).
Ce raycastHit te donne la normale (voir exemple ici) au sol, donc le vecteur dont tu as besoin pour caler ton perso -> l'axe vertical du perso doit donc "s'aligner" dessus. -> Voir si la projection fonctionne mais attention à bien garder la direction.
"Ce n'est pas en améliorant la bougie, que l'on a inventé l'ampoule, c'est en marchant longtemps."
Nétiquette du forum
Savoir faire une recherche
Apprendre la programmation

pikachuk
Messages : 9
Inscription : 19 Juil 2016 03:56

Re: [MY-AL] Adapter la rotation du rigidbody au terrain pour un fan game sonic ?

Message par pikachuk » 27 Juin 2017 17:52

boubouk50 a écrit :Désolé, je t'ai donné une demie réponse, fin de journée, toussa...

Ton Raycast te sort un RaycastHit -> (out RaycastHit hitInfo).
Ce raycastHit te donne la normale (voir exemple ici) au sol, donc le vecteur dont tu as besoin pour caler ton perso -> l'axe vertical du perso doit donc "s'aligner" dessus. -> Voir si la projection fonctionne mais attention à bien garder la direction.
Merci beaucoup, je vais essayer

pikachuk
Messages : 9
Inscription : 19 Juil 2016 03:56

Re: [MY-AL] Adapter la rotation du rigidbody au terrain pour un fan game sonic ?

Message par pikachuk » 27 Juin 2017 20:03

je viens d'essayer ça

Code : Tout sélectionner

   RaycastHit hit;
		if (Physics.Raycast(transform.position,-transform.up,out hit,1f))
        {

            Quaternion larotation  = Quaternion.FromToRotation(transform.up, hit.normal);
            Vector3 rotationvector = larotation.eulerAngles;
            transform.eulerAngles = new Vector3(rotationvector.x,transform.eulerAngles.y,rotationvector.z);
        }
        else
        {
            transform.eulerAngles = new Vector3(DefaultRotation.x, transform.eulerAngles.y, DefaultRotation.z);
        }
j'y suis presque mais si la surface n'est pas fluide sonic se met à bouger d'une façon très etrange
https://youtu.be/AthWimYHyYY

zebilamouche
Messages : 38
Inscription : 17 Juin 2016 20:34

Re: [MY-AL] Adapter la rotation du rigidbody au terrain pour un fan game sonic ?

Message par zebilamouche » 27 Juin 2017 20:56

Salut Pikachuck,
j'ai peut-être mal compris ce que tu cherchais à faire, mais ça ne serait pas mieux de remplacer :

Code : Tout sélectionner

if (Physics.Raycast(transform.position,-transform.up,out hit,1f))
Par :

Code : Tout sélectionner

if (Physics.Raycast(transform.position,Vector3.down,out hit,1f))
?

pikachuk
Messages : 9
Inscription : 19 Juil 2016 03:56

Re: [MY-AL] Adapter la rotation du rigidbody au terrain pour un fan game sonic ?

Message par pikachuk » 27 Juin 2017 21:13

zebilamouche a écrit :Salut Pikachuck,
j'ai peut-être mal compris ce que tu cherchais à faire, mais ça ne serait pas mieux de remplacer :

Code : Tout sélectionner

if (Physics.Raycast(transform.position,-transform.up,out hit,1f))
Par :

Code : Tout sélectionner

if (Physics.Raycast(transform.position,Vector3.down,out hit,1f))
?
je ne sais pas trop

pour expliquer j'aimerais que sonic réagisse comme dans les looping et terrains des jeux originaux :
https://youtu.be/RRbB1hq9IGk?t=57
sa rotation doit s'adapter à celle du terrain et s'il va assez vite dans les loopings il pourrait les parcourir

zebilamouche
Messages : 38
Inscription : 17 Juin 2016 20:34

Re: [MY-AL] Adapter la rotation du rigidbody au terrain pour un fan game sonic ?

Message par zebilamouche » 27 Juin 2017 21:27

Ah !
Le -transform.up est bon je crois.
Je pense que ça vient du RayCast
Essaye un :

Code : Tout sélectionner

Debug.Log(hit.collider.gameObject.name)
Pour voir si le RayCast ne toucherai pas Sonic, si c'est le cas je pense pouvoir t'aider.

pikachuk
Messages : 9
Inscription : 19 Juil 2016 03:56

Re: [MY-AL] Adapter la rotation du rigidbody au terrain pour un fan game sonic ?

Message par pikachuk » 27 Juin 2017 21:38

zebilamouche a écrit :Ah !
Le -transform.up est bon je crois.
Je pense que ça vient du RayCast
Essaye un :

Code : Tout sélectionner

Debug.Log(hit.collider.gameObject.name)
Pour voir si le RayCast ne toucherai pas Sonic, si c'est le cas je pense pouvoir t'aider.
j'avais déjà test tout à l'heure ça touche le terrain

Répondre

Revenir vers « (C#) CSharp »