Add UniTask.WaitForFixedUpdate

master
neuecc 2020-06-08 02:22:10 +09:00
parent 79330d7cdb
commit 4d4466e801
3 changed files with 60 additions and 10 deletions

View File

@ -72,13 +72,14 @@ async UniTask<string> DemoAsync()
await UniTask.Yield(PlayerLoopTiming.PreLateUpdate); await UniTask.Yield(PlayerLoopTiming.PreLateUpdate);
// replacement of yield return null // replacement of yield return null
await UniTask.Yield();
await UniTask.NextFrame(); await UniTask.NextFrame();
// replacement of WaitForEndOfFrame(same as UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate)) // replacement of WaitForEndOfFrame(same as UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate))
await UniTask.WaitForEndOfFrame(); await UniTask.WaitForEndOfFrame();
// replacement of yield return new WaitForFixedUpdate // replacement of yield return new WaitForFixedUpdate(same as UniTask.Yield(PlayerLoopTiming.FixedUpdate))
await UniTask.Yield(PlayerLoopTiming.FixedUpdate); await UniTask.WaitForFixedUpdate();
// replacement of yield return WaitUntil // replacement of yield return WaitUntil
await UniTask.WaitUntil(() => isActive == false); await UniTask.WaitUntil(() => isActive == false);
@ -92,9 +93,14 @@ async UniTask<string> DemoAsync()
// You can await standard task // You can await standard task
await Task.Run(() => 100); await Task.Run(() => 100);
// Multithreading, run on ThreadPool under this code(use SwitchToMainThread, same as `ObserveOnMainThreadDispatcher`) // Multithreading, run on ThreadPool under this code
await UniTask.SwitchToThreadPool(); await UniTask.SwitchToThreadPool();
/* work on ThreadPool */
// return to MainThread(same as `ObserveOnMainThread` in UniRx)
await UniTask.SwitchToMainThread();
// get async webrequest // get async webrequest
async UniTask<string> GetTextAsync(UnityWebRequest req) async UniTask<string> GetTextAsync(UnityWebRequest req)
{ {
@ -334,12 +340,12 @@ public enum PlayerLoopTiming
It indicates when to run, you can check [PlayerLoopList.md](https://gist.github.com/neuecc/bc3a1cfd4d74501ad057e49efcd7bdae) to Unity's default playerloop and injected UniTask's custom loop. It indicates when to run, you can check [PlayerLoopList.md](https://gist.github.com/neuecc/bc3a1cfd4d74501ad057e49efcd7bdae) to Unity's default playerloop and injected UniTask's custom loop.
`PlayerLoopTiming.Update` is similar as `yield return null` in coroutine, but it is called before Update(Update and uGUI events(button.onClick, etc...) are called on `ScriptRunBehaviourUpdate`, yield return null is called on `ScriptRunDelayedDynamicFrameRate`). `PlayerLoopTiming.Update` is similar as `yield return null` in coroutine, but it is called before Update(Update and uGUI events(button.onClick, etc...) are called on `ScriptRunBehaviourUpdate`, yield return null is called on `ScriptRunDelayedDynamicFrameRate`). `PlayerLoopTiming.FixedUpdate` is similar as `WaitForFixedUpdate`, `PlayerLoopTiming.LastPostLateUpdate` is similar as `WaitForEndOfFrame` in coroutine.
`PlayerLoopTiming.FixedUpdate` is similar as `WaitForFixedUpdate`, `PlayerLoopTiming.LastPostLateUpdate` is similar as `WaitForEndOfFrame` in coroutine.
`yield return null` and `UniTask.Yield` is similar but different. `yield return null` always return next frame but `UniTask.Yield` return next called, that is, call `UniTask.Yield(PlayerLoopTiming.Update)` on `PreUpdate`, it returns same frame. `UniTask.NextFrame()` gurantees return next frame, this would be expected to behave exactly the same as `yield return null`. `yield return null` and `UniTask.Yield` is similar but different. `yield return null` always return next frame but `UniTask.Yield` return next called, that is, call `UniTask.Yield(PlayerLoopTiming.Update)` on `PreUpdate`, it returns same frame. `UniTask.NextFrame()` gurantees return next frame, this would be expected to behave exactly the same as `yield return null`.
> UniTask.Yield(without CancellationToken) is a special type, returns `YieldAwaitable` and run on YieldRunner. It is most lightweight and faster.
AsyncOperation is returned from native timing. For example, await `SceneManager.LoadSceneAsync` is returned from `EarlyUpdate.UpdatePreloading` and after called, loaded scene called from `EarlyUpdate.ScriptRunDelayedStartupFrame`. Also `await UnityWebRequest` is returned from `EarlyUpdate.ExecuteMainThreadJobs`. AsyncOperation is returned from native timing. For example, await `SceneManager.LoadSceneAsync` is returned from `EarlyUpdate.UpdatePreloading` and after called, loaded scene called from `EarlyUpdate.ScriptRunDelayedStartupFrame`. Also `await UnityWebRequest` is returned from `EarlyUpdate.ExecuteMainThreadJobs`.
In UniTask, await directly and `WithCancellation` use native timing, `ToUniTask` use specified timing. This is usually not a particular problem, but with `LoadSceneAsync`, causes different order of Start and continuation after await. so recommend not to use `LoadSceneAsync.ToUniTask`. In UniTask, await directly and `WithCancellation` use native timing, `ToUniTask` use specified timing. This is usually not a particular problem, but with `LoadSceneAsync`, causes different order of Start and continuation after await. so recommend not to use `LoadSceneAsync.ToUniTask`.

View File

@ -44,6 +44,22 @@ namespace Cysharp.Threading.Tasks
return UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate, cancellationToken); return UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate, cancellationToken);
} }
/// <summary>
/// Same as UniTask.Yield(PlayerLoopTiming.FixedUpdate).
/// </summary>
public static YieldAwaitable WaitForFixedUpdate()
{
return UniTask.Yield(PlayerLoopTiming.FixedUpdate);
}
/// <summary>
/// Same as UniTask.Yield(PlayerLoopTiming.FixedUpdate, cancellationToken).
/// </summary>
public static UniTask WaitForFixedUpdate(CancellationToken cancellationToken)
{
return UniTask.Yield(PlayerLoopTiming.FixedUpdate, cancellationToken);
}
public static UniTask DelayFrame(int delayFrameCount, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken)) public static UniTask DelayFrame(int delayFrameCount, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
{ {
if (delayFrameCount < 0) if (delayFrameCount < 0)

View File

@ -267,11 +267,11 @@ public class SandboxMain : MonoBehaviour
//cts.Cancel(); //cts.Cancel();
//await r; //await r;
Debug.Log("SendWebRequestDone:" + PlayerLoopInfo.CurrentLoopType); Debug.Log("SendWebRequestDone:" + PlayerLoopInfo.CurrentLoopType);
// var foo = await UnityWebRequest.Get("https://bing.com/").SendWebRequest();
// foo.downloadHandler.text; // var foo = await UnityWebRequest.Get("https://bing.com/").SendWebRequest();
// // foo.downloadHandler.text;
//
_ = await UnityWebRequest.Get("https://bing.com/").SendWebRequest().WithCancellation(CancellationToken.None); _ = await UnityWebRequest.Get("https://bing.com/").SendWebRequest().WithCancellation(CancellationToken.None);
Debug.Log("SendWebRequestWithCancellationDone:" + PlayerLoopInfo.CurrentLoopType); Debug.Log("SendWebRequestWithCancellationDone:" + PlayerLoopInfo.CurrentLoopType);
} }
@ -358,11 +358,39 @@ public class SandboxMain : MonoBehaviour
StartCoroutine(CoroutineRun()); StartCoroutine(CoroutineRun());
} }
async UniTaskVoid AsyncFixedUpdate()
{
while (true)
{
await UniTask.WaitForFixedUpdate();
Debug.Log("Async:" + Time.frameCount + ", " + PlayerLoopInfo.CurrentLoopType);
}
}
IEnumerator CoroutineFixedUpdate()
{
while (true)
{
yield return new WaitForFixedUpdate();
Debug.Log("Coroutine:" + Time.frameCount + ", " + PlayerLoopInfo.CurrentLoopType);
}
}
private void FixedUpdate()
{
Debug.Log("FixedUpdate:" + Time.frameCount + ", " + PlayerLoopInfo.CurrentLoopType);
}
void Start() void Start()
{ {
PlayerLoopInfo.Inject(); PlayerLoopInfo.Inject();
_ = AsyncFixedUpdate();
StartCoroutine(CoroutineFixedUpdate());
okButton.onClick.AddListener(UniTask.UnityAction(async () => okButton.onClick.AddListener(UniTask.UnityAction(async () =>
{ {
/* /*