Compare commits

..

6 Commits

Author SHA1 Message Date
neuecc
887db5b281 2.0.24 2020-07-04 06:36:14 +09:00
neuecc
fee5518a82 Improve, Select/Where add UniTaskTracker 2020-07-04 06:29:50 +09:00
neuecc
551128e64c Add UniTaskAsyncEnumerable.Create 2020-07-04 06:29:33 +09:00
neuecc
c65ae8d18e error detail 2020-07-04 06:29:08 +09:00
neuecc
c1f75d9ebd Add UniTask.Never 2020-06-30 04:01:00 +09:00
neuecc
73a5ff6648 r 2020-06-29 03:24:10 +09:00
12 changed files with 580 additions and 104 deletions

View File

@@ -532,6 +532,38 @@ SelectAwaitWithCancellation(Func<T, CancellationToken, UniTask<TR>> selector)
If you want to use the `async` method inside the func, use the `***Await` or `***AwaitWithCancellation`.
How to create async iterator, C# 8.0 supports async iterator(`async yield return`) but it only allows `IAsyncEnumerable<T>` and of course requires C# 8.0. UniTask supports `UniTaskAsyncEnumerable.Create` method to create custom async iterator.
```csharp
// IAsyncEnumerable, C# 8.0 version of async iterator. ( do not use this style, IAsyncEnumerable is not controled in UniTask).
public async IAsyncEnumerable<int> MyEveryUpdate([EnumeratorCancellation]CancellationToken cancelationToken)
{
var frameCount = 0;
await UniTask.Yield();
while (!token.IsCancellationRequested)
{
yield return frameCount++;
await UniTask.Yield();
}
}
// UniTaskAsyncEnumerable.Create and use `await writer.YieldAsync` instead of `yield return`.
public IUniTaskAsyncEnumerable<int> MyEveryUpdate()
{
// writer(IAsyncWriter<T>) has `YieldAsync(value)` method.
return UniTaskAsyncEnumerable.Create<int>(async (writer, token) =>
{
var frameCount = 0;
await UniTask.Yield();
while (!token.IsCancellationRequested)
{
await writer.YieldAsync(frameCount++); // instead of `yield return`
await UniTask.Yield();
}
});
}
```
Awaitable Events
---
All uGUI component implements `***AsAsyncEnumerable` to convert asynchronous streams of events.
@@ -812,7 +844,7 @@ After Unity 2019.3.4f1, Unity 2020.1a21, that support path query parameter of gi
or add `"com.cysharp.unitask": "https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask"` to `Packages/manifest.json`.
If you want to set a target version, UniTask is using `*.*.*` release tag so you can specify a version like `#2.0.22`. For example `https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask#2.0.22`.
If you want to set a target version, UniTask is using `*.*.*` release tag so you can specify a version like `#2.0.24`. For example `https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask#2.0.24`.
### Install via OpenUPM

View File

@@ -295,71 +295,25 @@ namespace NetCoreSandbox
//await new ComparisonBenchmarks().ViaUniTaskT();
return;
#endif
// await new AllocationCheck().ViaUniTaskVoid();
var buttonTest = new AsyncReactiveProperty<AsyncUnit>(AsyncUnit.Default);
buttonTest
.Subscribe(async _ =>
var e = UniTaskAsyncEnumerable.Create<int>(async (writer, token) =>
{
try
for (int i = 0; i < 5; i++)
{
await new Foo().MethodFooAsync();
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace);
Console.WriteLine($"Start {i}");
await writer.YieldAsync(i);
Console.WriteLine($"End {i}");
}
});
buttonTest.Value = AsyncUnit.Default;
// AsyncTest().Forge
Console.WriteLine("A?");
var a = await new ZeroAllocAsyncAwaitInDotNetCore().NanikaAsync(1, 2);
Console.WriteLine("RET:" + a);
await WhereSelect();
SynchronizationContext.SetSynchronizationContext(new MySyncContext());
await Aaa();
//AsyncTest().Forget();
// AsyncTest().Forget();
ThreadPool.SetMinThreads(100, 100);
//List<UniTask<int>> list = new List<UniTask<int>>();
for (int i = 0; i < short.MaxValue; i++)
var ee = e.GetAsyncEnumerator();
while (await ee.MoveNextAsync())
{
//// list.Add(AsyncTest());
await YieldCore();
Console.WriteLine("ForEach " + ee.Current);
}
//await UniTask.WhenAll(list);
//Console.WriteLine("TOGO");
//var a = await AsyncTest();
//var b = AsyncTest();
//var c = AsyncTest();
await YieldCore();
//await b;
//await c;
//foreach (var item in Cysharp.Threading.Tasks.Internal.TaskPool.GetCacheSizeInfo())
//{
// Console.WriteLine(item);
//}
Console.ReadLine();
}
static async UniTask YieldCore()

