以前 UnityTestRunnerでUniTaskを使おう! にて、 UniTask.WaitForEndOfFrame
は正常に動かない旨を書きましたが、 UniTask 2.3.1
(https://github.com/Cysharp/UniTask/releases/tag/2.3.1) にて、MonoBehaviour を引数に渡すことにより正常に動くようになり、引数無しのものは Obsolete になりました。
UniTask 2.4.0
(https://github.com/Cysharp/UniTask/releases/tag/2.4.0) にて、内部でAwaitable.EndOfFrameAsync
を使った引数無しバージョンが復活しました。Awaitableが使える Unity2023.1以上 であれば引数無しを使えます!
内部では渡した MonoBehaviour を使ってコルーチンが走っていますが、 yield return
を使わない実装によりアロケーションはしないようになっています。
以前のPlayModeのテストコードをほぼそのまま使ってみましょう。
/// <summary>
/// 例えばスクリーンショットを撮るテスト(UniTask)
/// </summary>
[UnityTest]
public IEnumerator WaitForEndOfFrameUniTaskTest() => UniTask.ToCoroutine(async () =>
{
new GameObject("camera").AddComponent<Camera>();
// 適当なMonoBehaviourをコルーチン用に生成する
var runner = new GameObject("Runner").AddComponent<CoroutineRunner>();
// EndOfFrameまで待てる!!!!!!!!!
await UniTask.WaitForEndOfFrame(runner);
// UniTask2.4.0以上でUnity2023.1以降ならこっち
// await UniTask.WaitForEndOfFrame();
var tex = new Texture2D(Screen.width, Screen.height);
// // EndOfFrameでしか動かない
tex.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0);
tex.Apply();
var sprite = Sprite.Create(
tex,
new Rect(0, 0, tex.width, tex.height),
new Vector2(0.5f, 0.5f)
);
var renderer = new GameObject("sprite").AddComponent<SpriteRenderer>();
renderer.sprite = sprite;
await UniTask.Delay(5000);
});
今回はテストコードということでコルーチンを走らせる用に適当な MonoBehaviour を生成して引数に渡しています。
public class CoroutineRunner : MonoBehaviour
{}
// 適当なMonoBehaviourをコルーチン用に生成する
var runner = new GameObject("Runner").AddComponent<CoroutineRunner>();
// EndOfFrameまで待てる!!!!!!!!!
await UniTask.WaitForEndOfFrame(runner);
// UniTask2.4.0以上でUnity2023.1以降ならこっち
// await UniTask.WaitForEndOfFrame();
正常に動いています。きれいなサンセットが撮れました。