Как я могу дождаться окончания вращения объекта, а затем воспроизвести анимацию? - PullRequest
0 голосов
/ 09 марта 2020
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;

public class RoboSphereWindowBreakInteraction : MonoBehaviour
{
    public Transform target;
    public InteractableObjects interactableObjects;
    public AudioClip audioClip;
    public float speed;

    private bool hasStarted = false;
    private Animator anim;

    void Update()
    {
        if ((Input.GetKeyDown(KeyCode.B) || (hasStarted == true)))
        {
            float step = speed * Time.deltaTime; // calculate distance to move
            transform.position = Vector3.MoveTowards(transform.position, target.position, step);

            hasStarted = true;
        }
    }

    private void OnTriggerEnter(Collider other)
    {
        if (other.gameObject.name == "Square 1")
        {
            GetComponent<Rigidbody>().isKinematic = false;
            hasStarted = false;
            Destroy(GameObject.Find("Wall_Window_Long_03"));
        }
    }

    public void ActivateRoboSphere()
    {
        foreach(Transform child in transform)
        {
            if(child.name == "Camera")
            {
                RepositionCamera(child);
            }
        }

        anim = GetComponent<Animator>();
        anim.enabled = true;

        StartCoroutine(PlayAudio());
    }

    private void RepositionCamera(Transform camera)
    {
        var Eyes = GameObject.Find("eyeDome");

        camera.position = Eyes.transform.position + Eyes.transform.forward;
        camera.LookAt(Eyes.transform);
        camera.GetComponent<Camera>().enabled = true;
    }

    IEnumerator PlayAudio()
    {
        AudioSource audio = GetComponent<AudioSource>();

        audio.clip = audioClip;
        audio.Play();
        yield return new WaitForSeconds(audio.clip.length);

        var rotation = Quaternion.LookRotation(target.position - transform.position);
        StartCoroutine(Spin(3f, rotation));

        anim.SetBool("Roll_Anim", true);
    }

    IEnumerator Spin(float lerpTime, Quaternion rotation)
    {
        float elapsedTime = 0f;

        while (elapsedTime <= lerpTime)
        {
            transform.rotation = Quaternion.Slerp(transform.rotation, rotation, elapsedTime / lerpTime);
            elapsedTime += Time.deltaTime;
            yield return null;
        }
    }
}

Но когда анимация запускает вращение объекта, но не к цели, по крайней мере, к цели, которую я хотел.

Объект, сфера которого начинает вращаться лицом к окну (на скриншоте на заднем плане в верхний вид сцены), но затем он меняет лицевую сторону, обращенную к камере (камера, являющаяся дочерним элементом преобразования).

Метод ActivateRoboSphere вызывает RepositionCamera и ActivateRoboSphere вызывается один раз при щелчке мыши в событие щелчка.

Но по какой-то причине, когда объект воспроизводит анимацию «Roll_Anim», он снова направлен на камеру, а не на окно цели.

Я пометил цель окна там, где она должна быть с красным квадратом на скриншоте:

Facing the robosphere child camera on the left and not the window target marked with red square

Ответы [ 2 ]

3 голосов
/ 09 марта 2020

В вашем случае вы можете заставить свой вызов IEnumerator ждать, пока другой вызов не будет завершен, просто yield используя его как

...

// executes and at the same time waits for Spin to finish
yield return Spin(3f, rotation);

// called when Spin routine is finished
anim.SetBool("Roll_Anim", true);

В качестве альтернативы, вместо сторонней библиотеки инструментов как предложено здесь вы можете просто добавить обратный вызов как

IEnumerator Spin(float lerpTime, Quaternion rotation, Action whenDone)
{
    float elapsedTime = 0f;

    while (elapsedTime <= lerpTime)
    {
        transform.rotation = Quaternion.Slerp(transform.rotation, rotation, elapsedTime / lerpTime);
        elapsedTime += Time.deltaTime;
        yield return null;
    }

    whenDone?.Invoke();
}

и затем запустить подпрограмму, используя лямбда-выражение типа

StartCoroutine(Spin(3f, rotation, () => 
{
    anim.SetBool("Roll_Anim", true);
}));

или вызов метода, подобный

private void AfterSpinning()
{
    anim.SetBool("Roll_Anim", true);
}

...

StartCoroutine(Spin(3f, rotation, AfterSpinning));
1 голос
/ 09 марта 2020

Лучше использовать анимацию движения, например http://dotween.demigiant.com/.

Если вы установите Dotween, вы можете просто использовать

transform.DORotate(new vector3(0 ,100 , 0) , duration);

Вы также можете установить Легкость для подростков. или используйте незавершенные функции;

transform.DORotate(new vector3(1 ,0 , 1) , duration)
    .SetEase(Ease.OutCubic)
    .OnCompelete(() => { shouldClose = true; }); 

Вы также можете установить al oop для своей анимации .SetLoops(-1).

В дополнение к этому, вы можете использовать sequences для показа нескольких анимаций. вместе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...