View File

@@ -0,0 +1,170 @@
#pragma warning disable CS1998
#pragma warning disable CS0162
using Cysharp.Threading.Tasks;
using Cysharp.Threading.Tasks.Linq;
using FluentAssertions;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Xunit;
namespace NetCoreTests.Linq
{
public class CreateTest
{
[Fact]
public async Task SyncCreation()
{
var from = 10;
var count = 100;
var xs = await UniTaskAsyncEnumerable.Create<int>(async (writer, token) =>
{
for (int i = 0; i < count; i++)
{
await writer.YieldAsync(from + i);
}
}).ToArrayAsync();
var ys = await Range(from, count).AsUniTaskAsyncEnumerable().ToArrayAsync();
xs.Should().BeEquivalentTo(ys);
}
[Fact]
public async Task SyncManually()
{
var list = new List<int>();
var xs = UniTaskAsyncEnumerable.Create<int>(async (writer, token) =>
{
list.Add(100);
await writer.YieldAsync(10);
list.Add(200);
await writer.YieldAsync(20);
list.Add(300);
await writer.YieldAsync(30);
list.Add(400);
});
list.Should().BeEmpty();
var e = xs.GetAsyncEnumerator();
list.Should().BeEmpty();
await e.MoveNextAsync();
list.Should().BeEquivalentTo(100);
e.Current.Should().Be(10);
await e.MoveNextAsync();
list.Should().BeEquivalentTo(100, 200);
e.Current.Should().Be(20);
await e.MoveNextAsync();
list.Should().BeEquivalentTo(100, 200, 300);
e.Current.Should().Be(30);
(await e.MoveNextAsync()).Should().BeFalse();
list.Should().BeEquivalentTo(100, 200, 300, 400);
}
[Fact]
public async Task SyncExceptionFirst()
{
var from = 10;
var count = 100;
var xs = UniTaskAsyncEnumerable.Create<int>(async (writer, token) =>
{
for (int i = 0; i < count; i++)
{
throw new UniTaskTestException();
await writer.YieldAsync(from + i);
}
});
await Assert.ThrowsAsync<UniTaskTestException>(async () => await xs.ToArrayAsync());
}
[Fact]
public async Task SyncException()
{
var from = 10;
var count = 100;
var xs = UniTaskAsyncEnumerable.Create<int>(async (writer, token) =>
{
for (int i = 0; i < count; i++)
{
await writer.YieldAsync(from + i);
if (i == 15)
{
throw new UniTaskTestException();
}
}
});
await Assert.ThrowsAsync<UniTaskTestException>(async () => await xs.ToArrayAsync());
}
[Fact]
public async Task ASyncManually()
{
var list = new List<int>();
var xs = UniTaskAsyncEnumerable.Create<int>(async (writer, token) =>
{
await UniTask.Yield();
list.Add(100);
await writer.YieldAsync(10);
await UniTask.Yield();
list.Add(200);
await writer.YieldAsync(20);
await UniTask.Yield();
list.Add(300);
await UniTask.Yield();
await writer.YieldAsync(30);
await UniTask.Yield();
list.Add(400);
});
list.Should().BeEmpty();
var e = xs.GetAsyncEnumerator();
list.Should().BeEmpty();
await e.MoveNextAsync();
list.Should().BeEquivalentTo(100);
e.Current.Should().Be(10);
await e.MoveNextAsync();
list.Should().BeEquivalentTo(100, 200);
e.Current.Should().Be(20);
await e.MoveNextAsync();
list.Should().BeEquivalentTo(100, 200, 300);
e.Current.Should().Be(30);
(await e.MoveNextAsync()).Should().BeFalse();
list.Should().BeEquivalentTo(100, 200, 300, 400);
}
async IAsyncEnumerable<int> Range(int from, int count)
{
for (int i = 0; i < count; i++)
{
yield return from + i;
}
}
}
}

