Quaternion.Lerp din Unity încetinește atunci când ținta se află direct în spatele turelei (Dezvoltarea jocurilor, Unitate, Quaternion, Lerp)

Stijn van der Pol a intrebat.

Software: Unity v5.2.1f1 Personal

Încerc să obțin efectul unei turele în Unity. Pentru aceasta am o turelă formată din 3 părți, precum și o țintă. Problema este că ori de câte ori ținta pe care o vizează turela mea are un z de < 0, lerp viteză este extrem de lentă. Cu toate acestea, cu cât ținta este mai departe de x=0 (atât pozitiv cât și negativ), cu atât se va mișca mai repede. Acest efect apare numai atunci când ținta mea are o transform.position.z de < 0. Când z > 0, transform.position.x nu are niciun efect asupra lerp. viteză. Configurația mea este după cum urmează:

Cele 3 părți ale turelei sunt baza, , turela și țeava.

bază nu este nimic mai mult decât un bloc pentru turelă să se sprijine. turelă este un bloc care ține țeava în poziție cu baza ca părinte al acestuia. turelă se rotește în jurul lui axa y pentru a fi mereu cu fața la țintă. țeava are turelă ca părinte. baril se rotește în jurul lui axa x pentru a fi mereu cu fața la țintă. Vedeți imaginea de mai jos pentru rezultatul final.

Baza: Albastru; turelă: Roșu; țeava: Verde;

turelă are următorul cod:

public class turretRotation : MonoBehaviour {

    public Transform target;

    void Update()
    {
        Vector3 relativePosition = target.position - transform.position;
        relativePosition.y = 0;
        Quaternion rotation = Quaternion.LookRotation(relativePosition, new Vector3(0, 1, 0));
        transform.localRotation = Quaternion.Lerp(transform.localRotation, rotation, Time.deltaTime);
    }
}

țeava are următorul cod:

public class barrelRotation : MonoBehaviour {

    public Transform target;
    public float speed = 1;
    Vector3 relPos;
    Quaternion rot;

    void Update () {
        // Position of target relative to my position
        relPos = (target.position - transform.position).normalized;

        rot = Quaternion.LookRotation(relPos, new Vector3(0,1,0));

        // Lerping localRotatiot > rot with speed: Time.deltaTime * speed (set to 1 by default)
        transform.localRotation = Quaternion.Lerp(transform.localRotation, rot, Time.deltaTime *  speed);

        // Resetting y- and z-EulerAngles to 0; This way only the x-EulerAngle will be affected. 
        // The y rotation is inherited from the parent (turret_turret)
        transform.localEulerAngles = new Vector3(transform.localEulerAngles.x, 0, 0);
    }
}

În această imagine, Lerp funcționează așa cum a fost prevăzut; Notă target.transform.z > 0

În această imagine, ținta are un z = -5 și x = 0; acordați o atenție deosebită vitezei Lerp.

În cele din urmă ajunge la destinație, dar îi ia un timp foarte mult timp. Dintr-un motiv oarecare, cu cât ținta este mai departe de x=0, cu atât viteza Lerp este mai mare. Notă: Încă mai lent decât se dorește

În această imagine, ținta are z = -5 și x = -10

Deci, dintr-un motiv oarecare, atunci când target.transform.z are o valoare negativă, cu cât distanța de la target.transform.x la x=0 este mai mare, cu atât Lerp este mai mare. viteza Lerp.

Am căutat destul de mult și am dat peste o postare pe answers.unity.com care descria o problemă asemănătoare; din păcate, nu am primit niciun răspuns. http://answers.unity3d.com/questions/1084067/lerp-problem-when-target-is-behind.html

Deci, întrebarea mea este: „De ce se întâmplă acest lucru și, mai important, cum pot rezolva acest lucru?”

Orice ajutor ar fi foarte apreciat!

Comentarii

  • Deoarece depinde de distanță, s-ar putea să fie ceva în neregulă cu normalizarea – poate că reformularea codului(folosind variabila temp, sau Normalize() în loc de .normalized) ar ajuta?-.  > Por wondra.
  • Mulțumesc pentru răspuns, am încercat să folosesc Vector3.Normalize() în loc de .normalized, dar fără succes. Totuși, nu sunt sigur la ce vă referiți cu utilizarea variabilelor temporare. Ați putea să mă lămuriți mai bine? Vă mulțumesc din nou pentru ajutor.-  > Por Stijn van der Pol.
  • Atribuirea rezultatului (loc-țintă) la o variabilă locală, normalizarea pe linia următoare, doar pentru a fi super sigur că problema nu este normalizarea.-  > Por wondra.
  • Ah, am încercat, dar, din păcate, problema persistă în continuare.-  > Por Stijn van der Pol.
1 răspunsuri
DMGregory

Aruncând o privire la funcția de rotație a butoiului…

relPos = (target.position - transform.position).normalized;
rot = Quaternion.LookRotation(relPos, new Vector3(0,1,0));

relPos este în spațiul mondial, deci rot este o rotație absolută (adică relativă la cadru de coordonate al lumii)

transform.localRotation = Quaternion.Lerp(
      transform.localRotation, 
      rot,
      Time.deltaTime *  speed);

transform.localRotation este relativă la spațiul de coordonate al părintelui.

Astfel, acest Lerp se amestecă între o orientare relativă și una absolută..

Atunci când utilizați Lerp în acest mod, viteza sau creșterea fiecărui cadru este proporțională cu diferența dintre valorile de început & end. (Acest lucru adaugă un pic de încetinire plăcută pe măsură ce rotația se apropie de țintă în comparație cu Quaternion.RotateTowards() care impune o anumită viteză)

Presupunând că țeava ta este deja îndreptată oarecum în apropierea țintei tale…

  • Atunci când rotația părintelui este foarte asemănătoare cu cadrul coordonatelor lumii, diferența dintre transform.localRotation și rot va tinde să fie mică (urmărire lentă).

  • Atunci când rotirea părintelui este foarte mare în raport cu coordonatele lumii, diferența dintre transform.localRotation și rot va tinde să fie foarte mare (urmărire rapidă).

Prin urmare, trebuie să vă asigurați că folosiți comparații între mere atunci când faceți Lerping – fie lucrați în întregime în spațiul local (de exemplu, cu transform.parent.InverseTransformDirection(relPos) sau Quaternion.Inverse(transform.parent.rotation) ), fie în întregime în spațiul mondial.

Comentarii

  • Vă mulțumim pentru răspuns și pentru explicațiile amănunțite. Am înțeles greșeala mea și am adăugat linia relPos = transform.parent.InverseTransformDirection(relPos);. Acum funcționează perfect. Din nou, vă mulțumesc foarte mult.-  > Por Stijn van der Pol.