Unity3D中的帧率独立事件

时间:2017-08-27 07:47:18

标签: events unity3d delegates puredata libpd

我使用libpd4unity包与Pure Data进行通信。我收到了来自Pure Data的LibPD.Bang爆炸声。在爆炸事件中,我通过FMOD播放声音。

问题是,我经常收到爆炸,例如每500毫秒一次,但事件不会在特定的帧长度内触发。通常长度改变1帧或更少。

这个问题有解决方案吗?例如,帧速率独立事件?我想知道Unity3D中的事件(委托)是否与帧率无关。

因为有播放每个声音的速度,只有1帧废墟节奏。

我需要通过每个单独的爆炸来同步声音。

1 个答案:

答案 0 :(得分:2)

关于代表是否依赖Unity或独立于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只要求您订阅正确的代理。您无法控制何时执行这些库,库具有;所以如果你继续遇到这个问题,我觉得值得向开发人员提交错误报告。