View File

@@ -0,0 +1,192 @@
using Cysharp.Threading.Tasks.Internal;
using System;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<T> Create<T>(Func<IAsyncWriter<T>, CancellationToken, UniTask> create)
{
Error.ThrowArgumentNullException(create, nameof(create));
return new Create<T>(create);
}
}
public interface IAsyncWriter<T>
{
UniTask YieldAsync(T value);
}
internal sealed class Create<T> : IUniTaskAsyncEnumerable<T>
{
readonly Func<IAsyncWriter<T>, CancellationToken, UniTask> create;
public Create(Func<IAsyncWriter<T>, CancellationToken, UniTask> create)
{
this.create = create;
}
public IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new _Create(create, cancellationToken);
}
sealed class _Create : MoveNextSource, IUniTaskAsyncEnumerator<T>
{
readonly Func<IAsyncWriter<T>, CancellationToken, UniTask> create;
readonly CancellationToken cancellationToken;
int state = -1;
AsyncWriter writer;
public _Create(Func<IAsyncWriter<T>, CancellationToken, UniTask> create, CancellationToken cancellationToken)
{
this.create = create;
this.cancellationToken = cancellationToken;
TaskTracker.TrackActiveTask(this, 3);
}
public T Current { get; private set; }
public UniTask DisposeAsync()
{
TaskTracker.RemoveTracking(this);
return default;
}
public UniTask<bool> MoveNextAsync()
{
if (state == -2) return default;
completionSource.Reset();
MoveNext();
return new UniTask<bool>(this, completionSource.Version);
}
void MoveNext()
{
try
{
switch (state)
{
case -1: // init
{
writer = new AsyncWriter(this);
RunWriterTask(create(writer, cancellationToken)).Forget();
if (Volatile.Read(ref state) == -2)
{
return; // complete synchronously
}
state = 0; // wait YieldAsync, it set TrySetResult(true)
return;
}
case 0:
writer.SignalWriter();
return;
default:
goto DONE;
}
}
catch (Exception ex)
{
state = -2;
completionSource.TrySetException(ex);
return;
}
DONE:
state = -2;
completionSource.TrySetResult(false);
return;
}
async UniTaskVoid RunWriterTask(UniTask task)
{
try
{
await task;
goto DONE;
}
catch (Exception ex)
{
Volatile.Write(ref state, -2);
completionSource.TrySetException(ex);
return;
}
DONE:
Volatile.Write(ref state, -2);
completionSource.TrySetResult(false);
}
public bool TrySetCanceled(CancellationToken cancellationToken)
{
state = -2;
return completionSource.TrySetCanceled(cancellationToken);
}
public bool TrySetComplete()
{
state = -2;
return completionSource.TrySetResult(false);
}
public bool TrySetException(Exception error)
{
state = -2;
return completionSource.TrySetException(error);
}
public void SetResult(T value)
{
Current = value;
completionSource.TrySetResult(true);
}
}
sealed class AsyncWriter : IUniTaskSource, IAsyncWriter<T>
{
readonly _Create enumerator;
UniTaskCompletionSourceCore<AsyncUnit> core;
public AsyncWriter(_Create enumerator)
{
this.enumerator = enumerator;
}
public void GetResult(short token)
{
core.GetResult(token);
}
public UniTaskStatus GetStatus(short token)
{
return core.GetStatus(token);
}
public UniTaskStatus UnsafeGetStatus()
{
return core.UnsafeGetStatus();
}
public void OnCompleted(Action<object> continuation, object state, short token)
{
core.OnCompleted(continuation, state, token);
}
public UniTask YieldAsync(T value)
{
core.Reset();
enumerator.SetResult(value);
return new UniTask(this, core.Version);
}
public void SignalWriter()
{
core.TrySetResult(AsyncUnit.Default);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0202f723469f93945afa063bfb440d15
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -88,6 +88,7 @@ namespace Cysharp.Threading.Tasks.Linq
this.selector = selector;
this.cancellationToken = cancellationToken;
this.moveNextAction = MoveNext;
TaskTracker.TrackActiveTask(this, 3);
}
public TResult Current { get; private set; }
@@ -156,6 +157,7 @@ namespace Cysharp.Threading.Tasks.Linq
public UniTask DisposeAsync()
{
TaskTracker.RemoveTracking(this);
return enumerator.DisposeAsync();
}
}
@@ -195,6 +197,7 @@ namespace Cysharp.Threading.Tasks.Linq
this.selector = selector;
this.cancellationToken = cancellationToken;
this.moveNextAction = MoveNext;
TaskTracker.TrackActiveTask(this, 3);
}
public TResult Current { get; private set; }
@@ -263,6 +266,7 @@ namespace Cysharp.Threading.Tasks.Linq
public UniTask DisposeAsync()
{
TaskTracker.RemoveTracking(this);
return enumerator.DisposeAsync();
}
}
@@ -302,6 +306,7 @@ namespace Cysharp.Threading.Tasks.Linq
this.selector = selector;
this.cancellationToken = cancellationToken;
this.moveNextAction = MoveNext;
TaskTracker.TrackActiveTask(this, 3);
}
public TResult Current { get; private set; }
@@ -382,6 +387,7 @@ namespace Cysharp.Threading.Tasks.Linq
public UniTask DisposeAsync()
{
TaskTracker.RemoveTracking(this);
return enumerator.DisposeAsync();
}
}
@@ -422,6 +428,7 @@ namespace Cysharp.Threading.Tasks.Linq
this.selector = selector;
this.cancellationToken = cancellationToken;
this.moveNextAction = MoveNext;
TaskTracker.TrackActiveTask(this, 3);
}
public TResult Current { get; private set; }
@@ -502,6 +509,7 @@ namespace Cysharp.Threading.Tasks.Linq
public UniTask DisposeAsync()
{
TaskTracker.RemoveTracking(this);
return enumerator.DisposeAsync();
}
}
@@ -541,6 +549,7 @@ namespace Cysharp.Threading.Tasks.Linq
this.selector = selector;
this.cancellationToken = cancellationToken;
this.moveNextAction = MoveNext;
TaskTracker.TrackActiveTask(this, 3);
}
public TResult Current { get; private set; }
@@ -621,6 +630,7 @@ namespace Cysharp.Threading.Tasks.Linq
public UniTask DisposeAsync()
{
TaskTracker.RemoveTracking(this);
return enumerator.DisposeAsync();
}
}
@@ -661,6 +671,7 @@ namespace Cysharp.Threading.Tasks.Linq
this.selector = selector;
this.cancellationToken = cancellationToken;
this.moveNextAction = MoveNext;
TaskTracker.TrackActiveTask(this, 3);
}
public TResult Current { get; private set; }
@@ -741,6 +752,7 @@ namespace Cysharp.Threading.Tasks.Linq
public UniTask DisposeAsync()
{
TaskTracker.RemoveTracking(this);
return enumerator.DisposeAsync();
}
}

