如何在不同的时间只调用一次不同的方法?
How to call different methods only once, at different times?
我正在尝试使用 Actions 和 Events、Inumerators 和 Coroutines,但我感到很困惑。
目标:让 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 但这已经变得非常复杂了。
在这里使用事件确实使您想要做的事情变得过于复杂。
我会用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
}
}
我正在尝试使用 Actions 和 Events、Inumerators 和 Coroutines,但我感到很困惑。
目标:让 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 但这已经变得非常复杂了。
在这里使用事件确实使您想要做的事情变得过于复杂。
我会用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
}
}