我使用libpd4unity包与 Pure Data 进行通信。我收到了来自 Pure Data 的LibPD.Bang
. 在爆炸事件中,我通过 FMOD 播放声音。
问题是,我经常收到刘海,例如每 500 毫秒一次,但事件不会在特定长度的帧中触发。通常长度变化 1 帧更少或更多。
这个问题有解决方案吗?例如帧率独立事件?我想知道 Unity3D 中的事件(委托)是否与帧速率无关。
因为播放每个声音都有节奏,只有一帧会破坏节奏。
我需要同步每个单独的 bang 播放的声音。
关于代表是依赖于还是独立于 Unity 的帧率的问题,没有直接的答案。这取决于如何调用您的代表。他们是从线程中调用的吗?它们是在一个线程中执行的吗?协程不是独立于帧率的,它们在 Unity 的循环中执行。
以下脚本应该阐明在协程和线程中处理委托之间的区别。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading;
public class DelegatesAndFramerate : MonoBehaviour {
delegate void MyDelegate();
MyDelegate myDelegate1; // done with coroutines
MyDelegate myDelegate2; // done with threads
Thread thread;
bool threadDone = false;
private int frameCount = 0;
private int delegate1CallCount = 0;
private int delegate2CallCount = 0;
private int callerLoopsCount_coroutine = 0;
private int callerLoopsCount_thread = 0;
void Start () {
myDelegate1 += Elab1;
myDelegate2 += Elab2;
StartCoroutine(CallerCoroutine());
thread = new Thread(new ThreadStart(CallerThread));
thread.Start();
}
void Update()
{
frameCount++;
}
void Elab1()
{
delegate1CallCount++;
}
void Elab2()
{
delegate2CallCount++;
}
IEnumerator CallerCoroutine()
{
while(true)
{
callerLoopsCount_coroutine++;
myDelegate1();
yield return null;
}
}
void CallerThread()
{
while(!threadDone)
{
callerLoopsCount_thread++;
myDelegate2();
}
}
void OnDestroy()
{
Debug.Log("Frame Count: " + frameCount);
Debug.Log("Delegate Call Count (Coroutine): " + delegate1CallCount);
Debug.Log("Delegate Call Count (Thread): " + delegate2CallCount);
Debug.Log("Caller Loops Count (Coroutine): " + callerLoopsCount_coroutine);
Debug.Log("Caller Loops Count (Thread): " + callerLoopsCount_thread);
threadDone = true;
thread.Join();
}
}
如果将它附加到 GameObject 并让 Unity 播放几秒钟,您会看到从协程调用委托的次数等于执行的帧数,而从线程调用委托的次数会更大.
我在连接类似于 Pure Data 的软件方面有经验,我认为您需要的是一个(相当典型的)线程,其中包含所有代表,为 Unity 创建一个命令队列并在 Unity 的更新中消化它。不知道具体的 libPD,这可能不是该案例的最佳实践,但它是一种广泛使用的方法。基本上是生产者-消费者模式。
基于示例GUITextScript.cs,libPD 只需要您订阅正确的委托。您无法控制何时执行这些,库有;因此,如果您一直遇到此问题,我猜应该向开发人员提交错误报告。