View File

@@ -88,6 +88,7 @@ namespace Cysharp.Threading.Tasks.Linq
this.predicate = predicate;
this.cancellationToken = cancellationToken;
this.moveNextAction = MoveNext;
TaskTracker.TrackActiveTask(this, 3);
}
public TSource Current { get; private set; }
@@ -165,6 +166,7 @@ namespace Cysharp.Threading.Tasks.Linq
public UniTask DisposeAsync()
{
TaskTracker.RemoveTracking(this);
return enumerator.DisposeAsync();
}
}
@@ -204,6 +206,7 @@ namespace Cysharp.Threading.Tasks.Linq
this.predicate = predicate;
this.cancellationToken = cancellationToken;
this.moveNextAction = MoveNext;
TaskTracker.TrackActiveTask(this, 3);
}
public TSource Current { get; private set; }
@@ -281,6 +284,7 @@ namespace Cysharp.Threading.Tasks.Linq
public UniTask DisposeAsync()
{
TaskTracker.RemoveTracking(this);
return enumerator.DisposeAsync();
}
}
@@ -320,6 +324,7 @@ namespace Cysharp.Threading.Tasks.Linq
this.predicate = predicate;
this.cancellationToken = cancellationToken;
this.moveNextAction = MoveNext;
TaskTracker.TrackActiveTask(this, 3);
}
public TSource Current { get; private set; }
@@ -410,6 +415,7 @@ namespace Cysharp.Threading.Tasks.Linq
public UniTask DisposeAsync()
{
TaskTracker.RemoveTracking(this);
return enumerator.DisposeAsync();
}
}
@@ -450,6 +456,7 @@ namespace Cysharp.Threading.Tasks.Linq
this.predicate = predicate;
this.cancellationToken = cancellationToken;
this.moveNextAction = MoveNext;
TaskTracker.TrackActiveTask(this, 3);
}
public TSource Current { get; private set; }
@@ -540,6 +547,7 @@ namespace Cysharp.Threading.Tasks.Linq
public UniTask DisposeAsync()
{
TaskTracker.RemoveTracking(this);
return enumerator.DisposeAsync();
}
}
@@ -579,6 +587,7 @@ namespace Cysharp.Threading.Tasks.Linq
this.predicate = predicate;
this.cancellationToken = cancellationToken;
this.moveNextAction = MoveNext;
TaskTracker.TrackActiveTask(this, 3);
}
public TSource Current { get; private set; }
@@ -669,6 +678,7 @@ namespace Cysharp.Threading.Tasks.Linq
public UniTask DisposeAsync()
{
TaskTracker.RemoveTracking(this);
return enumerator.DisposeAsync();
}
}
@@ -709,6 +719,7 @@ namespace Cysharp.Threading.Tasks.Linq
this.predicate = predicate;
this.cancellationToken = cancellationToken;
this.moveNextAction = MoveNext;
TaskTracker.TrackActiveTask(this, 3);
}
public TSource Current { get; private set; }
@@ -799,6 +810,7 @@ namespace Cysharp.Threading.Tasks.Linq
public UniTask DisposeAsync()
{
TaskTracker.RemoveTracking(this);
return enumerator.DisposeAsync();
}
}

