Как да извикате различни методи само веднъж, по различно време?

Опитвам се да използвам действия и събития, изброители и корутини, но ставам толкова объркан.

Целта: Накарайте MoveCubes() да се изпълнява веднъж за 3 секунди и след това да накарате LerpSine() да се изпълнява веднъж за 3 секунди.

Секундите се проследяват от CountdownTimer.cs. Тогава SkinnedMeshSpawn.cs взаимодейства с него.

Таймер за обратно броене:

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

public class CountdownTimer : MonoBehaviour
{
    float currentTime = 0f;
    float startingTime = 10f;
    public static event Action RaiseReady;
    public static event Action RaiseReady2;
    public SkinnedMeshSpawn SkinnedMeshSpawn;

    void Start()
    {
        currentTime = startingTime;     
        StartCoroutine(UpdateCoroutine());
    }

    IEnumerator UpdateCoroutine()
    {
        while (true)
        {
            SkinnedMeshSpawn.GetComponent<SkinnedMeshSpawn>().MoveCubes();
            currentTime -= 1 * Time.deltaTime; //does it each frame
            int n = Convert.ToInt32(currentTime);

            if (n == 7)
            {
                RaiseReady?.Invoke();
                RaiseReady = null; // clean the event
                yield break; // Kills the coroutine
            }
            yield return new WaitForFixedUpdate();
        }
    }

    IEnumerator UpdateCoroutine2()
    {
        while (true)
        {
            SkinnedMeshSpawn.GetComponent<SkinnedMeshSpawn>().LerpSine();
            currentTime -= 1 * Time.deltaTime; //does it each frame
            int n = Convert.ToInt32(currentTime);

            if (n == 4)
            {
                RaiseReady2?.Invoke();
                RaiseReady2 = null; // clean the event
                yield break; // Kills the coroutine

            }
            yield return new WaitForFixedUpdate();
        }
    }
}

SkinnedMeshSpawn:

using UnityEngine;

[RequireComponent(typeof(SkinnedMeshRenderer))]
public class SkinnedMeshSpawn : MonoBehaviour
{
    public GameObject CubePrefab;
    public GameObject[] objects;
    SkinnedMesh mesh;
    public Rigidbody cubePrefabRb;

    public Vector3[] verts;

    int runOnce = 1;

    void Awake()
    {
        mesh = GetComponent<SkinnedMesh>();
        verts = new Vector3[mesh.vertexCount];
    }
    void Start()
    {
        verts = mesh.vertices;

        CountdownTimer.RaiseReady += CountdownTimer_RaiseReady;
        CountdownTimer.RaiseReady2 += CountdownTimer_RaiseReady2;

        mesh.OnResultsReady += DrawVertices;
    }
    void CountdownTimer_RaiseReady()
    {
        Debug.Log("Done");
        CountdownTimer.RaiseReady -= CountdownTimer_RaiseReady; // Remove listener though the other class is already clearing it
    }

    private void CountdownTimer_RaiseReady2()
    {
        Debug.Log("Done2");
        CountdownTimer.RaiseReady2 -= CountdownTimer_RaiseReady; // Remove listener though the other class is already clearing it
    }

    void DrawVertices(SkinnedMesh mesh)
    {
        if (runOnce == 1)
        {
            for (int i = 0; i < mesh.vertexCount; i++)
            {
                Vector3 position = verts[i];
                var cubeClone = Instantiate(CubePrefab, position, transform.rotation);
                cubeClone.tag = "CubePFInst";
            }
            runOnce = 0;
        }
    }


    public void MoveCubes()
    {
        if (runOnce == 0)
        {
            objects = GameObject.FindGameObjectsWithTag("CubePFInst");

            for (int i = 0; i < mesh.vertexCount; i++)
            {
                Vector3 position = verts[i];
                cubePrefabRb = objects[i].GetComponent<Rigidbody>();
                cubePrefabRb.MovePosition(Vector3.Lerp(position, position, Time.deltaTime * 6));
            }
        }
    }

    public void LerpSine()
    {
        Debug.Log("LerpSine");
    }
}

Най-многото, което успях да постигна досега, е да накарам UpdateCoroutine2 да бъде извикан и да накарам Done2 да се отпечата в журнала, но LerpSine се отпечатва многократно, сякаш стартирам съпрограмата с всяка актуализация на рамка.

Ще съм благодарен, ако някой може да прегледа кода и да даде предложения как да се постигне целта, посочена по-горе. По-късно исках да внедря GameManager, но това вече става много сложно.


person rashapou    schedule 10.07.2019    source източник
comment
Имам проблем да видя как се извиква UpdateCoroutine2.   -  person Ruzihm    schedule 10.07.2019
comment
Добре, събитие е като OnClick, като кратка версия действието е нещо, което се извиква в резултат на щракването (има и други причини), така че това изобщо не е това, от което се нуждаете... и как извиквате UpdateCoroutine2 не е включен в предоставения код.. сложихте ли го в актуализация?   -  person BugFinder    schedule 10.07.2019
comment
Опитите ми не са в посочения код, защото станаха много объркани; Извадих ги и оставих остатъка от това, което имах. Да, поставих го във функцията за актуализиране, защото не бях сигурен как да извикам нещо, след като кодът вече се изпълнява, освен това. Е, аз също се опитах да внедря друг IEnumerator и да извикам UpdateCoroutine2, когато достигне определено време, но това също го извика многократно по някаква причина. Ще се опитам да го напиша отново как го имах в последния си опит, но не знам как да се опитам да променя нещата.   -  person rashapou    schedule 11.07.2019
comment
Извиква многократно, защото е в while цикъл, който повтаря всяка фиксирана актуализация за 3 секунди...   -  person Ruzihm    schedule 11.07.2019


Отговори (1)


Използването на събития тук е наистина прекалено усложняване на нещата за нещото, което изглежда искате да направите.

Бих използвал yield return new WaitForSeconds(seconds); за време на нещата:

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

public class CountdownTimer : MonoBehaviour
{

    public SkinnedMeshSpawn SkinnedMeshSpawn;

    void Start()
    { 
        StartCoroutine(FunctionCaller(3f,3f));
    }

    IEnumerator FunctionCaller(float pause1, float pause2)
    {
        SkinnedMeshSpawn.GetComponent<SkinnedMeshSpawn>().MoveCubes();

        yield return new WaitForSeconds(pause1);

        SkinnedMeshSpawn.GetComponent<SkinnedMeshSpawn>().LerpSine();

        yield return new WaitForSeconds(pause2);

        // Do whatever after pause 2
    }
}
person Ruzihm    schedule 11.07.2019
comment
Много благодаря. Това има много повече смисъл. - person rashapou; 12.07.2019