mirror of
https://github.com/Cysharp/UniTask.git
synced 2026-05-26 01:40:17 +00:00
Compare commits
7 Commits
861fc6f21b
...
5157d78be8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5157d78be8 | ||
|
|
98538ef7c7 | ||
|
|
519590ca6e | ||
|
|
dce4366f3e | ||
|
|
88026ab14a | ||
|
|
95998ff3f2 | ||
|
|
9c4bab6e0a |
13
.config/dotnet-tools.json
Normal file
13
.config/dotnet-tools.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"version": 1,
|
||||
"isRoot": true,
|
||||
"tools": {
|
||||
"docfx": {
|
||||
"version": "2.78.3",
|
||||
"commands": [
|
||||
"docfx"
|
||||
],
|
||||
"rollForward": false
|
||||
}
|
||||
}
|
||||
}
|
||||
4
.github/dependabot.yaml
vendored
4
.github/dependabot.yaml
vendored
@@ -5,8 +5,10 @@ updates:
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly" # Check for updates to GitHub Actions every week
|
||||
cooldown:
|
||||
default-days: 14 # Wait 14 days before creating another PR for the same dependency. This will prevent vulnerability on the package impact.
|
||||
ignore:
|
||||
# I just want update action when major/minor version is updated. patch updates are too noisy.
|
||||
- dependency-name: '*'
|
||||
- dependency-name: "*"
|
||||
update-types:
|
||||
- version-update:semver-patch
|
||||
|
||||
40
.github/workflows/build-docs.yaml
vendored
40
.github/workflows/build-docs.yaml
vendored
@@ -8,25 +8,49 @@ on:
|
||||
|
||||
jobs:
|
||||
run-docfx:
|
||||
if: ${{ ((github.event_name == 'push' && github.repository_owner == 'Cysharp') || startsWith(github.event.pull_request.head.label, 'Cysharp:')) && github.triggering_actor != 'dependabot[bot]' }}
|
||||
permissions:
|
||||
contents: write
|
||||
pages: write
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- name: Load secrets
|
||||
id: op-load-secret
|
||||
uses: 1password/load-secrets-action@581a835fb51b8e7ec56b71cf2ffddd7e68bb25e0 # v2.0.0
|
||||
with:
|
||||
export-env: false
|
||||
env:
|
||||
OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN_PUBLIC }}
|
||||
UNITY_EMAIL: "op://${{ vars.OP_VAULT_ACTIONS_PUBLIC }}/UNITY_LICENSE/username"
|
||||
UNITY_PASSWORD: "op://${{ vars.OP_VAULT_ACTIONS_PUBLIC }}/UNITY_LICENSE/credential"
|
||||
UNITY_SERIAL: "op://${{ vars.OP_VAULT_ACTIONS_PUBLIC }}/UNITY_LICENSE/serial"
|
||||
- uses: Cysharp/Actions/.github/actions/checkout@main
|
||||
# Execute scripts: Export Package
|
||||
# /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -projectPath . -executeMethod PackageExporter.Export
|
||||
- name: Build Unity (.unitypackage)
|
||||
uses: Cysharp/Actions/.github/actions/unity-builder@main
|
||||
env:
|
||||
UNITY_EMAIL: ${{ steps.op-load-secret.outputs.UNITY_EMAIL }}
|
||||
UNITY_PASSWORD: ${{ steps.op-load-secret.outputs.UNITY_PASSWORD }}
|
||||
UNITY_SERIAL: ${{ steps.op-load-secret.outputs.UNITY_SERIAL }}
|
||||
with:
|
||||
projectPath: src/UniTask
|
||||
unityVersion: "2022.3.39f1"
|
||||
targetPlatform: StandaloneLinux64
|
||||
buildMethod: PackageExporter.Export
|
||||
|
||||
- uses: Cysharp/Actions/.github/actions/checkout@main
|
||||
with:
|
||||
repository: Cysharp/DocfxTemplate
|
||||
path: docs/_DocfxTemplate
|
||||
- uses: Kirbyrawr/docfx-action@db9a22c8fe1e8693a2a21be54cb0b87dfaa72cc4
|
||||
name: Docfx metadata
|
||||
with:
|
||||
args: metadata docs/docfx.json
|
||||
- uses: Kirbyrawr/docfx-action@db9a22c8fe1e8693a2a21be54cb0b87dfaa72cc4
|
||||
name: Docfx build
|
||||
with:
|
||||
args: build docs/docfx.json
|
||||
- uses: Cysharp/Actions/.github/actions/setup-dotnet@main
|
||||
- name: dotnet tool restore
|
||||
run: dotnet tool restore
|
||||
- name: Docfx metadata
|
||||
run: dotnet docfx metadata docs/docfx.json
|
||||
- name: Docfx build
|
||||
run: dotnet docfx build docs/docfx.json
|
||||
- name: Publish to GitHub Pages
|
||||
uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0
|
||||
with:
|
||||
|
||||
@@ -4,7 +4,11 @@
|
||||
"src": [
|
||||
{
|
||||
"files": [
|
||||
"UniTask/Assets/Plugins/UniTask/Runtime/**/*.cs"
|
||||
"UniTask/Library/ScriptAssemblies/UniTask*.dll"
|
||||
],
|
||||
"exclude": [
|
||||
"UniTask/Library/ScriptAssemblies/UniTask.Tests.dll",
|
||||
"UniTask/Library/ScriptAssemblies/UniTask.Tests.Editor.dll"
|
||||
],
|
||||
"src": "../src"
|
||||
}
|
||||
@@ -54,7 +58,6 @@
|
||||
}
|
||||
],
|
||||
"dest": "_site",
|
||||
|
||||
"globalMetadataFiles": [],
|
||||
"fileMetadataFiles": [],
|
||||
"template": [
|
||||
@@ -67,4 +70,4 @@
|
||||
"keepFileLink": false,
|
||||
"cleanupCacheHistory": false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,6 +118,9 @@ namespace Cysharp.Threading.Tasks.Internal
|
||||
case PlayerLoopTiming.LastPostLateUpdate:
|
||||
LastPostLateUpdate();
|
||||
break;
|
||||
case PlayerLoopTiming.ManualUpdate:
|
||||
ManualUpdate();
|
||||
break;
|
||||
#if UNITY_2020_2_OR_NEWER
|
||||
case PlayerLoopTiming.TimeUpdate:
|
||||
TimeUpdate();
|
||||
@@ -148,6 +151,7 @@ namespace Cysharp.Threading.Tasks.Internal
|
||||
void LastPreLateUpdate() => RunCore();
|
||||
void PostLateUpdate() => RunCore();
|
||||
void LastPostLateUpdate() => RunCore();
|
||||
void ManualUpdate() => RunCore();
|
||||
#if UNITY_2020_2_OR_NEWER
|
||||
void TimeUpdate() => RunCore();
|
||||
void LastTimeUpdate() => RunCore();
|
||||
@@ -178,7 +182,7 @@ namespace Cysharp.Threading.Tasks.Internal
|
||||
}
|
||||
else
|
||||
{
|
||||
continue; // next i
|
||||
continue; // next i
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -96,6 +96,7 @@ namespace Cysharp.Threading.Tasks
|
||||
TimeUpdate = 14,
|
||||
LastTimeUpdate = 15,
|
||||
#endif
|
||||
ManualUpdate = 16,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
@@ -192,6 +193,7 @@ namespace Cysharp.Threading.Tasks
|
||||
static SynchronizationContext unitySynchronizationContext;
|
||||
static ContinuationQueue[] yielders;
|
||||
static PlayerLoopRunner[] runners;
|
||||
static PlayerLoopRunner ManualRunner;
|
||||
internal static bool IsEditorApplicationQuitting { get; private set; }
|
||||
static PlayerLoopSystem[] InsertRunner(PlayerLoopSystem loopSystem,
|
||||
bool injectOnFirst,
|
||||
@@ -251,6 +253,10 @@ namespace Cysharp.Threading.Tasks
|
||||
|
||||
return dest;
|
||||
}
|
||||
public static void ManualUpdate()
|
||||
{
|
||||
ManualRunner.Run();
|
||||
}
|
||||
|
||||
static PlayerLoopSystem[] RemoveRunner(PlayerLoopSystem loopSystem, Type loopRunnerYieldType, Type loopRunnerType)
|
||||
{
|
||||
@@ -302,7 +308,7 @@ namespace Cysharp.Threading.Tasks
|
||||
catch { }
|
||||
|
||||
#if UNITY_EDITOR && UNITY_2019_3_OR_NEWER
|
||||
// When domain reload is disabled, re-initialization is required when entering play mode;
|
||||
// When domain reload is disabled, re-initialization is required when entering play mode;
|
||||
// otherwise, pending tasks will leak between play mode sessions.
|
||||
var domainReloadDisabled = UnityEditor.EditorSettings.enterPlayModeOptionsEnabled &&
|
||||
UnityEditor.EditorSettings.enterPlayModeOptions.HasFlag(UnityEditor.EnterPlayModeOptions.DisableDomainReload);
|
||||
@@ -405,6 +411,8 @@ namespace Cysharp.Threading.Tasks
|
||||
runners = new PlayerLoopRunner[14];
|
||||
#endif
|
||||
|
||||
ManualRunner = new PlayerLoopRunner(PlayerLoopTiming.ManualUpdate);
|
||||
|
||||
var copyList = playerLoop.subSystemList.ToArray();
|
||||
|
||||
// Initialization
|
||||
@@ -491,6 +499,11 @@ namespace Cysharp.Threading.Tasks
|
||||
|
||||
public static void AddAction(PlayerLoopTiming timing, IPlayerLoopItem action)
|
||||
{
|
||||
if ((int)timing == (int)PlayerLoopTiming.ManualUpdate)
|
||||
{
|
||||
ManualRunner.AddAction(action);
|
||||
return;
|
||||
}
|
||||
var runner = runners[(int)timing];
|
||||
if (runner == null)
|
||||
{
|
||||
@@ -528,8 +541,8 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
sb.AppendFormat("------{0}------", header.type.Name);
|
||||
sb.AppendLine();
|
||||
|
||||
if (header.subSystemList is null)
|
||||
|
||||
if (header.subSystemList is null)
|
||||
{
|
||||
sb.AppendFormat("{0} has no subsystems!", header.ToString());
|
||||
sb.AppendLine();
|
||||
@@ -557,11 +570,11 @@ namespace Cysharp.Threading.Tasks
|
||||
|
||||
foreach (var header in playerLoop.subSystemList)
|
||||
{
|
||||
if (header.subSystemList is null)
|
||||
{
|
||||
if (header.subSystemList is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
foreach (var subSystem in header.subSystemList)
|
||||
{
|
||||
if (subSystem.type == typeof(UniTaskLoopRunners.UniTaskLoopRunnerInitialization))
|
||||
|
||||
@@ -16,11 +16,14 @@ namespace Cysharp.Threading.Tasks
|
||||
/// <summary>Ignore timescale, use Time.unscaledDeltaTime.</summary>
|
||||
UnscaledDeltaTime,
|
||||
/// <summary>use Stopwatch.GetTimestamp().</summary>
|
||||
Realtime
|
||||
Realtime,
|
||||
ManualTime
|
||||
}
|
||||
|
||||
public partial struct UniTask
|
||||
{
|
||||
public static float deltaTime;
|
||||
public static int frameCount;
|
||||
public static YieldAwaitable Yield()
|
||||
{
|
||||
// optimized for single continuation
|
||||
@@ -80,7 +83,7 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
await Awaitable.EndOfFrameAsync(cancellationToken);
|
||||
}
|
||||
#else
|
||||
#else
|
||||
[Obsolete("Use WaitForEndOfFrame(MonoBehaviour) instead or UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate). Equivalent for coroutine's WaitForEndOfFrame requires MonoBehaviour(runner of Coroutine).")]
|
||||
public static YieldAwaitable WaitForEndOfFrame()
|
||||
{
|
||||
@@ -92,7 +95,7 @@ namespace Cysharp.Threading.Tasks
|
||||
{
|
||||
return UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate, cancellationToken, cancelImmediately);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
public static UniTask WaitForEndOfFrame(MonoBehaviour coroutineRunner)
|
||||
{
|
||||
@@ -179,6 +182,10 @@ namespace Cysharp.Threading.Tasks
|
||||
|
||||
switch (delayType)
|
||||
{
|
||||
case DelayType.ManualTime:
|
||||
{
|
||||
return new UniTask(DelayManualPromise.Create(delayTimeSpan, delayTiming, cancellationToken, cancelImmediately, out var token), token);
|
||||
}
|
||||
case DelayType.UnscaledDeltaTime:
|
||||
{
|
||||
return new UniTask(DelayIgnoreTimeScalePromise.Create(delayTimeSpan, delayTiming, cancellationToken, cancelImmediately, out var token), token);
|
||||
@@ -229,7 +236,7 @@ namespace Cysharp.Threading.Tasks
|
||||
|
||||
result.cancellationToken = cancellationToken;
|
||||
result.cancelImmediately = cancelImmediately;
|
||||
|
||||
|
||||
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||
{
|
||||
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||
@@ -320,6 +327,7 @@ namespace Cysharp.Threading.Tasks
|
||||
CancellationToken cancellationToken;
|
||||
CancellationTokenRegistration cancellationTokenRegistration;
|
||||
bool cancelImmediately;
|
||||
PlayerLoopTiming timing = PlayerLoopTiming.Update;
|
||||
|
||||
NextFramePromise()
|
||||
{
|
||||
@@ -337,8 +345,9 @@ namespace Cysharp.Threading.Tasks
|
||||
result = new NextFramePromise();
|
||||
}
|
||||
|
||||
result.frameCount = PlayerLoopHelper.IsMainThread ? Time.frameCount : -1;
|
||||
result.frameCount = PlayerLoopHelper.IsMainThread ?(timing == PlayerLoopTiming.ManualUpdate ? UniTask.frameCount : Time.frameCount) : -1;
|
||||
result.cancellationToken = cancellationToken;
|
||||
result.timing = timing;
|
||||
result.cancelImmediately = cancelImmediately;
|
||||
|
||||
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||
@@ -400,7 +409,7 @@ namespace Cysharp.Threading.Tasks
|
||||
return false;
|
||||
}
|
||||
|
||||
if (frameCount == Time.frameCount)
|
||||
if (frameCount == (timing == PlayerLoopTiming.ManualUpdate ? UniTask.frameCount : Time.frameCount))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -695,6 +704,138 @@ namespace Cysharp.Threading.Tasks
|
||||
}
|
||||
}
|
||||
|
||||
sealed class DelayManualPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<DelayManualPromise>
|
||||
{
|
||||
static TaskPool<DelayManualPromise> pool;
|
||||
DelayManualPromise nextNode;
|
||||
public ref DelayManualPromise NextNode => ref nextNode;
|
||||
|
||||
static DelayManualPromise()
|
||||
{
|
||||
TaskPool.RegisterSizeGetter(typeof(DelayManualPromise), () => pool.Size);
|
||||
}
|
||||
|
||||
int initialFrame;
|
||||
float delayTimeSpan;
|
||||
float elapsed;
|
||||
CancellationToken cancellationToken;
|
||||
CancellationTokenRegistration cancellationTokenRegistration;
|
||||
bool cancelImmediately;
|
||||
|
||||
UniTaskCompletionSourceCore<object> core;
|
||||
|
||||
DelayManualPromise()
|
||||
{
|
||||
}
|
||||
|
||||
public static IUniTaskSource Create(TimeSpan delayTimeSpan, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token);
|
||||
}
|
||||
|
||||
if (!pool.TryPop(out var result))
|
||||
{
|
||||
result = new DelayManualPromise();
|
||||
}
|
||||
|
||||
result.elapsed = 0.0f;
|
||||
result.delayTimeSpan = (float)delayTimeSpan.TotalSeconds;
|
||||
result.cancellationToken = cancellationToken;
|
||||
result.initialFrame = PlayerLoopHelper.IsMainThread ? frameCount : -1;
|
||||
result.cancelImmediately = cancelImmediately;
|
||||
|
||||
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||
{
|
||||
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||
{
|
||||
var promise = (DelayManualPromise)state;
|
||||
promise.core.TrySetCanceled(promise.cancellationToken);
|
||||
}, result);
|
||||
}
|
||||
|
||||
TaskTracker.TrackActiveTask(result, 3);
|
||||
|
||||
PlayerLoopHelper.AddAction(timing, result);
|
||||
|
||||
token = result.core.Version;
|
||||
return result;
|
||||
}
|
||||
|
||||
public void GetResult(short token)
|
||||
{
|
||||
try
|
||||
{
|
||||
core.GetResult(token);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
||||
{
|
||||
TryReturn();
|
||||
}
|
||||
else
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 bool MoveNext()
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
core.TrySetCanceled(cancellationToken);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (elapsed == 0.0f)
|
||||
{
|
||||
if (initialFrame == Time.frameCount)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
elapsed += Time.deltaTime;
|
||||
if (elapsed >= delayTimeSpan)
|
||||
{
|
||||
core.TrySetResult(null);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TryReturn()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
core.Reset();
|
||||
delayTimeSpan = default;
|
||||
elapsed = default;
|
||||
cancellationToken = default;
|
||||
cancellationTokenRegistration.Dispose();
|
||||
cancelImmediately = default;
|
||||
return pool.TryPush(this);
|
||||
}
|
||||
}
|
||||
|
||||
sealed class DelayPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<DelayPromise>
|
||||
{
|
||||
static TaskPool<DelayPromise> pool;
|
||||
|
||||
Reference in New Issue
Block a user