View File

@@ -175,6 +175,22 @@ namespace Cysharp.Threading.Tasks
return new UniTask<T>(new DeferPromise<T>(factory), 0);
}
/// <summary>
/// Never complete.
/// </summary>
public static UniTask Never(CancellationToken cancellationToken)
{
return new UniTask<AsyncUnit>(new NeverPromise<AsyncUnit>(cancellationToken), 0);
}
/// <summary>
/// Never complete.
/// </summary>
public static UniTask<T> Never<T>(CancellationToken cancellationToken)
{
return new UniTask<T>(new NeverPromise<T>(cancellationToken), 0);
}
sealed class ExceptionResultSource : IUniTaskSource
{
readonly ExceptionDispatchInfo exception;
@@ -384,6 +400,54 @@ namespace Cysharp.Threading.Tasks
return task.Status;
}
}
sealed class NeverPromise<T> : IUniTaskSource<T>
{
static readonly Action<object> cancellationCallback = CancellationCallback;
CancellationToken cancellationToken;
UniTaskCompletionSourceCore<T> core;
public NeverPromise(CancellationToken cancellationToken)
{
this.cancellationToken = cancellationToken;
if (this.cancellationToken.CanBeCanceled)
{
this.cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationCallback, this);
}
}
static void CancellationCallback(object state)
{
var self = (NeverPromise<T>)state;
self.core.TrySetCanceled(self.cancellationToken);
}
public T GetResult(short token)
{
return core.GetResult(token);
}
public UniTaskStatus GetStatus(short token)
{
return core.GetStatus(token);
}
public UniTaskStatus UnsafeGetStatus()
{
return core.UnsafeGetStatus();
}
public void OnCompleted(Action<object> continuation, object state, short token)
{
core.OnCompleted(continuation, state, token);
}
void IUniTaskSource.GetResult(short token)
{
core.GetResult(token);
}
}
}
internal static class CompletedTasks

View File

@@ -229,7 +229,7 @@ namespace Cysharp.Threading.Tasks
ValidateToken(token);
if (completedCount == 0)
{
throw new InvalidOperationException("not yet completed.");
throw new InvalidOperationException("Not yet completed, UniTask only allow to use await.");
}
if (error != null)
@@ -288,7 +288,7 @@ namespace Cysharp.Threading.Tasks
// It will cause call OnCompleted multiple time, invalid.
if (!ReferenceEquals(oldContinuation, UniTaskCompletionSourceCoreShared.s_sentinel))
{
throw new InvalidOperationException();
throw new InvalidOperationException("Already continuation registered, can not await twice or get Status after await.");
}
continuation(state);

View File

@@ -1,7 +1,7 @@
{
"name": "com.cysharp.unitask",
"displayName": "UniTask",
"version": "2.0.23",
"version": "2.0.24",
"unity": "2018.4",
"description": "Provides an efficient async/await integration to Unity.",
"keywords": [ "async/await", "async", "Task", "UniTask" ],

View File

@@ -1,46 +1,52 @@
using System;
using System.Threading.Tasks;
using Cysharp.Threading.Tasks;
using Cysharp.Threading.Tasks.Linq;
using Cysharp.Threading.Tasks;
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
/*UNniTastWhenAnyTester*/
[ExecuteInEditMode]
public class ExceptionExamples : MonoBehaviour
{
public Button ButtonTest;
public bool apply = false;
void Start()
private async UniTaskVoid Update()
{
ButtonTest.OnClickAsAsyncEnumerable()
.Subscribe(async _ =>
if (apply)
{
apply = false;
await LaunchTasksAndDetectWhenAnyDone(5);
}
}
private async UniTask LaunchTasksAndDetectWhenAnyDone(int nbTasks)
{
List<UniTask<int>> sleeptasks = new List<UniTask<int>>();
for (int i = 0; i < nbTasks; i++)
{
sleeptasks.Add(SleepAndReturnTrue(i).ToAsyncLazy().Task);
}
while (sleeptasks.Count > 0)
{
Debug.Log(DateTime.Now.ToString() + " waiting for " + sleeptasks.Count + " tasks...");
try
{
try
{
await new Foo().MethodFooAsync();
}
catch (Exception e)
{
Debug.Log(e.StackTrace);
}
}, this.GetCancellationTokenOnDestroy());
}
}
class Foo
{
public async UniTask MethodFooAsync()
{
await MethodBarAsync();
(int index, int taskID) = await UniTask.WhenAny(sleeptasks);
Debug.Log(DateTime.Now.ToString() + " Sleep task " + taskID + " done");
sleeptasks.RemoveAt(index);
}
catch
{
throw;
//Debug.Log("Error: " + e.Message);
//return;
}
}
}
private async UniTask MethodBarAsync()
private async UniTask<int> SleepAndReturnTrue(int taskIndex)
{
Throw();
}
private void Throw()
{
throw new Exception();
await UniTask.Delay(100);
return taskIndex;
}
}

View File

@@ -459,18 +459,41 @@ public class SandboxMain : MonoBehaviour
PrepareCamera();
}
public IUniTaskAsyncEnumerable<int> MyEveryUpdate()
{
return UniTaskAsyncEnumerable.Create<int>(async (writer, token) =>
{
var frameCount = 0;
await UniTask.Yield();
while (!token.IsCancellationRequested)
{
await writer.YieldAsync(frameCount++); // instead of `yield return`
await UniTask.Yield();
}
});
}
async UniTaskVoid Start()
{
var cts = new CancellationTokenSource();
okButton.onClick.AddListener(() =>
{
ShootAsync().Forget();
cts.Cancel();
});
// Nanika();
//// Nanika();
//await UniTask.Yield();
await MyEveryUpdate().Select(x => x).Where(x => x % 2 == 0).ForEachAsync(x =>
{
UnityEngine.Debug.Log(x + ":" + Time.frameCount);
}, cts.Token);
await UniTask.Yield();
// this.GetCancellationTokenOnDestroy()
//PlayerLoopInfo.Inject();
@@ -992,17 +1015,17 @@ public class SandboxMain : MonoBehaviour
void PrepareCamera()
{
Debug.Log("Support AsyncGPUReadback:" + SystemInfo.supportsAsyncGPUReadback);
//Debug.Log("Support AsyncGPUReadback:" + SystemInfo.supportsAsyncGPUReadback);
var width = 480;
var height = 240;
var depth = 24;
//var width = 480;
//var height = 240;
//var depth = 24;
mycamera.targetTexture = new RenderTexture(width, height, depth, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Default)
{
antiAliasing = 8
};
mycamera.enabled = true;
//mycamera.targetTexture = new RenderTexture(width, height, depth, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Default)
//{
// antiAliasing = 8
//};
//mycamera.enabled = true;
//myRenderTexture = new RenderTexture(width, height, depth, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Default)
//{