mirror of https://github.com/Cysharp/UniTask
Compare commits
227 Commits
Author | SHA1 | Date |
---|---|---|
|
06067cd4c8 | |
|
d9983cfe27 | |
|
70eb7cd3ee | |
|
cc3c70af90 | |
|
8042b29ff8 | |
|
b0d01ca75f | |
|
7a63ab7088 | |
|
bdf102f145 | |
|
41cea030ab | |
|
f9fd769be7 | |
|
579304fe47 | |
|
740ca7ef01 | |
|
7c0f199fe0 | |
|
9a3ec31533 | |
|
37d8f4f48e | |
|
27a0c06ede | |
|
e4082ecd75 | |
|
3b0fd784ff | |
|
dc9ebfd765 | |
|
005c83fbd7 | |
|
5984b67ecb | |
|
05fdf48058 | |
|
647ed6ff82 | |
|
0826b7e976 | |
|
a51632cd4b | |
|
bf945a7ef4 | |
|
353f15e94f | |
|
cf19f18662 | |
|
fdb9d1cf95 | |
|
2e0917428b | |
|
0b16005f4b | |
|
74bbe87b58 | |
|
6f4131539b | |
|
06283f0ffb | |
|
dfe5ee43c2 | |
|
eaa553dc83 | |
|
83d8a2b424 | |
|
4d204e4aa6 | |
|
87e164e275 | |
|
b63eb8d090 | |
|
75119acb50 | |
|
f7b3c2fbe1 | |
|
b317ecfa01 | |
|
7b05569ef7 | |
|
e0465c6c2c | |
|
9057452c86 | |
|
a2f6f84bde | |
|
f057abff0f | |
|
c61a7d9961 | |
|
9587f2eeec | |
|
550784f31c | |
|
11b3282b3d | |
|
b2532b0798 | |
|
4fc41ecb17 | |
|
e52663cef6 | |
|
1827be2de7 | |
|
8560561ef3 | |
|
2019f1fa7f | |
|
9e2265d148 | |
|
9d02279822 | |
|
17ce06d93c | |
|
7b810413fe | |
|
d78c0d6c02 | |
|
d248acc7d1 | |
|
4c0b1f753a | |
|
7bb6feda55 | |
|
f8a501290a | |
|
cb497c9eb5 | |
|
342a37a074 | |
|
c3146ec74f | |
|
df16813fae | |
|
8d98bbc7ba | |
|
bb095697f7 | |
|
cdf88c6a6a | |
|
4eee2c9270 | |
|
222b1401f5 | |
|
fbe0bf8515 | |
|
626685292c | |
|
67794f5cdd | |
|
2e225fb841 | |
|
935523f25c | |
|
3b3f7ebd3e | |
|
88ecfa2992 | |
|
aa70fe5c5a | |
|
0c8057c668 | |
|
28867646b0 | |
|
ca60864021 | |
|
1e4561da22 | |
|
1496cc990a | |
|
7bb3bf8d0e | |
|
d057074f17 | |
|
b724a2aa84 | |
|
938ddd5356 | |
|
911c37d4d8 | |
|
caccccb0b5 | |
|
a48f11d31b | |
|
fcd93feb56 | |
|
b472b23773 | |
|
01c8fada1f | |
|
10cd137126 | |
|
809d23edae | |
|
d38731bc44 | |
|
64792b672d | |
|
3892cc2299 | |
|
5bfccaa3b6 | |
|
b49b7332bb | |
|
08184af737 | |
|
0ef6c59385 | |
|
4b0bd3b509 | |
|
9a4720d180 | |
|
b99646558c | |
|
ee12dd9ae7 | |
|
006e0f2c81 | |
|
7d31299b5c | |
|
fe8bf834e6 | |
|
5843258e8c | |
|
6cd002645e | |
|
4fe0861714 | |
|
fbbba061dd | |
|
81f2e37ea5 | |
|
66de0d3a58 | |
|
beb10abbf7 | |
|
d60f64761b | |
|
36ac0863ad | |
|
104f8e09ca | |
|
cfbff008c4 | |
|
5cc97c7f00 | |
|
5666292496 | |
|
1288cbc128 | |
|
5f3aa18f38 | |
|
0970ae8c31 | |
|
ad23f7fb29 | |
|
a4be8f316e | |
|
370425578f | |
|
1b76f77608 | |
|
0579984355 | |
|
39cf81d2ab | |
|
0a203c8db9 | |
|
55be4dba82 | |
|
f0adf36633 | |
|
24afc4f3eb | |
|
2cf06af433 | |
|
94be2e748b | |
|
7f582e5e29 | |
|
3f042c8886 | |
|
6f5d818544 | |
|
2ccb37cb02 | |
|
cfe509a556 | |
|
a46a4cac01 | |
|
3ed28e534a | |
|
be8dbe8804 | |
|
64f7eec4e9 | |
|
3a93f4a49f | |
|
71958adc3d | |
|
acc71550c9 | |
|
3ba64412f8 | |
|
90c5e5a6ad | |
|
8a022ee02d | |
|
6a89ea8139 | |
|
90c81613ac | |
|
7c62904a74 | |
|
4f6344a12f | |
|
937d3adf66 | |
|
3bac16229f | |
|
ea57847c97 | |
|
730d68132d | |
|
6db872236e | |
|
ba7e676c6f | |
|
6e99accf99 | |
|
b195df9773 | |
|
f303d9d7e8 | |
|
62a2a2e8f9 | |
|
ffbadbcc4c | |
|
50ad2ee9d6 | |
|
c170af5642 | |
|
242bceecd3 | |
|
06346b8a2a | |
|
b071eeadfb | |
|
e7f23d8328 | |
|
47a3f09abf | |
|
a7a6af0a68 | |
|
f203b6c051 | |
|
07211f1fc3 | |
|
bc27f6c0d8 | |
|
c65f9c3497 | |
|
afe5f57adc | |
|
9135c7ce56 | |
|
7fae415689 | |
|
e5cc8667ac | |
|
0ea18d0e16 | |
|
2d674999f0 | |
|
3121903fa3 | |
|
af2e49aa29 | |
|
22940635fe | |
|
c1042b32b7 | |
|
29a144694d | |
|
548d56e654 | |
|
6fb4f2d6d2 | |
|
8eac07ad24 | |
|
716402a180 | |
|
4c3d6938ed | |
|
b4486802f2 | |
|
d210e3d76a | |
|
f2773f585e | |
|
305695ad5d | |
|
418ab36a72 | |
|
563b4fbbd5 | |
|
878d33115f | |
|
356a4ee62e | |
|
eb32ae25e0 | |
|
3ca4062536 | |
|
019f8aaf30 | |
|
663fa737f3 | |
|
73d86259ce | |
|
c7eedf85c7 | |
|
8dc3ffd552 | |
|
b992a061fb | |
|
4fc09a6f61 | |
|
e57176a43c | |
|
710d0d9012 | |
|
039de3ef65 | |
|
de38f63a55 | |
|
38f8193199 | |
|
15cffb7357 | |
|
d55748e05b | |
|
5602861dd4 | |
|
f6037d6c9b |
|
@ -0,0 +1 @@
|
||||||
|
github: [neuecc]
|
|
@ -0,0 +1,12 @@
|
||||||
|
# ref: https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot
|
||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: "github-actions"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "weekly" # Check for updates to GitHub Actions every week
|
||||||
|
ignore:
|
||||||
|
# I just want update action when major/minor version is updated. patch updates are too noisy.
|
||||||
|
- dependency-name: '*'
|
||||||
|
update-types:
|
||||||
|
- version-update:semver-patch
|
|
@ -13,66 +13,76 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: Cysharp/Actions/.github/actions/checkout@main
|
||||||
- uses: Cysharp/Actions/.github/actions/setup-dotnet@main
|
- uses: Cysharp/Actions/.github/actions/setup-dotnet@main
|
||||||
with:
|
|
||||||
dotnet-version: |
|
|
||||||
3.1.x
|
|
||||||
6.0.x
|
|
||||||
- run: dotnet build -c Debug
|
- run: dotnet build -c Debug
|
||||||
- run: dotnet test -c Debug
|
- run: dotnet test -c Debug
|
||||||
|
|
||||||
build-unity:
|
build-unity:
|
||||||
if: "((github.event_name == 'push' && github.repository_owner == 'Cysharp') || startsWith(github.event.pull_request.head.label, 'Cysharp:'))"
|
if: ${{ ((github.event_name == 'push' && github.repository_owner == 'Cysharp') || startsWith(github.event.pull_request.head.label, 'Cysharp:')) && github.triggering_actor != 'dependabot[bot]' }}
|
||||||
strategy:
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
max-parallel: 2
|
||||||
matrix:
|
matrix:
|
||||||
unity: ["2019.3.9f1", "2019.4.13f1", "2020.1.12f1"]
|
unity: ["2022.3.39f1", "6000.0.12f1"] # Test with LTS
|
||||||
include:
|
|
||||||
- unity: 2019.3.9f1
|
|
||||||
license: UNITY_LICENSE_2019
|
|
||||||
- unity: 2019.4.13f1
|
|
||||||
license: UNITY_LICENSE_2019
|
|
||||||
- unity: 2020.1.12f1
|
|
||||||
license: UNITY_LICENSE_2020
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 15
|
timeout-minutes: 30 # Unity build takes more than 20min.
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- name: Load secrets
|
||||||
# Execute scripts: RuntimeUnitTestToolkit
|
id: op-load-secret
|
||||||
# /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -projectPath . -executeMethod UnitTestBuilder.BuildUnitTest /headless /ScriptBackend mono /BuildTarget StandaloneLinux64
|
uses: 1password/load-secrets-action@581a835fb51b8e7ec56b71cf2ffddd7e68bb25e0 # v2.0.0
|
||||||
- name: Build UnitTest(Linux64, mono)
|
|
||||||
uses: game-ci/unity-builder@v2
|
|
||||||
env:
|
|
||||||
UNITY_LICENSE: ${{ secrets[matrix.license] }}
|
|
||||||
with:
|
with:
|
||||||
projectPath: src/UniTask
|
export-env: false
|
||||||
unityVersion: ${{ matrix.unity }}
|
env:
|
||||||
targetPlatform: StandaloneLinux64
|
OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN_PUBLIC }}
|
||||||
buildMethod: UnitTestBuilder.BuildUnitTest
|
UNITY_EMAIL: "op://${{ vars.OP_VAULT_ACTIONS_PUBLIC }}/UNITY_LICENSE/username"
|
||||||
customParameters: /headless /ScriptBackend mono
|
UNITY_PASSWORD: "op://${{ vars.OP_VAULT_ACTIONS_PUBLIC }}/UNITY_LICENSE/credential"
|
||||||
versioning: None
|
UNITY_SERIAL: "op://${{ vars.OP_VAULT_ACTIONS_PUBLIC }}/UNITY_LICENSE/serial"
|
||||||
- name: Execute UnitTest
|
|
||||||
run: ./src/UniTask/bin/UnitTest/StandaloneLinux64_Mono2x/test
|
- uses: Cysharp/Actions/.github/actions/checkout@main
|
||||||
|
|
||||||
# Execute scripts: Export Package
|
# Execute scripts: Export Package
|
||||||
# /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -projectPath . -executeMethod PackageExporter.Export
|
# /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -projectPath . -executeMethod PackageExporter.Export
|
||||||
- name: Export unitypackage
|
- name: Build Unity (.unitypacakge)
|
||||||
uses: game-ci/unity-builder@v2
|
if: ${{ startsWith(matrix.unity, '2022') }} # only execute once
|
||||||
|
uses: Cysharp/Actions/.github/actions/unity-builder@main
|
||||||
env:
|
env:
|
||||||
UNITY_LICENSE: ${{ secrets[matrix.license] }}
|
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:
|
with:
|
||||||
projectPath: src/UniTask
|
projectPath: src/UniTask
|
||||||
unityVersion: ${{ matrix.unity }}
|
unityVersion: ${{ matrix.unity }}
|
||||||
targetPlatform: StandaloneLinux64
|
targetPlatform: StandaloneLinux64
|
||||||
buildMethod: PackageExporter.Export
|
buildMethod: PackageExporter.Export
|
||||||
versioning: None
|
|
||||||
|
# Execute UnitTest
|
||||||
|
# /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -projectPath . -executeMethod UnitTestBuilder.BuildUnitTest /headless /ScriptBackend IL2CPP /BuildTarget StandaloneLinux64
|
||||||
|
- name: Build UnitTest (IL2CPP)
|
||||||
|
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: ${{ matrix.unity }}
|
||||||
|
targetPlatform: StandaloneLinux64
|
||||||
|
buildMethod: UnitTestBuilder.BuildUnitTest
|
||||||
|
customParameters: "/headless /ScriptBackend IL2CPP"
|
||||||
|
- name: Check UnitTest file is generated
|
||||||
|
run: ls -lR ./src/UniTask/bin/UnitTest
|
||||||
|
- name: Execute UnitTest
|
||||||
|
run: ./src/UniTask/bin/UnitTest/StandaloneLinux64_IL2CPP/test
|
||||||
|
|
||||||
- uses: Cysharp/Actions/.github/actions/check-metas@main # check meta files
|
- uses: Cysharp/Actions/.github/actions/check-metas@main # check meta files
|
||||||
with:
|
with:
|
||||||
directory: src/UniTask
|
directory: src/UniTask
|
||||||
|
|
||||||
# Store artifacts.
|
# Store artifacts.
|
||||||
- uses: actions/upload-artifact@v2
|
- uses: Cysharp/Actions/.github/actions/upload-artifact@main
|
||||||
|
if: ${{ startsWith(matrix.unity, '2021') }} # only execute 2021
|
||||||
with:
|
with:
|
||||||
name: UniTask.unitypackage-${{ matrix.unity }}.zip
|
name: UniTask.unitypackage-${{ matrix.unity }}.zip
|
||||||
path: ./src/UniTask/*.unitypackage
|
path: ./src/UniTask/*.unitypackage
|
||||||
|
retention-days: 1
|
||||||
|
|
|
@ -11,21 +11,21 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: Cysharp/Actions/.github/actions/checkout@main
|
||||||
- uses: actions/checkout@v3
|
- uses: Cysharp/Actions/.github/actions/checkout@main
|
||||||
with:
|
with:
|
||||||
repository: Cysharp/DocfxTemplate
|
repository: Cysharp/DocfxTemplate
|
||||||
path: docs/_DocfxTemplate
|
path: docs/_DocfxTemplate
|
||||||
- uses: Kirbyrawr/docfx-action@master
|
- uses: Kirbyrawr/docfx-action@db9a22c8fe1e8693a2a21be54cb0b87dfaa72cc4
|
||||||
name: Docfx metadata
|
name: Docfx metadata
|
||||||
with:
|
with:
|
||||||
args: metadata docs/docfx.json
|
args: metadata docs/docfx.json
|
||||||
- uses: Kirbyrawr/docfx-action@master
|
- uses: Kirbyrawr/docfx-action@db9a22c8fe1e8693a2a21be54cb0b87dfaa72cc4
|
||||||
name: Docfx build
|
name: Docfx build
|
||||||
with:
|
with:
|
||||||
args: build docs/docfx.json
|
args: build docs/docfx.json
|
||||||
- name: Publish to GitHub Pages
|
- name: Publish to GitHub Pages
|
||||||
uses: peaceiris/actions-gh-pages@v3
|
uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0
|
||||||
with:
|
with:
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
publish_dir: docs/_site
|
publish_dir: docs/_site
|
||||||
|
|
|
@ -12,17 +12,13 @@ on:
|
||||||
default: false
|
default: false
|
||||||
type: boolean
|
type: boolean
|
||||||
|
|
||||||
env:
|
|
||||||
GIT_TAG: ${{ github.event.inputs.tag }}
|
|
||||||
DRY_RUN: ${{ github.event.inputs.dry-run }}
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
update-packagejson:
|
update-packagejson:
|
||||||
uses: Cysharp/Actions/.github/workflows/update-packagejson.yaml@main
|
uses: Cysharp/Actions/.github/workflows/update-packagejson.yaml@main
|
||||||
with:
|
with:
|
||||||
file-path: ./src/UniTask/Assets/Plugins/UniTask/package.json
|
file-path: ./src/UniTask/Assets/Plugins/UniTask/package.json
|
||||||
tag: ${{ github.event.inputs.tag }}
|
tag: ${{ inputs.tag }}
|
||||||
dry-run: ${{ fromJson(github.event.inputs.dry-run) }}
|
dry-run: ${{ inputs.dry-run }}
|
||||||
|
|
||||||
build-dotnet:
|
build-dotnet:
|
||||||
needs: [update-packagejson]
|
needs: [update-packagejson]
|
||||||
|
@ -30,96 +26,84 @@ jobs:
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
steps:
|
steps:
|
||||||
- run: echo ${{ needs.update-packagejson.outputs.sha }}
|
- run: echo ${{ needs.update-packagejson.outputs.sha }}
|
||||||
- uses: actions/checkout@v3
|
- uses: Cysharp/Actions/.github/actions/checkout@main
|
||||||
with:
|
with:
|
||||||
ref: ${{ needs.update-packagejson.outputs.sha }}
|
ref: ${{ needs.update-packagejson.outputs.sha }}
|
||||||
- uses: Cysharp/Actions/.github/actions/setup-dotnet@main
|
- uses: Cysharp/Actions/.github/actions/setup-dotnet@main
|
||||||
with:
|
|
||||||
dotnet-version: |
|
|
||||||
3.1.x
|
|
||||||
6.0.x
|
|
||||||
# build and pack
|
# build and pack
|
||||||
- run: dotnet build -c Release -p:Version=${{ env.GIT_TAG }}
|
- run: dotnet build -c Release -p:Version=${{ inputs.tag }}
|
||||||
- run: dotnet test -c Release --no-build
|
- run: dotnet test -c Release --no-build
|
||||||
- run: dotnet pack ./src/UniTask.NetCore/UniTask.NetCore.csproj -c Release --no-build -p:Version=${{ env.GIT_TAG }} -o ./publish
|
- run: dotnet pack ./src/UniTask.NetCore/UniTask.NetCore.csproj -c Release --no-build -p:Version=${{ inputs.tag }} -o ./publish
|
||||||
# Store artifacts.
|
# Store artifacts.
|
||||||
- uses: actions/upload-artifact@v2
|
- uses: Cysharp/Actions/.github/actions/upload-artifact@main
|
||||||
with:
|
with:
|
||||||
name: nuget
|
name: nuget
|
||||||
path: ./publish/
|
path: ./publish/
|
||||||
|
retention-days: 1
|
||||||
|
|
||||||
build-unity:
|
build-unity:
|
||||||
needs: [update-packagejson]
|
needs: [update-packagejson]
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
unity: ["2019.3.9f1"]
|
unity: ["2022.3.39f1"]
|
||||||
include:
|
|
||||||
- unity: 2019.3.9f1
|
|
||||||
license: UNITY_LICENSE_2019
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 15
|
timeout-minutes: 15
|
||||||
steps:
|
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"
|
||||||
|
|
||||||
- run: echo ${{ needs.update-packagejson.outputs.sha }}
|
- run: echo ${{ needs.update-packagejson.outputs.sha }}
|
||||||
- uses: actions/checkout@v3
|
- uses: Cysharp/Actions/.github/actions/checkout@main
|
||||||
with:
|
with:
|
||||||
ref: ${{ needs.update-packagejson.outputs.sha }}
|
ref: ${{ needs.update-packagejson.outputs.sha }}
|
||||||
# Execute scripts: Export Package
|
# Execute scripts: Export Package
|
||||||
# /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -projectPath . -executeMethod PackageExporter.Export
|
# /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -projectPath . -executeMethod PackageExporter.Export
|
||||||
- name: Export unitypackage
|
- name: Build Unity (.unitypacakge)
|
||||||
uses: game-ci/unity-builder@v2
|
uses: Cysharp/Actions/.github/actions/unity-builder@main
|
||||||
env:
|
env:
|
||||||
UNITY_LICENSE: ${{ secrets[matrix.license] }}
|
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:
|
with:
|
||||||
projectPath: src/UniTask
|
projectPath: src/UniTask
|
||||||
unityVersion: ${{ matrix.unity }}
|
unityVersion: ${{ matrix.unity }}
|
||||||
targetPlatform: StandaloneLinux64
|
targetPlatform: StandaloneLinux64
|
||||||
buildMethod: PackageExporter.Export
|
buildMethod: PackageExporter.Export
|
||||||
versioning: None
|
|
||||||
|
|
||||||
- uses: Cysharp/Actions/.github/actions/check-metas@main # check meta files
|
- uses: Cysharp/Actions/.github/actions/check-metas@main # check meta files
|
||||||
with:
|
with:
|
||||||
directory: src/UniTask
|
directory: src/UniTask
|
||||||
|
|
||||||
# Store artifacts.
|
# Store artifacts.
|
||||||
- uses: actions/upload-artifact@v2
|
- uses: Cysharp/Actions/.github/actions/upload-artifact@main
|
||||||
with:
|
with:
|
||||||
name: UniTask.${{ env.GIT_TAG }}.unitypackage
|
name: UniTask.${{ inputs.tag }}.unitypackage
|
||||||
path: ./src/UniTask/UniTask.${{ env.GIT_TAG }}.unitypackage
|
path: ./src/UniTask/UniTask.${{ inputs.tag }}.unitypackage
|
||||||
|
retention-days: 1
|
||||||
|
|
||||||
|
# release
|
||||||
create-release:
|
create-release:
|
||||||
if: github.event.inputs.dry-run == 'false'
|
|
||||||
needs: [update-packagejson, build-dotnet, build-unity]
|
needs: [update-packagejson, build-dotnet, build-unity]
|
||||||
runs-on: ubuntu-latest
|
uses: Cysharp/Actions/.github/workflows/create-release.yaml@main
|
||||||
timeout-minutes: 10
|
|
||||||
steps:
|
|
||||||
- uses: Cysharp/Actions/.github/actions/setup-dotnet@main
|
|
||||||
# Create Releases
|
|
||||||
- uses: actions/create-release@v1
|
|
||||||
id: create_release
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
with:
|
with:
|
||||||
tag_name: ${{ env.GIT_TAG }}
|
commit-id: ${{ needs.update-packagejson.outputs.sha }}
|
||||||
release_name: Ver.${{ env.GIT_TAG }}
|
dry-run: ${{ inputs.dry-run }}
|
||||||
commitish: ${{ needs.update-packagejson.outputs.sha }}
|
tag: ${{ inputs.tag }}
|
||||||
draft: true
|
nuget-push: true
|
||||||
prerelease: false
|
release-upload: true
|
||||||
# Download(All) Artifacts to current directory
|
release-asset-path: ./UniTask.${{ inputs.tag }}.unitypackage/UniTask.${{ inputs.tag }}.unitypackage
|
||||||
- uses: actions/download-artifact@v2
|
secrets: inherit
|
||||||
# Upload to NuGet
|
|
||||||
- run: dotnet nuget push "./nuget/*.nupkg" --skip-duplicate -s https://www.nuget.org/api/v2/package -k ${{ secrets.NUGET_KEY }}
|
|
||||||
# Upload to Releases(unitypackage)
|
|
||||||
- uses: actions/upload-release-asset@v1
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
with:
|
|
||||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
|
||||||
asset_path: ./UniTask.${{ env.GIT_TAG }}.unitypackage/UniTask.${{ env.GIT_TAG }}.unitypackage
|
|
||||||
asset_name: UniTask.${{ env.GIT_TAG }}.unitypackage
|
|
||||||
asset_content_type: application/octet-stream
|
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
if: needs.update-packagejson.outputs.is-branch-created == 'true'
|
if: ${{ needs.update-packagejson.outputs.is-branch-created == 'true' }}
|
||||||
needs: [update-packagejson, build-dotnet, build-unity]
|
needs: [update-packagejson, build-dotnet, build-unity]
|
||||||
uses: Cysharp/Actions/.github/workflows/clean-packagejson-branch.yaml@main
|
uses: Cysharp/Actions/.github/workflows/clean-packagejson-branch.yaml@main
|
||||||
with:
|
with:
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
name: Prevent github change
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- ".github/**/*.yaml"
|
||||||
|
- ".github/**/*.yml"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
detect:
|
||||||
|
uses: Cysharp/Actions/.github/workflows/prevent-github-change.yaml@main
|
|
@ -8,8 +8,7 @@ on:
|
||||||
jobs:
|
jobs:
|
||||||
generateTOC:
|
generateTOC:
|
||||||
name: TOC Generator
|
name: TOC Generator
|
||||||
runs-on: ubuntu-latest
|
uses: Cysharp/Actions/.github/workflows/toc-generator.yaml@main
|
||||||
steps:
|
|
||||||
- uses: technote-space/toc-generator@v2.4.0
|
|
||||||
with:
|
with:
|
||||||
TOC_TITLE: "## Table of Contents"
|
TOC_TITLE: "## Table of Contents"
|
||||||
|
secrets: inherit
|
||||||
|
|
|
@ -130,134 +130,15 @@ UpgradeLog*.XML
|
||||||
Assets/WSATestCertificate.pfx
|
Assets/WSATestCertificate.pfx
|
||||||
.vs/
|
.vs/
|
||||||
|
|
||||||
Assembly-CSharp\.csproj
|
# Unity
|
||||||
|
|
||||||
UniRx\.Async\.csproj
|
# Unity
|
||||||
|
.vsconfig
|
||||||
UniRx\.Async\.Editor\.csproj
|
src/UniTask/Library/*
|
||||||
|
src/UniTask/Temp/*
|
||||||
UniRx\.Async\.Tests\.csproj
|
src/UniTask/Logs/*
|
||||||
|
src/UniTask/[Uu]ser[Ss]ettings/
|
||||||
UniTask\.sln
|
src/UniTask/*.sln
|
||||||
|
src/UniTask/*.csproj
|
||||||
RuntimeUnitTestToolkit\.csproj
|
src/UniTask/*.unitypackage
|
||||||
|
!src/UniTask/Packages/
|
||||||
Assembly-CSharp-Editor\.csproj
|
|
||||||
|
|
||||||
UniRx\.Async\.unitypackage
|
|
||||||
|
|
||||||
UniRx.Async.Tests.Editor.csproj
|
|
||||||
|
|
||||||
src/UniTask/UniTask.csproj
|
|
||||||
|
|
||||||
src/UniTask/UniTask.Editor.csproj
|
|
||||||
|
|
||||||
src/UniTask/UniTask.Tests.csproj
|
|
||||||
|
|
||||||
src/UniTask/UniTask.Tests.Editor.csproj
|
|
||||||
|
|
||||||
src/UniTask/UniTask.*.unitypackage
|
|
||||||
|
|
||||||
src/UniTask/UniTask.Linq.csproj
|
|
||||||
|
|
||||||
src/UniTask/DOTween.Modules.csproj
|
|
||||||
|
|
||||||
src/UniTask/Unity.Addressables.csproj
|
|
||||||
|
|
||||||
src/UniTask/Unity.Addressables.Editor.csproj
|
|
||||||
|
|
||||||
src/UniTask/Unity.Analytics.DataPrivacy.csproj
|
|
||||||
|
|
||||||
src/UniTask/Unity.Recorder.csproj
|
|
||||||
|
|
||||||
src/UniTask/Unity.Recorder.Editor.csproj
|
|
||||||
|
|
||||||
src/UniTask/Unity.ResourceManager.csproj
|
|
||||||
|
|
||||||
src/UniTask/Unity.Rider.Editor.csproj
|
|
||||||
|
|
||||||
src/UniTask/Unity.ScriptableBuildPipeline.csproj
|
|
||||||
|
|
||||||
src/UniTask/Unity.ScriptableBuildPipeline.Editor.csproj
|
|
||||||
|
|
||||||
src/UniTask/Unity.TextMeshPro.csproj
|
|
||||||
|
|
||||||
src/UniTask/Unity.TextMeshPro.Editor.csproj
|
|
||||||
|
|
||||||
src/UniTask/Unity.Timeline.csproj
|
|
||||||
|
|
||||||
src/UniTask/Unity.Timeline.Editor.csproj
|
|
||||||
|
|
||||||
src/UniTask/Unity.VisualStudio.Editor.csproj
|
|
||||||
|
|
||||||
src/UniTask/Unity.VSCode.Editor.csproj
|
|
||||||
|
|
||||||
src/UniTask/UnityEditor.CacheServer.csproj
|
|
||||||
|
|
||||||
src/UniTask/UnityEditor.TestRunner.csproj
|
|
||||||
|
|
||||||
src/UniTask/UnityEditor.UI.csproj
|
|
||||||
|
|
||||||
src/UniTask/UnityEngine.Advertisements.csproj
|
|
||||||
|
|
||||||
src/UniTask/UnityEngine.Monetization.csproj
|
|
||||||
|
|
||||||
src/UniTask/UnityEngine.TestRunner.csproj
|
|
||||||
|
|
||||||
src/UniTask/UnityEngine.UI.csproj
|
|
||||||
|
|
||||||
src/UniTask/TempAsm.csproj
|
|
||||||
|
|
||||||
src/UniTask/UniTask.Addressables.csproj
|
|
||||||
|
|
||||||
src/UniTask/UniTask.DOTween.csproj
|
|
||||||
|
|
||||||
src/UniTask/UniTask.TextMeshPro.csproj
|
|
||||||
|
|
||||||
src/UniTask/RuntimeUnitTestToolkit.Player.csproj
|
|
||||||
|
|
||||||
src/UniTask/TempAsm.Player.csproj
|
|
||||||
|
|
||||||
src/UniTask/UniTask.Addressables.Player.csproj
|
|
||||||
|
|
||||||
src/UniTask/UniTask.DOTween.Player.csproj
|
|
||||||
|
|
||||||
src/UniTask/UniTask.Linq.Player.csproj
|
|
||||||
|
|
||||||
src/UniTask/UniTask.Player.csproj
|
|
||||||
|
|
||||||
src/UniTask/UniTask.Tests.Player.csproj
|
|
||||||
|
|
||||||
src/UniTask/UniTask.TextMeshPro.Player.csproj
|
|
||||||
|
|
||||||
src/UniTask/Unity.Addressables.Player.csproj
|
|
||||||
|
|
||||||
src/UniTask/Unity.Analytics.DataPrivacy.Player.csproj
|
|
||||||
|
|
||||||
src/UniTask/Unity.ResourceManager.Player.csproj
|
|
||||||
|
|
||||||
src/UniTask/Unity.ScriptableBuildPipeline.Player.csproj
|
|
||||||
|
|
||||||
src/UniTask/Unity.TextMeshPro.Player.csproj
|
|
||||||
|
|
||||||
src/UniTask/Unity.Timeline.Player.csproj
|
|
||||||
|
|
||||||
src/UniTask/UnityEngine.Advertisements.Player.csproj
|
|
||||||
|
|
||||||
src/UniTask/UnityEngine.Monetization.Player.csproj
|
|
||||||
|
|
||||||
src/UniTask/UnityEngine.TestRunner.Player.csproj
|
|
||||||
|
|
||||||
src/UniTask/UnityEngine.UI.Player.csproj
|
|
||||||
|
|
||||||
src/UniTask/DOTween.Modules.Player.csproj
|
|
||||||
|
|
||||||
src/UniTask/Assembly-CSharp.Player.csproj
|
|
||||||
|
|
||||||
src/UniTask/Unity.EditorCoroutines.Editor.csproj
|
|
||||||
|
|
||||||
src/UniTask/.vsconfig
|
|
||||||
|
|
||||||
src/UniTask/Logs/ApiUpdaterCheck.txt
|
|
||||||
|
|
||||||
src/UniTask/Assembly-CSharp-firstpass.csproj
|
|
||||||
|
|
81
README.md
81
README.md
|
@ -1,6 +1,6 @@
|
||||||
UniTask
|
UniTask
|
||||||
===
|
===
|
||||||
[](https://github.com/Cysharp/UniTask/actions) [](https://github.com/Cysharp/UniTask/releases)
|
[](https://github.com/Cysharp/UniTask/actions) [](https://github.com/Cysharp/UniTask/releases) [](https://github.com/Cysharp/UniTask/blob/master/README_CN.md)
|
||||||
|
|
||||||
Provides an efficient allocation free async/await integration for Unity.
|
Provides an efficient allocation free async/await integration for Unity.
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@ For advanced tips, see blog post: [Extends UnityWebRequest via async decorator p
|
||||||
- [AsyncEnumerable and Async LINQ](#asyncenumerable-and-async-linq)
|
- [AsyncEnumerable and Async LINQ](#asyncenumerable-and-async-linq)
|
||||||
- [Awaitable Events](#awaitable-events)
|
- [Awaitable Events](#awaitable-events)
|
||||||
- [Channel](#channel)
|
- [Channel](#channel)
|
||||||
|
- [vs Awaitable](#vs-awaitable)
|
||||||
- [For Unit Testing](#for-unit-testing)
|
- [For Unit Testing](#for-unit-testing)
|
||||||
- [ThreadPool limitation](#threadpool-limitation)
|
- [ThreadPool limitation](#threadpool-limitation)
|
||||||
- [IEnumerator.ToUniTask limitation](#ienumeratortounitask-limitation)
|
- [IEnumerator.ToUniTask limitation](#ienumeratortounitask-limitation)
|
||||||
|
@ -44,7 +45,6 @@ For advanced tips, see blog post: [Extends UnityWebRequest via async decorator p
|
||||||
- [API References](#api-references)
|
- [API References](#api-references)
|
||||||
- [UPM Package](#upm-package)
|
- [UPM Package](#upm-package)
|
||||||
- [Install via git URL](#install-via-git-url)
|
- [Install via git URL](#install-via-git-url)
|
||||||
- [Install via OpenUPM](#install-via-openupm)
|
|
||||||
- [.NET Core](#net-core)
|
- [.NET Core](#net-core)
|
||||||
- [License](#license)
|
- [License](#license)
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ For advanced tips, see blog post: [Extends UnityWebRequest via async decorator p
|
||||||
|
|
||||||
Getting started
|
Getting started
|
||||||
---
|
---
|
||||||
Install via [UPM package](#upm-package) or asset package(`UniTask.*.*.*.unitypackage`) available in [UniTask/releases](https://github.com/Cysharp/UniTask/releases) page.
|
Install via [UPM package](#upm-package) with git reference or asset package(`UniTask.*.*.*.unitypackage`) available in [UniTask/releases](https://github.com/Cysharp/UniTask/releases).
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// extension awaiter/methods can be used by this namespace
|
// extension awaiter/methods can be used by this namespace
|
||||||
|
@ -68,6 +68,7 @@ async UniTask<string> DemoAsync()
|
||||||
await SceneManager.LoadSceneAsync("scene2");
|
await SceneManager.LoadSceneAsync("scene2");
|
||||||
|
|
||||||
// .WithCancellation enables Cancel, GetCancellationTokenOnDestroy synchornizes with lifetime of GameObject
|
// .WithCancellation enables Cancel, GetCancellationTokenOnDestroy synchornizes with lifetime of GameObject
|
||||||
|
// after Unity 2022.2, you can use `destroyCancellationToken` in MonoBehaviour
|
||||||
var asset2 = await Resources.LoadAsync<TextAsset>("bar").WithCancellation(this.GetCancellationTokenOnDestroy());
|
var asset2 = await Resources.LoadAsync<TextAsset>("bar").WithCancellation(this.GetCancellationTokenOnDestroy());
|
||||||
|
|
||||||
// .ToUniTask accepts progress callback(and all options), Progress.Create is a lightweight alternative of IProgress<T>
|
// .ToUniTask accepts progress callback(and all options), Progress.Create is a lightweight alternative of IProgress<T>
|
||||||
|
@ -86,8 +87,13 @@ async UniTask<string> DemoAsync()
|
||||||
await UniTask.Yield();
|
await UniTask.Yield();
|
||||||
await UniTask.NextFrame();
|
await UniTask.NextFrame();
|
||||||
|
|
||||||
// replacement of WaitForEndOfFrame(requires MonoBehaviour(CoroutineRunner))
|
// replacement of WaitForEndOfFrame
|
||||||
|
#if UNITY_2023_1_OR_NEWER
|
||||||
|
await UniTask.WaitForEndOfFrame();
|
||||||
|
#else
|
||||||
|
// requires MonoBehaviour(CoroutineRunner))
|
||||||
await UniTask.WaitForEndOfFrame(this); // this is MonoBehaviour
|
await UniTask.WaitForEndOfFrame(this); // this is MonoBehaviour
|
||||||
|
#endif
|
||||||
|
|
||||||
// replacement of yield return new WaitForFixedUpdate(same as UniTask.Yield(PlayerLoopTiming.FixedUpdate))
|
// replacement of yield return new WaitForFixedUpdate(same as UniTask.Yield(PlayerLoopTiming.FixedUpdate))
|
||||||
await UniTask.WaitForFixedUpdate();
|
await UniTask.WaitForFixedUpdate();
|
||||||
|
@ -156,7 +162,7 @@ UniTask provides three pattern of extension methods.
|
||||||
|
|
||||||
> Note: AssetBundleRequest has `asset` and `allAssets`, default await returns `asset`. If you want to get `allAssets`, you can use `AwaitForAllAssets()` method.
|
> Note: AssetBundleRequest has `asset` and `allAssets`, default await returns `asset`. If you want to get `allAssets`, you can use `AwaitForAllAssets()` method.
|
||||||
|
|
||||||
The type of `UniTask` can use utilities like `UniTask.WhenAll`, `UniTask.WhenAny`. They are like `Task.WhenAll`/`Task.WhenAny` but the return type is more useful. They return value tuples so you can deconstruct each result and pass multiple types.
|
The type of `UniTask` can use utilities like `UniTask.WhenAll`, `UniTask.WhenAny`, `UniTask.WhenEach`. They are like `Task.WhenAll`/`Task.WhenAny` but the return type is more useful. They return value tuples so you can deconstruct each result and pass multiple types.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
public async UniTaskVoid LoadManyAsync()
|
public async UniTaskVoid LoadManyAsync()
|
||||||
|
@ -289,9 +295,11 @@ public class MyBehaviour : MonoBehaviour
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
After Unity 2022.2, Unity adds CancellationToken in [MonoBehaviour.destroyCancellationToken](https://docs.unity3d.com/ScriptReference/MonoBehaviour-destroyCancellationToken.html) and [Application.exitCancellationToken](https://docs.unity3d.com/ScriptReference/Application-exitCancellationToken.html).
|
||||||
|
|
||||||
When cancellation is detected, all methods throw `OperationCanceledException` and propagate upstream. When exception(not limited to `OperationCanceledException`) is not handled in async method, it is propagated finally to `UniTaskScheduler.UnobservedTaskException`. The default behaviour of received unhandled exception is to write log as exception. Log level can be changed using `UniTaskScheduler.UnobservedExceptionWriteLogType`. If you want to use custom behaviour, set an action to `UniTaskScheduler.UnobservedTaskException.`
|
When cancellation is detected, all methods throw `OperationCanceledException` and propagate upstream. When exception(not limited to `OperationCanceledException`) is not handled in async method, it is propagated finally to `UniTaskScheduler.UnobservedTaskException`. The default behaviour of received unhandled exception is to write log as exception. Log level can be changed using `UniTaskScheduler.UnobservedExceptionWriteLogType`. If you want to use custom behaviour, set an action to `UniTaskScheduler.UnobservedTaskException.`
|
||||||
|
|
||||||
Andalso `OperationCanceledException` is a special exception, this is silently ignored at `UnobservedTaskException`.
|
And also `OperationCanceledException` is a special exception, this is silently ignored at `UnobservedTaskException`.
|
||||||
|
|
||||||
If you want to cancel behaviour in an async UniTask method, throw `OperationCanceledException` manually.
|
If you want to cancel behaviour in an async UniTask method, throw `OperationCanceledException` manually.
|
||||||
|
|
||||||
|
@ -332,6 +340,18 @@ if (isCanceled)
|
||||||
|
|
||||||
Note: Only suppress throws if you call directly into the most source method. Otherwise, the return value will be converted, but the entire pipeline will not suppress throws.
|
Note: Only suppress throws if you call directly into the most source method. Otherwise, the return value will be converted, but the entire pipeline will not suppress throws.
|
||||||
|
|
||||||
|
Some features that use Unity's player loop, such as `UniTask.Yield` and `UniTask.Delay` etc, determines CancellationToken state on the player loop.
|
||||||
|
This means it does not cancel immediately upon `CancellationToken` fired.
|
||||||
|
|
||||||
|
If you want to change this behaviour, the cancellation to be immediate, set the `cancelImmediately` flag as an argument.
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
await UniTask.Yield(cancellationToken, cancelImmediately: true);
|
||||||
|
```
|
||||||
|
|
||||||
|
Note: Setting `cancelImmediately` to true and detecting an immediate cancellation is more costly than the default behavior.
|
||||||
|
This is because it uses `CancellationToken.Register`; it is heavier than checking CancellationToken on the player loop.
|
||||||
|
|
||||||
Timeout handling
|
Timeout handling
|
||||||
---
|
---
|
||||||
Timeout is a variation of cancellation. You can set timeout by `CancellationTokenSouce.CancelAfterSlim(TimeSpan)` and pass CancellationToken to async methods.
|
Timeout is a variation of cancellation. You can set timeout by `CancellationTokenSouce.CancelAfterSlim(TimeSpan)` and pass CancellationToken to async methods.
|
||||||
|
@ -359,7 +379,7 @@ If you want to use timeout with other source of cancellation, use `CancellationT
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
var cancelToken = new CancellationTokenSource();
|
var cancelToken = new CancellationTokenSource();
|
||||||
cancelButton.onClick.AddListener(()=>
|
cancelButton.onClick.AddListener(() =>
|
||||||
{
|
{
|
||||||
cancelToken.Cancel(); // cancel from button click.
|
cancelToken.Cancel(); // cancel from button click.
|
||||||
});
|
});
|
||||||
|
@ -499,6 +519,8 @@ It indicates when to run, you can check [PlayerLoopList.md](https://gist.github.
|
||||||
`PlayerLoopTiming.Update` is similar to `yield return null` in a 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 to `WaitForFixedUpdate`.
|
`PlayerLoopTiming.Update` is similar to `yield return null` in a 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 to `WaitForFixedUpdate`.
|
||||||
|
|
||||||
> `PlayerLoopTiming.LastPostLateUpdate` is not equivalent to coroutine's `yield return new WaitForEndOfFrame()`. Coroutine's WaitForEndOfFrame seems to run after the PlayerLoop is done. Some methods that require coroutine's end of frame(`Texture2D.ReadPixels`, `ScreenCapture.CaptureScreenshotAsTexture`, `CommandBuffer`, etc) do not work correctly when replaced with async/await. In these cases, pass MonoBehaviour(coroutine runnner) to `UniTask.WaitForEndOfFrame`. For example, `await UniTask.WaitForEndOfFrame(this);` is lightweight allocation free alternative of `yield return new WaitForEndOfFrame()`.
|
> `PlayerLoopTiming.LastPostLateUpdate` is not equivalent to coroutine's `yield return new WaitForEndOfFrame()`. Coroutine's WaitForEndOfFrame seems to run after the PlayerLoop is done. Some methods that require coroutine's end of frame(`Texture2D.ReadPixels`, `ScreenCapture.CaptureScreenshotAsTexture`, `CommandBuffer`, etc) do not work correctly when replaced with async/await. In these cases, pass MonoBehaviour(coroutine runnner) to `UniTask.WaitForEndOfFrame`. For example, `await UniTask.WaitForEndOfFrame(this);` is lightweight allocation free alternative of `yield return new WaitForEndOfFrame()`.
|
||||||
|
>
|
||||||
|
> Note: In Unity 2023.1 or newer, `await UniTask.WaitForEndOfFrame();` no longer requires MonoBehaviour. It uses `UnityEngine.Awaitable.EndOfFrameAsync`.
|
||||||
|
|
||||||
`yield return null` and `UniTask.Yield` are similar but different. `yield return null` always returns next frame but `UniTask.Yield` returns next called. That is, call `UniTask.Yield(PlayerLoopTiming.Update)` on `PreUpdate`, it returns same frame. `UniTask.NextFrame()` guarantees return next frame, you can expect this to behave exactly the same as `yield return null`.
|
`yield return null` and `UniTask.Yield` are similar but different. `yield return null` always returns next frame but `UniTask.Yield` returns next called. That is, call `UniTask.Yield(PlayerLoopTiming.Update)` on `PreUpdate`, it returns same frame. `UniTask.NextFrame()` guarantees return next frame, you can expect this to behave exactly the same as `yield return null`.
|
||||||
|
|
||||||
|
@ -508,6 +530,9 @@ It indicates when to run, you can check [PlayerLoopList.md](https://gist.github.
|
||||||
|
|
||||||
In UniTask, await directly uses native timing, while `WithCancellation` and `ToUniTask` use specified timing. This is usually not a particular problem, but with `LoadSceneAsync`, it causes a different order of Start and continuation after await. So it is recommended not to use `LoadSceneAsync.ToUniTask`.
|
In UniTask, await directly uses native timing, while `WithCancellation` and `ToUniTask` use specified timing. This is usually not a particular problem, but with `LoadSceneAsync`, it causes a different order of Start and continuation after await. So it is recommended not to use `LoadSceneAsync.ToUniTask`.
|
||||||
|
|
||||||
|
> Note: When using Unity 2023.1 or newer, ensure you have `using UnityEngine;` in the using statements of your file when working with new `UnityEngine.Awaitable` methods like `SceneManager.LoadSceneAsync`.
|
||||||
|
> This prevents compilation errors by avoiding the use of the `UnityEngine.AsyncOperation` version.
|
||||||
|
|
||||||
In the stacktrace, you can check where it is running in playerloop.
|
In the stacktrace, you can check where it is running in playerloop.
|
||||||
|
|
||||||

|

|
||||||
|
@ -658,7 +683,8 @@ By default, UniTask supports TextMeshPro(`BindTo(TMP_Text)` and `TMP_InputField`
|
||||||
|
|
||||||
There are defined in separated asmdefs like `UniTask.TextMeshPro`, `UniTask.DOTween`, `UniTask.Addressables`.
|
There are defined in separated asmdefs like `UniTask.TextMeshPro`, `UniTask.DOTween`, `UniTask.Addressables`.
|
||||||
|
|
||||||
TextMeshPro and Addressables support are automatically enabled when importing their packages from package manager. However for DOTween support, it is required to import `com.demigiant.dotween` from [OpenUPM](https://openupm.com/packages/com.demigiant.dotween/) or to define `UNITASK_DOTWEEN_SUPPORT` to enable it.
|
TextMeshPro and Addressables support are automatically enabled when importing their packages from package manager.
|
||||||
|
However for DOTween support, after importing from the [DOTWeen assets](https://assetstore.unity.com/packages/tools/animation/dotween-hotween-v2-27676r) and define the scripting define symbol `UNITASK_DOTWEEN_SUPPORT` to enable it.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// sequential
|
// sequential
|
||||||
|
@ -681,7 +707,7 @@ Unity 2020.2 supports C# 8.0 so you can use `await foreach`. This is the new Upd
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// Unity 2020.2, C# 8.0
|
// Unity 2020.2, C# 8.0
|
||||||
await foreach (var _ in UniTaskAsyncEnumerable.EveryUpdate(token))
|
await foreach (var _ in UniTaskAsyncEnumerable.EveryUpdate().WithCancellation(token))
|
||||||
{
|
{
|
||||||
Debug.Log("Update() " + Time.frameCount);
|
Debug.Log("Update() " + Time.frameCount);
|
||||||
}
|
}
|
||||||
|
@ -691,10 +717,23 @@ In a C# 7.3 environment, you can use the `ForEachAsync` method to work in almost
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// C# 7.3(Unity 2018.3~)
|
// C# 7.3(Unity 2018.3~)
|
||||||
await UniTaskAsyncEnumerable.EveryUpdate(token).ForEachAsync(_ =>
|
await UniTaskAsyncEnumerable.EveryUpdate().ForEachAsync(_ =>
|
||||||
{
|
{
|
||||||
Debug.Log("Update() " + Time.frameCount);
|
Debug.Log("Update() " + Time.frameCount);
|
||||||
});
|
}, token);
|
||||||
|
```
|
||||||
|
|
||||||
|
`UniTask.WhenEach` that is similar to .NET 9's `Task.WhenEach` can consume new way for await multiple tasks.
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
await foreach (var result in UniTask.WhenEach(task1, task2, task3))
|
||||||
|
{
|
||||||
|
// The result is of type WhenEachResult<T>.
|
||||||
|
// It contains either `T Result` or `Exception Exception`.
|
||||||
|
// You can check `IsCompletedSuccessfully` or `IsFaulted` to determine whether to access `.Result` or `.Exception`.
|
||||||
|
// If you want to throw an exception when `IsFaulted` and retrieve the result when successful, use `GetResult()`.
|
||||||
|
Debug.Log(result.GetResult());
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
UniTaskAsyncEnumerable implements asynchronous LINQ, similar to LINQ in `IEnumerable<T>` or Rx in `IObservable<T>`. All standard LINQ query operators can be applied to asynchronous streams. For example, the following code shows how to apply a Where filter to a button-click asynchronous stream that runs once every two clicks.
|
UniTaskAsyncEnumerable implements asynchronous LINQ, similar to LINQ in `IEnumerable<T>` or Rx in `IObservable<T>`. All standard LINQ query operators can be applied to asynchronous streams. For example, the following code shows how to apply a Where filter to a button-click asynchronous stream that runs once every two clicks.
|
||||||
|
@ -717,7 +756,7 @@ Async LINQ is enabled when `using Cysharp.Threading.Tasks.Linq;`, and `UniTaskAs
|
||||||
|
|
||||||
It's closer to UniRx (Reactive Extensions), but UniTaskAsyncEnumerable is a pull-based asynchronous stream, whereas Rx was a push-based asynchronous stream. Note that although similar, the characteristics are different and the details behave differently along with them.
|
It's closer to UniRx (Reactive Extensions), but UniTaskAsyncEnumerable is a pull-based asynchronous stream, whereas Rx was a push-based asynchronous stream. Note that although similar, the characteristics are different and the details behave differently along with them.
|
||||||
|
|
||||||
`UniTaskAsyncEnumerable` is the entry point like `Enumerable`. In addition to the standard query operators, there are other generators for Unity such as `EveryUpdate`, `Timer`, `TimerFrame`, `Interval`, `IntervalFrame`, and `EveryValueChanged`. And also added additional UniTask original query operators like `Append`, `Prepend`, `DistinctUntilChanged`, `ToHashSet`, `Buffer`, `CombineLatest`, `Do`, `Never`, `ForEachAsync`, `Pairwise`, `Publish`, `Queue`, `Return`, `SkipUntil`, `TakeUntil`, `SkipUntilCanceled`, `TakeUntilCanceled`, `TakeLast`, `Subscribe`.
|
`UniTaskAsyncEnumerable` is the entry point like `Enumerable`. In addition to the standard query operators, there are other generators for Unity such as `EveryUpdate`, `Timer`, `TimerFrame`, `Interval`, `IntervalFrame`, and `EveryValueChanged`. And also added additional UniTask original query operators like `Append`, `Prepend`, `DistinctUntilChanged`, `ToHashSet`, `Buffer`, `CombineLatest`,`Merge` `Do`, `Never`, `ForEachAsync`, `Pairwise`, `Publish`, `Queue`, `Return`, `SkipUntil`, `TakeUntil`, `SkipUntilCanceled`, `TakeUntilCanceled`, `TakeLast`, `Subscribe`.
|
||||||
|
|
||||||
The method with Func as an argument has three additional overloads, `***Await`, `***AwaitWithCancellation`.
|
The method with Func as an argument has three additional overloads, `***Await`, `***AwaitWithCancellation`.
|
||||||
|
|
||||||
|
@ -918,6 +957,14 @@ public class AsyncMessageBroker<T> : IDisposable
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
vs Awaitable
|
||||||
|
---
|
||||||
|
Unity 6 introduces the awaitable type, [Awaitable](https://docs.unity3d.com/6000.0/Documentation/ScriptReference/Awaitable.html). To put it simply, Awaitable can be considered a subset of UniTask, and in fact, Awaitable's design was influenced by UniTask. It should be able to handle PlayerLoop-based awaits, pooled Tasks, and support for cancellation with `CancellationToken` in a similar way. With its inclusion in the standard library, you may wonder whether to continue using UniTask or migrate to Awaitable. Here's a brief guide.
|
||||||
|
|
||||||
|
First, the functionality provided by Awaitable is equivalent to what coroutines offer. Instead of `yield return`, you use await; `await NextFrameAsync()` replaces `yield return null`; and there are equivalents for `WaitForSeconds` and `EndOfFrame`. However, that's the extent of it. Being coroutine-based in terms of functionality, it lacks Task-based features. In practical application development using async/await, operations like `WhenAll` are essential. Additionally, UniTask enables many frame-based operations (such as `DelayFrame`) and more flexible PlayerLoopTiming control, which are not available in Awaitable. Of course, there's no Tracker Window either.
|
||||||
|
|
||||||
|
Therefore, I recommend using UniTask for application development. UniTask is a superset of Awaitable and includes many essential features. For library development, where you want to avoid external dependencies, using Awaitable as a return type for methods would be appropriate. Awaitable can be converted to UniTask using `AsUniTask`, so there's no issue in handling Awaitable-based functionality within the UniTask library. Of course, if you don't need to worry about dependencies, using UniTask would be the best choice even for library development.
|
||||||
|
|
||||||
For Unit Testing
|
For Unit Testing
|
||||||
---
|
---
|
||||||
Unity's `[UnityTest]` attribute can test coroutine(IEnumerator) but can not test async. `UniTask.ToCoroutine` bridges async/await to coroutine so you can test async methods.
|
Unity's `[UnityTest]` attribute can test coroutine(IEnumerator) but can not test async. `UniTask.ToCoroutine` bridges async/await to coroutine so you can test async methods.
|
||||||
|
@ -1007,6 +1054,7 @@ Use UniTask type.
|
||||||
| `Task.Run` | `UniTask.RunOnThreadPool` |
|
| `Task.Run` | `UniTask.RunOnThreadPool` |
|
||||||
| `Task.WhenAll` | `UniTask.WhenAll` |
|
| `Task.WhenAll` | `UniTask.WhenAll` |
|
||||||
| `Task.WhenAny` | `UniTask.WhenAny` |
|
| `Task.WhenAny` | `UniTask.WhenAny` |
|
||||||
|
| `Task.WhenEach` | `UniTask.WhenEach` |
|
||||||
| `Task.CompletedTask` | `UniTask.CompletedTask` |
|
| `Task.CompletedTask` | `UniTask.CompletedTask` |
|
||||||
| `Task.FromException` | `UniTask.FromException` |
|
| `Task.FromException` | `UniTask.FromException` |
|
||||||
| `Task.FromResult` | `UniTask.FromResult` |
|
| `Task.FromResult` | `UniTask.FromResult` |
|
||||||
|
@ -1072,13 +1120,6 @@ or add `"com.cysharp.unitask": "https://github.com/Cysharp/UniTask.git?path=src/
|
||||||
|
|
||||||
If you want to set a target version, UniTask uses the `*.*.*` release tag so you can specify a version like `#2.1.0`. For example `https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask#2.1.0`.
|
If you want to set a target version, UniTask uses the `*.*.*` release tag so you can specify a version like `#2.1.0`. For example `https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask#2.1.0`.
|
||||||
|
|
||||||
### Install via OpenUPM
|
|
||||||
|
|
||||||
The package is available on the [openupm registry](https://openupm.com). It's recommended to install it via [openupm-cli](https://github.com/openupm/openupm-cli).
|
|
||||||
|
|
||||||
```
|
|
||||||
openupm add com.cysharp.unitask
|
|
||||||
```
|
|
||||||
|
|
||||||
.NET Core
|
.NET Core
|
||||||
---
|
---
|
||||||
|
@ -1088,7 +1129,7 @@ For .NET Core, use NuGet.
|
||||||
|
|
||||||
UniTask of .NET Core version is a subset of Unity UniTask with PlayerLoop dependent methods removed.
|
UniTask of .NET Core version is a subset of Unity UniTask with PlayerLoop dependent methods removed.
|
||||||
|
|
||||||
It runs at higher performance than the standard Task/ValueTask, but you should be careful to ignore the ExecutionContext/SynchronizationContext when using it. `AysncLocal` also does not work because it ignores ExecutionContext.
|
It runs at higher performance than the standard Task/ValueTask, but you should be careful to ignore the ExecutionContext/SynchronizationContext when using it. `AsyncLocal` also does not work because it ignores ExecutionContext.
|
||||||
|
|
||||||
If you use UniTask internally, but provide ValueTask as an external API, you can write it like the following(Inspired by [PooledAwait](https://github.com/mgravell/PooledAwait)).
|
If you use UniTask internally, but provide ValueTask as an external API, you can write it like the following(Inspired by [PooledAwait](https://github.com/mgravell/PooledAwait)).
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,10 +1,11 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>netcoreapp3.1;netstandard2.1;netstandard2.0</TargetFrameworks>
|
<TargetFrameworks>net6.0;net7.0;netstandard2.1;netstandard2.0</TargetFrameworks>
|
||||||
<AssemblyName>UniTask</AssemblyName>
|
<AssemblyName>UniTask</AssemblyName>
|
||||||
<LangVersion>8.0</LangVersion>
|
<LangVersion>8.0</LangVersion>
|
||||||
<RootNamespace>Cysharp.Threading.Tasks</RootNamespace>
|
<RootNamespace>Cysharp.Threading.Tasks</RootNamespace>
|
||||||
|
<DefineConstants>UNITASK_NETCORE</DefineConstants>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
<NoWarn>$(NoWarn);CS1591</NoWarn>
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<RootNamespace>NetCoreSandbox</RootNamespace>
|
<RootNamespace>NetCoreSandbox</RootNamespace>
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
|
@ -159,6 +159,30 @@ namespace NetCoreTests.Linq
|
||||||
list.Should().Equal(100, 200, 300, 400);
|
list.Should().Equal(100, 200, 300, 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task AwaitForeachBreak()
|
||||||
|
{
|
||||||
|
var finallyCalled = false;
|
||||||
|
var enumerable = UniTaskAsyncEnumerable.Create<int>(async (writer, _) =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await writer.YieldAsync(1);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
finallyCalled = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await foreach (var x in enumerable)
|
||||||
|
{
|
||||||
|
x.Should().Be(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
finallyCalled.Should().BeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
async IAsyncEnumerable<int> Range(int from, int count)
|
async IAsyncEnumerable<int> Range(int from, int count)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
|
|
|
@ -0,0 +1,139 @@
|
||||||
|
#pragma warning disable CS1998
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
using Cysharp.Threading.Tasks.Linq;
|
||||||
|
using FluentAssertions;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace NetCoreTests.Linq
|
||||||
|
{
|
||||||
|
public class MergeTest
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public async Task TwoSource()
|
||||||
|
{
|
||||||
|
var semaphore = new SemaphoreSlim(1, 1);
|
||||||
|
|
||||||
|
var a = UniTaskAsyncEnumerable.Create<string>(async (writer, _) =>
|
||||||
|
{
|
||||||
|
await UniTask.SwitchToThreadPool();
|
||||||
|
|
||||||
|
await semaphore.WaitAsync();
|
||||||
|
await writer.YieldAsync("A1");
|
||||||
|
semaphore.Release();
|
||||||
|
|
||||||
|
await semaphore.WaitAsync();
|
||||||
|
await writer.YieldAsync("A2");
|
||||||
|
semaphore.Release();
|
||||||
|
});
|
||||||
|
|
||||||
|
var b = UniTaskAsyncEnumerable.Create<string>(async (writer, _) =>
|
||||||
|
{
|
||||||
|
await UniTask.SwitchToThreadPool();
|
||||||
|
|
||||||
|
await semaphore.WaitAsync();
|
||||||
|
await writer.YieldAsync("B1");
|
||||||
|
await writer.YieldAsync("B2");
|
||||||
|
semaphore.Release();
|
||||||
|
|
||||||
|
await semaphore.WaitAsync();
|
||||||
|
await writer.YieldAsync("B3");
|
||||||
|
semaphore.Release();
|
||||||
|
});
|
||||||
|
|
||||||
|
var result = await a.Merge(b).ToArrayAsync();
|
||||||
|
result.Should().Equal("A1", "B1", "B2", "A2", "B3");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ThreeSource()
|
||||||
|
{
|
||||||
|
var semaphore = new SemaphoreSlim(0, 1);
|
||||||
|
|
||||||
|
var a = UniTaskAsyncEnumerable.Create<string>(async (writer, _) =>
|
||||||
|
{
|
||||||
|
await UniTask.SwitchToThreadPool();
|
||||||
|
|
||||||
|
await semaphore.WaitAsync();
|
||||||
|
await writer.YieldAsync("A1");
|
||||||
|
semaphore.Release();
|
||||||
|
|
||||||
|
await semaphore.WaitAsync();
|
||||||
|
await writer.YieldAsync("A2");
|
||||||
|
semaphore.Release();
|
||||||
|
});
|
||||||
|
|
||||||
|
var b = UniTaskAsyncEnumerable.Create<string>(async (writer, _) =>
|
||||||
|
{
|
||||||
|
await UniTask.SwitchToThreadPool();
|
||||||
|
|
||||||
|
await semaphore.WaitAsync();
|
||||||
|
await writer.YieldAsync("B1");
|
||||||
|
await writer.YieldAsync("B2");
|
||||||
|
semaphore.Release();
|
||||||
|
|
||||||
|
await semaphore.WaitAsync();
|
||||||
|
await writer.YieldAsync("B3");
|
||||||
|
semaphore.Release();
|
||||||
|
});
|
||||||
|
|
||||||
|
var c = UniTaskAsyncEnumerable.Create<string>(async (writer, _) =>
|
||||||
|
{
|
||||||
|
await UniTask.SwitchToThreadPool();
|
||||||
|
|
||||||
|
await writer.YieldAsync("C1");
|
||||||
|
semaphore.Release();
|
||||||
|
});
|
||||||
|
|
||||||
|
var result = await a.Merge(b, c).ToArrayAsync();
|
||||||
|
result.Should().Equal("C1", "A1", "B1", "B2", "A2", "B3");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Throw()
|
||||||
|
{
|
||||||
|
var a = UniTaskAsyncEnumerable.Create<string>(async (writer, _) =>
|
||||||
|
{
|
||||||
|
await writer.YieldAsync("A1");
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
var b = UniTaskAsyncEnumerable.Create<string>(async (writer, _) =>
|
||||||
|
{
|
||||||
|
throw new UniTaskTestException();
|
||||||
|
});
|
||||||
|
|
||||||
|
var enumerator = a.Merge(b).GetAsyncEnumerator();
|
||||||
|
(await enumerator.MoveNextAsync()).Should().Be(true);
|
||||||
|
enumerator.Current.Should().Be("A1");
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<UniTaskTestException>(async () => await enumerator.MoveNextAsync());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Cancel()
|
||||||
|
{
|
||||||
|
var cts = new CancellationTokenSource();
|
||||||
|
|
||||||
|
var a = UniTaskAsyncEnumerable.Create<string>(async (writer, _) =>
|
||||||
|
{
|
||||||
|
await writer.YieldAsync("A1");
|
||||||
|
});
|
||||||
|
|
||||||
|
var b = UniTaskAsyncEnumerable.Create<string>(async (writer, _) =>
|
||||||
|
{
|
||||||
|
await writer.YieldAsync("B1");
|
||||||
|
});
|
||||||
|
|
||||||
|
var enumerator = a.Merge(b).GetAsyncEnumerator(cts.Token);
|
||||||
|
(await enumerator.MoveNextAsync()).Should().Be(true);
|
||||||
|
enumerator.Current.Should().Be("A1");
|
||||||
|
|
||||||
|
cts.Cancel();
|
||||||
|
await Assert.ThrowsAsync<OperationCanceledException>(async () => await enumerator.MoveNextAsync());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
#pragma warning disable CS1998
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace NetCoreTests
|
||||||
|
{
|
||||||
|
public class TaskExtensionsTest
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public async Task PropagateException()
|
||||||
|
{
|
||||||
|
await Assert.ThrowsAsync<InvalidOperationException>(async () =>
|
||||||
|
{
|
||||||
|
await ThrowAsync().AsUniTask();
|
||||||
|
});
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<InvalidOperationException>(async () =>
|
||||||
|
{
|
||||||
|
await ThrowOrValueAsync().AsUniTask();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task PropagateExceptionWhenAll()
|
||||||
|
{
|
||||||
|
await Assert.ThrowsAsync<InvalidOperationException>(async () =>
|
||||||
|
{
|
||||||
|
await Task.WhenAll(ThrowAsync(), ThrowAsync()).AsUniTask();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async Task ThrowAsync()
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
async Task<int> ThrowOrValueAsync()
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
|
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
using FluentAssertions;
|
||||||
|
using NetCoreTests.Linq;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace NetCoreTests
|
||||||
|
{
|
||||||
|
public class AutoResetUniTaskCompletionSourceTest
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public async Task SetResultAfterReturn()
|
||||||
|
{
|
||||||
|
var source1 = AutoResetUniTaskCompletionSource.Create();
|
||||||
|
source1.TrySetResult();
|
||||||
|
await source1.Task;
|
||||||
|
|
||||||
|
source1.TrySetResult().Should().BeFalse();
|
||||||
|
|
||||||
|
var source2 = AutoResetUniTaskCompletionSource.Create();
|
||||||
|
source2.TrySetResult();
|
||||||
|
await source2.Task;
|
||||||
|
|
||||||
|
source2.TrySetResult().Should().BeFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task SetCancelAfterReturn()
|
||||||
|
{
|
||||||
|
var source = AutoResetUniTaskCompletionSource.Create();
|
||||||
|
source.TrySetResult();
|
||||||
|
await source.Task;
|
||||||
|
|
||||||
|
source.TrySetCanceled().Should().BeFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task SetExceptionAfterReturn()
|
||||||
|
{
|
||||||
|
var source = AutoResetUniTaskCompletionSource.Create();
|
||||||
|
source.TrySetResult();
|
||||||
|
await source.Task;
|
||||||
|
|
||||||
|
source.TrySetException(new UniTaskTestException()).Should().BeFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task SetResultWithValueAfterReturn()
|
||||||
|
{
|
||||||
|
var source1 = AutoResetUniTaskCompletionSource<int>.Create();
|
||||||
|
source1.TrySetResult(100);
|
||||||
|
(await source1.Task).Should().Be(100);
|
||||||
|
|
||||||
|
source1.TrySetResult(100).Should().BeFalse();
|
||||||
|
|
||||||
|
var source2 = AutoResetUniTaskCompletionSource.Create();
|
||||||
|
source2.TrySetResult();
|
||||||
|
await source2.Task;
|
||||||
|
source2.TrySetResult().Should().BeFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task SetCancelWithValueAfterReturn()
|
||||||
|
{
|
||||||
|
var source = AutoResetUniTaskCompletionSource<int>.Create();
|
||||||
|
source.TrySetResult(100);
|
||||||
|
(await source.Task).Should().Be(100);
|
||||||
|
source.TrySetCanceled().Should().BeFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task SetExceptionWithValueAfterReturn()
|
||||||
|
{
|
||||||
|
var source = AutoResetUniTaskCompletionSource<int>.Create();
|
||||||
|
source.TrySetResult(100);
|
||||||
|
(await source.Task).Should().Be(100);
|
||||||
|
source.TrySetException(new UniTaskTestException()).Should().BeFalse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
using FluentAssertions;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace NetCoreTests
|
||||||
|
{
|
||||||
|
public class WhenEachTest
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public async Task Each()
|
||||||
|
{
|
||||||
|
var a = Delay(1, 3000);
|
||||||
|
var b = Delay(2, 1000);
|
||||||
|
var c = Delay(3, 2000);
|
||||||
|
|
||||||
|
var l = new List<int>();
|
||||||
|
await foreach (var item in UniTask.WhenEach(a, b, c))
|
||||||
|
{
|
||||||
|
l.Add(item.Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
l.Should().Equal(2, 3, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Error()
|
||||||
|
{
|
||||||
|
var a = Delay2(1, 3000);
|
||||||
|
var b = Delay2(2, 1000);
|
||||||
|
var c = Delay2(3, 2000);
|
||||||
|
|
||||||
|
var l = new List<WhenEachResult<int>>();
|
||||||
|
await foreach (var item in UniTask.WhenEach(a, b, c))
|
||||||
|
{
|
||||||
|
l.Add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
l[0].IsCompletedSuccessfully.Should().BeTrue();
|
||||||
|
l[0].IsFaulted.Should().BeFalse();
|
||||||
|
l[0].Result.Should().Be(2);
|
||||||
|
|
||||||
|
l[1].IsCompletedSuccessfully.Should().BeFalse();
|
||||||
|
l[1].IsFaulted.Should().BeTrue();
|
||||||
|
l[1].Exception.Message.Should().Be("ERROR");
|
||||||
|
|
||||||
|
l[2].IsCompletedSuccessfully.Should().BeTrue();
|
||||||
|
l[2].IsFaulted.Should().BeFalse();
|
||||||
|
l[2].Result.Should().Be(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
async UniTask<int> Delay(int id, int sleep)
|
||||||
|
{
|
||||||
|
await Task.Delay(sleep);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
async UniTask<int> Delay2(int id, int sleep)
|
||||||
|
{
|
||||||
|
await Task.Delay(sleep);
|
||||||
|
if (id == 3) throw new Exception("ERROR");
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.ExceptionServices;
|
using System.Runtime.ExceptionServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using UnityEngine.AddressableAssets;
|
||||||
using UnityEngine.ResourceManagement.AsyncOperations;
|
using UnityEngine.ResourceManagement.AsyncOperations;
|
||||||
|
|
||||||
namespace Cysharp.Threading.Tasks
|
namespace Cysharp.Threading.Tasks
|
||||||
|
@ -20,12 +21,12 @@ namespace Cysharp.Threading.Tasks
|
||||||
return ToUniTask(handle).GetAwaiter();
|
return ToUniTask(handle).GetAwaiter();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask WithCancellation(this AsyncOperationHandle handle, CancellationToken cancellationToken)
|
public static UniTask WithCancellation(this AsyncOperationHandle handle, CancellationToken cancellationToken, bool cancelImmediately = false, bool autoReleaseWhenCanceled = false)
|
||||||
{
|
{
|
||||||
return ToUniTask(handle, cancellationToken: cancellationToken);
|
return ToUniTask(handle, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately, autoReleaseWhenCanceled: autoReleaseWhenCanceled);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask ToUniTask(this AsyncOperationHandle handle, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask ToUniTask(this AsyncOperationHandle handle, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false, bool autoReleaseWhenCanceled = false)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled(cancellationToken);
|
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled(cancellationToken);
|
||||||
|
|
||||||
|
@ -44,7 +45,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
return UniTask.CompletedTask;
|
return UniTask.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new UniTask(AsyncOperationHandleConfiguredSource.Create(handle, timing, progress, cancellationToken, out var token), token);
|
return new UniTask(AsyncOperationHandleConfiguredSource.Create(handle, timing, progress, cancellationToken, cancelImmediately, autoReleaseWhenCanceled, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct AsyncOperationHandleAwaiter : ICriticalNotifyCompletion
|
public struct AsyncOperationHandleAwaiter : ICriticalNotifyCompletion
|
||||||
|
@ -103,20 +104,23 @@ namespace Cysharp.Threading.Tasks
|
||||||
TaskPool.RegisterSizeGetter(typeof(AsyncOperationHandleConfiguredSource), () => pool.Size);
|
TaskPool.RegisterSizeGetter(typeof(AsyncOperationHandleConfiguredSource), () => pool.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly Action<AsyncOperationHandle> continuationAction;
|
readonly Action<AsyncOperationHandle> completedCallback;
|
||||||
AsyncOperationHandle handle;
|
AsyncOperationHandle handle;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
IProgress<float> progress;
|
IProgress<float> progress;
|
||||||
|
bool autoReleaseWhenCanceled;
|
||||||
|
bool cancelImmediately;
|
||||||
bool completed;
|
bool completed;
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<AsyncUnit> core;
|
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||||
|
|
||||||
AsyncOperationHandleConfiguredSource()
|
AsyncOperationHandleConfiguredSource()
|
||||||
{
|
{
|
||||||
continuationAction = Continuation;
|
completedCallback = HandleCompleted;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource Create(AsyncOperationHandle handle, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource Create(AsyncOperationHandle handle, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, bool cancelImmediately, bool autoReleaseWhenCanceled, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
@ -131,31 +135,52 @@ namespace Cysharp.Threading.Tasks
|
||||||
result.handle = handle;
|
result.handle = handle;
|
||||||
result.progress = progress;
|
result.progress = progress;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.cancelImmediately = cancelImmediately;
|
||||||
|
result.autoReleaseWhenCanceled = autoReleaseWhenCanceled;
|
||||||
result.completed = false;
|
result.completed = false;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var promise = (AsyncOperationHandleConfiguredSource)state;
|
||||||
|
if (promise.autoReleaseWhenCanceled && promise.handle.IsValid())
|
||||||
|
{
|
||||||
|
Addressables.Release(promise.handle);
|
||||||
|
}
|
||||||
|
promise.core.TrySetCanceled(promise.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
PlayerLoopHelper.AddAction(timing, result);
|
PlayerLoopHelper.AddAction(timing, result);
|
||||||
|
|
||||||
handle.Completed += result.continuationAction;
|
handle.Completed += result.completedCallback;
|
||||||
|
|
||||||
token = result.core.Version;
|
token = result.core.Version;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Continuation(AsyncOperationHandle _)
|
void HandleCompleted(AsyncOperationHandle _)
|
||||||
{
|
{
|
||||||
handle.Completed -= continuationAction;
|
if (handle.IsValid())
|
||||||
|
{
|
||||||
|
handle.Completed -= completedCallback;
|
||||||
|
}
|
||||||
|
|
||||||
if (completed)
|
if (completed)
|
||||||
{
|
{
|
||||||
TryReturn();
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
completed = true;
|
completed = true;
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
if (autoReleaseWhenCanceled && handle.IsValid())
|
||||||
|
{
|
||||||
|
Addressables.Release(handle);
|
||||||
|
}
|
||||||
core.TrySetCanceled(cancellationToken);
|
core.TrySetCanceled(cancellationToken);
|
||||||
}
|
}
|
||||||
else if (handle.Status == AsyncOperationStatus.Failed)
|
else if (handle.Status == AsyncOperationStatus.Failed)
|
||||||
|
@ -167,12 +192,25 @@ namespace Cysharp.Threading.Tasks
|
||||||
core.TrySetResult(AsyncUnit.Default);
|
core.TrySetResult(AsyncUnit.Default);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void GetResult(short token)
|
public void GetResult(short token)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
core.GetResult(token);
|
core.GetResult(token);
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public UniTaskStatus GetStatus(short token)
|
public UniTaskStatus GetStatus(short token)
|
||||||
{
|
{
|
||||||
|
@ -193,20 +231,23 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
if (completed)
|
if (completed)
|
||||||
{
|
{
|
||||||
TryReturn();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
completed = true;
|
completed = true;
|
||||||
|
if (autoReleaseWhenCanceled && handle.IsValid())
|
||||||
|
{
|
||||||
|
Addressables.Release(handle);
|
||||||
|
}
|
||||||
core.TrySetCanceled(cancellationToken);
|
core.TrySetCanceled(cancellationToken);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (progress != null && handle.IsValid())
|
if (progress != null && handle.IsValid())
|
||||||
{
|
{
|
||||||
progress.Report(handle.PercentComplete);
|
progress.Report(handle.GetDownloadStatus().Percent);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -219,6 +260,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
handle = default;
|
handle = default;
|
||||||
progress = default;
|
progress = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -232,12 +274,12 @@ namespace Cysharp.Threading.Tasks
|
||||||
return ToUniTask(handle).GetAwaiter();
|
return ToUniTask(handle).GetAwaiter();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask<T> WithCancellation<T>(this AsyncOperationHandle<T> handle, CancellationToken cancellationToken)
|
public static UniTask<T> WithCancellation<T>(this AsyncOperationHandle<T> handle, CancellationToken cancellationToken, bool cancelImmediately = false, bool autoReleaseWhenCanceled = false)
|
||||||
{
|
{
|
||||||
return ToUniTask(handle, cancellationToken: cancellationToken);
|
return ToUniTask(handle, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately, autoReleaseWhenCanceled: autoReleaseWhenCanceled);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask<T> ToUniTask<T>(this AsyncOperationHandle<T> handle, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask<T> ToUniTask<T>(this AsyncOperationHandle<T> handle, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false, bool autoReleaseWhenCanceled = false)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<T>(cancellationToken);
|
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<T>(cancellationToken);
|
||||||
|
|
||||||
|
@ -255,7 +297,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
return UniTask.FromResult(handle.Result);
|
return UniTask.FromResult(handle.Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new UniTask<T>(AsyncOperationHandleConfiguredSource<T>.Create(handle, timing, progress, cancellationToken, out var token), token);
|
return new UniTask<T>(AsyncOperationHandleConfiguredSource<T>.Create(handle, timing, progress, cancellationToken, cancelImmediately, autoReleaseWhenCanceled, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class AsyncOperationHandleConfiguredSource<T> : IUniTaskSource<T>, IPlayerLoopItem, ITaskPoolNode<AsyncOperationHandleConfiguredSource<T>>
|
sealed class AsyncOperationHandleConfiguredSource<T> : IUniTaskSource<T>, IPlayerLoopItem, ITaskPoolNode<AsyncOperationHandleConfiguredSource<T>>
|
||||||
|
@ -269,20 +311,23 @@ namespace Cysharp.Threading.Tasks
|
||||||
TaskPool.RegisterSizeGetter(typeof(AsyncOperationHandleConfiguredSource<T>), () => pool.Size);
|
TaskPool.RegisterSizeGetter(typeof(AsyncOperationHandleConfiguredSource<T>), () => pool.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly Action<AsyncOperationHandle<T>> continuationAction;
|
readonly Action<AsyncOperationHandle<T>> completedCallback;
|
||||||
AsyncOperationHandle<T> handle;
|
AsyncOperationHandle<T> handle;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
IProgress<float> progress;
|
IProgress<float> progress;
|
||||||
|
bool autoReleaseWhenCanceled;
|
||||||
|
bool cancelImmediately;
|
||||||
bool completed;
|
bool completed;
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<T> core;
|
UniTaskCompletionSourceCore<T> core;
|
||||||
|
|
||||||
AsyncOperationHandleConfiguredSource()
|
AsyncOperationHandleConfiguredSource()
|
||||||
{
|
{
|
||||||
continuationAction = Continuation;
|
completedCallback = HandleCompleted;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource<T> Create(AsyncOperationHandle<T> handle, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource<T> Create(AsyncOperationHandle<T> handle, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, bool cancelImmediately, bool autoReleaseWhenCanceled, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
@ -298,30 +343,50 @@ namespace Cysharp.Threading.Tasks
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
result.completed = false;
|
result.completed = false;
|
||||||
result.progress = progress;
|
result.progress = progress;
|
||||||
|
result.autoReleaseWhenCanceled = autoReleaseWhenCanceled;
|
||||||
|
result.cancelImmediately = cancelImmediately;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var promise = (AsyncOperationHandleConfiguredSource<T>)state;
|
||||||
|
if (promise.autoReleaseWhenCanceled && promise.handle.IsValid())
|
||||||
|
{
|
||||||
|
Addressables.Release(promise.handle);
|
||||||
|
}
|
||||||
|
promise.core.TrySetCanceled(promise.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
PlayerLoopHelper.AddAction(timing, result);
|
PlayerLoopHelper.AddAction(timing, result);
|
||||||
|
|
||||||
handle.Completed += result.continuationAction;
|
handle.Completed += result.completedCallback;
|
||||||
|
|
||||||
token = result.core.Version;
|
token = result.core.Version;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Continuation(AsyncOperationHandle<T> argHandle)
|
void HandleCompleted(AsyncOperationHandle<T> argHandle)
|
||||||
{
|
{
|
||||||
handle.Completed -= continuationAction;
|
if (handle.IsValid())
|
||||||
|
{
|
||||||
|
handle.Completed -= completedCallback;
|
||||||
|
}
|
||||||
|
|
||||||
if (completed)
|
if (completed)
|
||||||
{
|
{
|
||||||
TryReturn();
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
completed = true;
|
completed = true;
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
if (autoReleaseWhenCanceled && handle.IsValid())
|
||||||
|
{
|
||||||
|
Addressables.Release(handle);
|
||||||
|
}
|
||||||
core.TrySetCanceled(cancellationToken);
|
core.TrySetCanceled(cancellationToken);
|
||||||
}
|
}
|
||||||
else if (argHandle.Status == AsyncOperationStatus.Failed)
|
else if (argHandle.Status == AsyncOperationStatus.Failed)
|
||||||
|
@ -333,12 +398,25 @@ namespace Cysharp.Threading.Tasks
|
||||||
core.TrySetResult(argHandle.Result);
|
core.TrySetResult(argHandle.Result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public T GetResult(short token)
|
public T GetResult(short token)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
return core.GetResult(token);
|
return core.GetResult(token);
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void IUniTaskSource.GetResult(short token)
|
void IUniTaskSource.GetResult(short token)
|
||||||
{
|
{
|
||||||
|
@ -364,20 +442,23 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
if (completed)
|
if (completed)
|
||||||
{
|
{
|
||||||
TryReturn();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
completed = true;
|
completed = true;
|
||||||
|
if (autoReleaseWhenCanceled && handle.IsValid())
|
||||||
|
{
|
||||||
|
Addressables.Release(handle);
|
||||||
|
}
|
||||||
core.TrySetCanceled(cancellationToken);
|
core.TrySetCanceled(cancellationToken);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (progress != null && handle.IsValid())
|
if (progress != null && handle.IsValid())
|
||||||
{
|
{
|
||||||
progress.Report(handle.PercentComplete);
|
progress.Report(handle.GetDownloadStatus().Percent);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -390,6 +471,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
handle = default;
|
handle = default;
|
||||||
progress = default;
|
progress = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
"name": "UniTask.Addressables",
|
"name": "UniTask.Addressables",
|
||||||
"references": [
|
"references": [
|
||||||
"UniTask",
|
"UniTask",
|
||||||
"Unity.ResourceManager"
|
"Unity.ResourceManager",
|
||||||
|
"Unity.Addressables"
|
||||||
],
|
],
|
||||||
"includePlatforms": [],
|
"includePlatforms": [],
|
||||||
"excludePlatforms": [],
|
"excludePlatforms": [],
|
||||||
|
|
|
@ -144,22 +144,20 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly TweenCallback onCompleteCallbackDelegate;
|
readonly TweenCallback onCompleteCallbackDelegate;
|
||||||
readonly TweenCallback onUpdateDelegate;
|
|
||||||
|
|
||||||
Tween tween;
|
Tween tween;
|
||||||
TweenCancelBehaviour cancelBehaviour;
|
TweenCancelBehaviour cancelBehaviour;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationRegistration;
|
||||||
CallbackType callbackType;
|
CallbackType callbackType;
|
||||||
bool canceled;
|
bool canceled;
|
||||||
|
|
||||||
TweenCallback originalUpdateAction;
|
|
||||||
TweenCallback originalCompleteAction;
|
TweenCallback originalCompleteAction;
|
||||||
UniTaskCompletionSourceCore<AsyncUnit> core;
|
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||||
|
|
||||||
TweenConfiguredSource()
|
TweenConfiguredSource()
|
||||||
{
|
{
|
||||||
onCompleteCallbackDelegate = OnCompleteCallbackDelegate;
|
onCompleteCallbackDelegate = OnCompleteCallbackDelegate;
|
||||||
onUpdateDelegate = OnUpdate;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource Create(Tween tween, TweenCancelBehaviour cancelBehaviour, CancellationToken cancellationToken, CallbackType callbackType, out short token)
|
public static IUniTaskSource Create(Tween tween, TweenCancelBehaviour cancelBehaviour, CancellationToken cancellationToken, CallbackType callbackType, out short token)
|
||||||
|
@ -179,17 +177,8 @@ namespace Cysharp.Threading.Tasks
|
||||||
result.cancelBehaviour = cancelBehaviour;
|
result.cancelBehaviour = cancelBehaviour;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
result.callbackType = callbackType;
|
result.callbackType = callbackType;
|
||||||
|
|
||||||
result.originalUpdateAction = tween.onUpdate;
|
|
||||||
result.canceled = false;
|
result.canceled = false;
|
||||||
|
|
||||||
if (result.originalUpdateAction == result.onUpdateDelegate)
|
|
||||||
{
|
|
||||||
result.originalUpdateAction = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
tween.onUpdate = result.onUpdateDelegate;
|
|
||||||
|
|
||||||
switch (callbackType)
|
switch (callbackType)
|
||||||
{
|
{
|
||||||
case CallbackType.Kill:
|
case CallbackType.Kill:
|
||||||
|
@ -225,6 +214,50 @@ namespace Cysharp.Threading.Tasks
|
||||||
result.originalCompleteAction = null;
|
result.originalCompleteAction = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(x =>
|
||||||
|
{
|
||||||
|
var source = (TweenConfiguredSource)x;
|
||||||
|
switch (source.cancelBehaviour)
|
||||||
|
{
|
||||||
|
case TweenCancelBehaviour.Kill:
|
||||||
|
default:
|
||||||
|
source.tween.Kill(false);
|
||||||
|
break;
|
||||||
|
case TweenCancelBehaviour.KillAndCancelAwait:
|
||||||
|
source.canceled = true;
|
||||||
|
source.tween.Kill(false);
|
||||||
|
break;
|
||||||
|
case TweenCancelBehaviour.KillWithCompleteCallback:
|
||||||
|
source.tween.Kill(true);
|
||||||
|
break;
|
||||||
|
case TweenCancelBehaviour.KillWithCompleteCallbackAndCancelAwait:
|
||||||
|
source.canceled = true;
|
||||||
|
source.tween.Kill(true);
|
||||||
|
break;
|
||||||
|
case TweenCancelBehaviour.Complete:
|
||||||
|
source.tween.Complete(false);
|
||||||
|
break;
|
||||||
|
case TweenCancelBehaviour.CompleteAndCancelAwait:
|
||||||
|
source.canceled = true;
|
||||||
|
source.tween.Complete(false);
|
||||||
|
break;
|
||||||
|
case TweenCancelBehaviour.CompleteWithSequenceCallback:
|
||||||
|
source.tween.Complete(true);
|
||||||
|
break;
|
||||||
|
case TweenCancelBehaviour.CompleteWithSequenceCallbackAndCancelAwait:
|
||||||
|
source.canceled = true;
|
||||||
|
source.tween.Complete(true);
|
||||||
|
break;
|
||||||
|
case TweenCancelBehaviour.CancelAwait:
|
||||||
|
source.RestoreOriginalCallback();
|
||||||
|
source.core.TrySetCanceled(source.cancellationToken);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
token = result.core.Version;
|
token = result.core.Version;
|
||||||
|
@ -255,77 +288,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnUpdate()
|
|
||||||
{
|
|
||||||
originalUpdateAction?.Invoke();
|
|
||||||
|
|
||||||
if (!cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (this.cancelBehaviour)
|
|
||||||
{
|
|
||||||
case TweenCancelBehaviour.Kill:
|
|
||||||
default:
|
|
||||||
this.tween.Kill(false);
|
|
||||||
break;
|
|
||||||
case TweenCancelBehaviour.KillAndCancelAwait:
|
|
||||||
this.canceled = true;
|
|
||||||
this.tween.Kill(false);
|
|
||||||
break;
|
|
||||||
case TweenCancelBehaviour.KillWithCompleteCallback:
|
|
||||||
this.tween.Kill(true);
|
|
||||||
break;
|
|
||||||
case TweenCancelBehaviour.KillWithCompleteCallbackAndCancelAwait:
|
|
||||||
this.canceled = true;
|
|
||||||
this.tween.Kill(true);
|
|
||||||
break;
|
|
||||||
case TweenCancelBehaviour.Complete:
|
|
||||||
this.tween.Complete(false);
|
|
||||||
break;
|
|
||||||
case TweenCancelBehaviour.CompleteAndCancelAwait:
|
|
||||||
this.canceled = true;
|
|
||||||
this.tween.Complete(false);
|
|
||||||
break;
|
|
||||||
case TweenCancelBehaviour.CompleteWithSequenceCallback:
|
|
||||||
this.tween.Complete(true);
|
|
||||||
break;
|
|
||||||
case TweenCancelBehaviour.CompleteWithSequenceCallbackAndCancelAwait:
|
|
||||||
this.canceled = true;
|
|
||||||
this.tween.Complete(true);
|
|
||||||
break;
|
|
||||||
case TweenCancelBehaviour.CancelAwait:
|
|
||||||
// restore to original callback
|
|
||||||
switch (callbackType)
|
|
||||||
{
|
|
||||||
case CallbackType.Kill:
|
|
||||||
tween.onKill = originalCompleteAction;
|
|
||||||
break;
|
|
||||||
case CallbackType.Complete:
|
|
||||||
tween.onComplete = originalCompleteAction;
|
|
||||||
break;
|
|
||||||
case CallbackType.Pause:
|
|
||||||
tween.onPause = originalCompleteAction;
|
|
||||||
break;
|
|
||||||
case CallbackType.Play:
|
|
||||||
tween.onPlay = originalCompleteAction;
|
|
||||||
break;
|
|
||||||
case CallbackType.Rewind:
|
|
||||||
tween.onRewind = originalCompleteAction;
|
|
||||||
break;
|
|
||||||
case CallbackType.StepComplete:
|
|
||||||
tween.onStepComplete = originalCompleteAction;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.core.TrySetCanceled(this.cancellationToken);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void DoCancelBeforeCreate(Tween tween, TweenCancelBehaviour tweenCancelBehaviour)
|
static void DoCancelBeforeCreate(Tween tween, TweenCancelBehaviour tweenCancelBehaviour)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -392,8 +354,18 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
core.Reset();
|
core.Reset();
|
||||||
tween.onUpdate = originalUpdateAction;
|
cancellationRegistration.Dispose();
|
||||||
|
|
||||||
|
RestoreOriginalCallback();
|
||||||
|
|
||||||
|
tween = default;
|
||||||
|
cancellationToken = default;
|
||||||
|
originalCompleteAction = default;
|
||||||
|
return pool.TryPush(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RestoreOriginalCallback()
|
||||||
|
{
|
||||||
switch (callbackType)
|
switch (callbackType)
|
||||||
{
|
{
|
||||||
case CallbackType.Kill:
|
case CallbackType.Kill:
|
||||||
|
@ -417,12 +389,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
tween = default;
|
|
||||||
cancellationToken = default;
|
|
||||||
originalUpdateAction = default;
|
|
||||||
originalCompleteAction = default;
|
|
||||||
return pool.TryPush(this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,11 @@
|
||||||
"name": "com.unity.textmeshpro",
|
"name": "com.unity.textmeshpro",
|
||||||
"expression": "",
|
"expression": "",
|
||||||
"define": "UNITASK_TEXTMESHPRO_SUPPORT"
|
"define": "UNITASK_TEXTMESHPRO_SUPPORT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "com.unity.ugui",
|
||||||
|
"expression": "2.0.0",
|
||||||
|
"define": "UNITASK_TEXTMESHPRO_SUPPORT"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"noEngineReferences": false
|
"noEngineReferences": false
|
||||||
|
|
|
@ -1,4 +1,9 @@
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
|
#pragma warning disable CS0108
|
||||||
|
|
||||||
|
#if (UNITASK_NETCORE && !NETSTANDARD2_0) || UNITY_2022_3_OR_NEWER
|
||||||
|
#define SUPPORT_VALUETASK
|
||||||
|
#endif
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
@ -19,9 +24,8 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
// similar as IValueTaskSource
|
// similar as IValueTaskSource
|
||||||
public interface IUniTaskSource
|
public interface IUniTaskSource
|
||||||
#if !UNITY_2018_3_OR_NEWER && !NETSTANDARD2_0
|
#if SUPPORT_VALUETASK
|
||||||
: System.Threading.Tasks.Sources.IValueTaskSource
|
: System.Threading.Tasks.Sources.IValueTaskSource
|
||||||
#pragma warning disable CS0108
|
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
UniTaskStatus GetStatus(short token);
|
UniTaskStatus GetStatus(short token);
|
||||||
|
@ -30,8 +34,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
UniTaskStatus UnsafeGetStatus(); // only for debug use.
|
UniTaskStatus UnsafeGetStatus(); // only for debug use.
|
||||||
|
|
||||||
#if !UNITY_2018_3_OR_NEWER && !NETSTANDARD2_0
|
#if SUPPORT_VALUETASK
|
||||||
#pragma warning restore CS0108
|
|
||||||
|
|
||||||
System.Threading.Tasks.Sources.ValueTaskSourceStatus System.Threading.Tasks.Sources.IValueTaskSource.GetStatus(short token)
|
System.Threading.Tasks.Sources.ValueTaskSourceStatus System.Threading.Tasks.Sources.IValueTaskSource.GetStatus(short token)
|
||||||
{
|
{
|
||||||
|
@ -53,13 +56,13 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IUniTaskSource<out T> : IUniTaskSource
|
public interface IUniTaskSource<out T> : IUniTaskSource
|
||||||
#if !UNITY_2018_3_OR_NEWER && !NETSTANDARD2_0
|
#if SUPPORT_VALUETASK
|
||||||
, System.Threading.Tasks.Sources.IValueTaskSource<T>
|
, System.Threading.Tasks.Sources.IValueTaskSource<T>
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
new T GetResult(short token);
|
new T GetResult(short token);
|
||||||
|
|
||||||
#if !UNITY_2018_3_OR_NEWER && !NETSTANDARD2_0
|
#if SUPPORT_VALUETASK
|
||||||
|
|
||||||
new public UniTaskStatus GetStatus(short token)
|
new public UniTaskStatus GetStatus(short token)
|
||||||
{
|
{
|
||||||
|
|
|
@ -39,7 +39,7 @@ namespace Cysharp.Threading.Tasks.Internal
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
public static void ThrowArgumentException<T>(string message)
|
public static void ThrowArgumentException(string message)
|
||||||
{
|
{
|
||||||
throw new ArgumentException(message);
|
throw new ArgumentException(message);
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
public UniTask DisposeAsync()
|
public UniTask DisposeAsync()
|
||||||
{
|
{
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
|
writer.Dispose();
|
||||||
return default;
|
return default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +128,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class AsyncWriter : IUniTaskSource, IAsyncWriter<T>
|
sealed class AsyncWriter : IUniTaskSource, IAsyncWriter<T>, IDisposable
|
||||||
{
|
{
|
||||||
readonly _Create enumerator;
|
readonly _Create enumerator;
|
||||||
|
|
||||||
|
@ -138,6 +139,15 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
this.enumerator = enumerator;
|
this.enumerator = enumerator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
var status = core.GetStatus(core.Version);
|
||||||
|
if (status == UniTaskStatus.Pending)
|
||||||
|
{
|
||||||
|
core.TrySetCanceled();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void GetResult(short token)
|
public void GetResult(short token)
|
||||||
{
|
{
|
||||||
core.GetResult(token);
|
core.GetResult(token);
|
||||||
|
|
|
@ -0,0 +1,234 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using Cysharp.Threading.Tasks.Internal;
|
||||||
|
|
||||||
|
namespace Cysharp.Threading.Tasks.Linq
|
||||||
|
{
|
||||||
|
public static partial class UniTaskAsyncEnumerable
|
||||||
|
{
|
||||||
|
public static IUniTaskAsyncEnumerable<T> Merge<T>(this IUniTaskAsyncEnumerable<T> first, IUniTaskAsyncEnumerable<T> second)
|
||||||
|
{
|
||||||
|
Error.ThrowArgumentNullException(first, nameof(first));
|
||||||
|
Error.ThrowArgumentNullException(second, nameof(second));
|
||||||
|
|
||||||
|
return new Merge<T>(new [] { first, second });
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IUniTaskAsyncEnumerable<T> Merge<T>(this IUniTaskAsyncEnumerable<T> first, IUniTaskAsyncEnumerable<T> second, IUniTaskAsyncEnumerable<T> third)
|
||||||
|
{
|
||||||
|
Error.ThrowArgumentNullException(first, nameof(first));
|
||||||
|
Error.ThrowArgumentNullException(second, nameof(second));
|
||||||
|
Error.ThrowArgumentNullException(third, nameof(third));
|
||||||
|
|
||||||
|
return new Merge<T>(new[] { first, second, third });
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IUniTaskAsyncEnumerable<T> Merge<T>(this IEnumerable<IUniTaskAsyncEnumerable<T>> sources)
|
||||||
|
{
|
||||||
|
return sources is IUniTaskAsyncEnumerable<T>[] array
|
||||||
|
? new Merge<T>(array)
|
||||||
|
: new Merge<T>(sources.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IUniTaskAsyncEnumerable<T> Merge<T>(params IUniTaskAsyncEnumerable<T>[] sources)
|
||||||
|
{
|
||||||
|
return new Merge<T>(sources);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal sealed class Merge<T> : IUniTaskAsyncEnumerable<T>
|
||||||
|
{
|
||||||
|
readonly IUniTaskAsyncEnumerable<T>[] sources;
|
||||||
|
|
||||||
|
public Merge(IUniTaskAsyncEnumerable<T>[] sources)
|
||||||
|
{
|
||||||
|
if (sources.Length <= 0)
|
||||||
|
{
|
||||||
|
Error.ThrowArgumentException("No source async enumerable to merge");
|
||||||
|
}
|
||||||
|
this.sources = sources;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
||||||
|
=> new _Merge(sources, cancellationToken);
|
||||||
|
|
||||||
|
enum MergeSourceState
|
||||||
|
{
|
||||||
|
Pending,
|
||||||
|
Running,
|
||||||
|
Completed,
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class _Merge : MoveNextSource, IUniTaskAsyncEnumerator<T>
|
||||||
|
{
|
||||||
|
static readonly Action<object> GetResultAtAction = GetResultAt;
|
||||||
|
|
||||||
|
readonly int length;
|
||||||
|
readonly IUniTaskAsyncEnumerator<T>[] enumerators;
|
||||||
|
readonly MergeSourceState[] states;
|
||||||
|
readonly Queue<(T, Exception, bool)> queuedResult = new Queue<(T, Exception, bool)>();
|
||||||
|
readonly CancellationToken cancellationToken;
|
||||||
|
|
||||||
|
int moveNextCompleted;
|
||||||
|
|
||||||
|
public T Current { get; private set; }
|
||||||
|
|
||||||
|
public _Merge(IUniTaskAsyncEnumerable<T>[] sources, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
this.cancellationToken = cancellationToken;
|
||||||
|
length = sources.Length;
|
||||||
|
states = ArrayPool<MergeSourceState>.Shared.Rent(length);
|
||||||
|
enumerators = ArrayPool<IUniTaskAsyncEnumerator<T>>.Shared.Rent(length);
|
||||||
|
for (var i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
enumerators[i] = sources[i].GetAsyncEnumerator(cancellationToken);
|
||||||
|
states[i] = (int)MergeSourceState.Pending;;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTask<bool> MoveNextAsync()
|
||||||
|
{
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
completionSource.Reset();
|
||||||
|
Interlocked.Exchange(ref moveNextCompleted, 0);
|
||||||
|
|
||||||
|
if (HasQueuedResult() && Interlocked.CompareExchange(ref moveNextCompleted, 1, 0) == 0)
|
||||||
|
{
|
||||||
|
(T, Exception, bool) value;
|
||||||
|
lock (states)
|
||||||
|
{
|
||||||
|
value = queuedResult.Dequeue();
|
||||||
|
}
|
||||||
|
var resultValue = value.Item1;
|
||||||
|
var exception = value.Item2;
|
||||||
|
var hasNext = value.Item3;
|
||||||
|
if (exception != null)
|
||||||
|
{
|
||||||
|
completionSource.TrySetException(exception);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Current = resultValue;
|
||||||
|
completionSource.TrySetResult(hasNext);
|
||||||
|
}
|
||||||
|
return new UniTask<bool>(this, completionSource.Version);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
lock (states)
|
||||||
|
{
|
||||||
|
if (states[i] == MergeSourceState.Pending)
|
||||||
|
{
|
||||||
|
states[i] = MergeSourceState.Running;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var awaiter = enumerators[i].MoveNextAsync().GetAwaiter();
|
||||||
|
if (awaiter.IsCompleted)
|
||||||
|
{
|
||||||
|
GetResultAt(i, awaiter);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
awaiter.SourceOnCompleted(GetResultAtAction, StateTuple.Create(this, i, awaiter));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new UniTask<bool>(this, completionSource.Version);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async UniTask DisposeAsync()
|
||||||
|
{
|
||||||
|
for (var i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
await enumerators[i].DisposeAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayPool<MergeSourceState>.Shared.Return(states, true);
|
||||||
|
ArrayPool<IUniTaskAsyncEnumerator<T>>.Shared.Return(enumerators, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GetResultAt(object state)
|
||||||
|
{
|
||||||
|
using (var tuple = (StateTuple<_Merge, int, UniTask<bool>.Awaiter>)state)
|
||||||
|
{
|
||||||
|
tuple.Item1.GetResultAt(tuple.Item2, tuple.Item3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetResultAt(int index, UniTask<bool>.Awaiter awaiter)
|
||||||
|
{
|
||||||
|
bool hasNext;
|
||||||
|
bool completedAll;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
hasNext = awaiter.GetResult();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (Interlocked.CompareExchange(ref moveNextCompleted, 1, 0) == 0)
|
||||||
|
{
|
||||||
|
completionSource.TrySetException(ex);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lock (states)
|
||||||
|
{
|
||||||
|
queuedResult.Enqueue((default, ex, default));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lock (states)
|
||||||
|
{
|
||||||
|
states[index] = hasNext ? MergeSourceState.Pending : MergeSourceState.Completed;
|
||||||
|
completedAll = !hasNext && IsCompletedAll();
|
||||||
|
}
|
||||||
|
if (hasNext || completedAll)
|
||||||
|
{
|
||||||
|
if (Interlocked.CompareExchange(ref moveNextCompleted, 1, 0) == 0)
|
||||||
|
{
|
||||||
|
Current = enumerators[index].Current;
|
||||||
|
completionSource.TrySetResult(!completedAll);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lock (states)
|
||||||
|
{
|
||||||
|
queuedResult.Enqueue((enumerators[index].Current, null, !completedAll));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HasQueuedResult()
|
||||||
|
{
|
||||||
|
lock (states)
|
||||||
|
{
|
||||||
|
return queuedResult.Count > 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsCompletedAll()
|
||||||
|
{
|
||||||
|
lock (states)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
if (states[i] != MergeSourceState.Completed)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: ca56812f160c45d0bacb4339819edf1a
|
||||||
|
timeCreated: 1694133666
|
|
@ -4,38 +4,50 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
{
|
{
|
||||||
public static partial class UniTaskAsyncEnumerable
|
public static partial class UniTaskAsyncEnumerable
|
||||||
{
|
{
|
||||||
public static IUniTaskAsyncEnumerable<AsyncUnit> EveryUpdate(PlayerLoopTiming updateTiming = PlayerLoopTiming.Update)
|
public static IUniTaskAsyncEnumerable<AsyncUnit> EveryUpdate(PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
return new EveryUpdate(updateTiming);
|
return new EveryUpdate(updateTiming, cancelImmediately);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class EveryUpdate : IUniTaskAsyncEnumerable<AsyncUnit>
|
internal class EveryUpdate : IUniTaskAsyncEnumerable<AsyncUnit>
|
||||||
{
|
{
|
||||||
readonly PlayerLoopTiming updateTiming;
|
readonly PlayerLoopTiming updateTiming;
|
||||||
|
readonly bool cancelImmediately;
|
||||||
|
|
||||||
public EveryUpdate(PlayerLoopTiming updateTiming)
|
public EveryUpdate(PlayerLoopTiming updateTiming, bool cancelImmediately)
|
||||||
{
|
{
|
||||||
this.updateTiming = updateTiming;
|
this.updateTiming = updateTiming;
|
||||||
|
this.cancelImmediately = cancelImmediately;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IUniTaskAsyncEnumerator<AsyncUnit> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
public IUniTaskAsyncEnumerator<AsyncUnit> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return new _EveryUpdate(updateTiming, cancellationToken);
|
return new _EveryUpdate(updateTiming, cancellationToken, cancelImmediately);
|
||||||
}
|
}
|
||||||
|
|
||||||
class _EveryUpdate : MoveNextSource, IUniTaskAsyncEnumerator<AsyncUnit>, IPlayerLoopItem
|
class _EveryUpdate : MoveNextSource, IUniTaskAsyncEnumerator<AsyncUnit>, IPlayerLoopItem
|
||||||
{
|
{
|
||||||
readonly PlayerLoopTiming updateTiming;
|
readonly PlayerLoopTiming updateTiming;
|
||||||
CancellationToken cancellationToken;
|
readonly CancellationToken cancellationToken;
|
||||||
|
readonly CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
|
||||||
bool disposed;
|
bool disposed;
|
||||||
|
|
||||||
public _EveryUpdate(PlayerLoopTiming updateTiming, CancellationToken cancellationToken)
|
public _EveryUpdate(PlayerLoopTiming updateTiming, CancellationToken cancellationToken, bool cancelImmediately)
|
||||||
{
|
{
|
||||||
this.updateTiming = updateTiming;
|
this.updateTiming = updateTiming;
|
||||||
this.cancellationToken = cancellationToken;
|
this.cancellationToken = cancellationToken;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var source = (_EveryUpdate)state;
|
||||||
|
source.completionSource.TrySetCanceled(source.cancellationToken);
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(this, 2);
|
TaskTracker.TrackActiveTask(this, 2);
|
||||||
PlayerLoopHelper.AddAction(updateTiming, this);
|
PlayerLoopHelper.AddAction(updateTiming, this);
|
||||||
}
|
}
|
||||||
|
@ -44,10 +56,14 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
|
|
||||||
public UniTask<bool> MoveNextAsync()
|
public UniTask<bool> MoveNextAsync()
|
||||||
{
|
{
|
||||||
// return false instead of throw
|
if (disposed) return CompletedTasks.False;
|
||||||
if (disposed || cancellationToken.IsCancellationRequested) return CompletedTasks.False;
|
|
||||||
|
|
||||||
completionSource.Reset();
|
completionSource.Reset();
|
||||||
|
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completionSource.TrySetCanceled(cancellationToken);
|
||||||
|
}
|
||||||
return new UniTask<bool>(this, completionSource.Version);
|
return new UniTask<bool>(this, completionSource.Version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,6 +71,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
{
|
{
|
||||||
if (!disposed)
|
if (!disposed)
|
||||||
{
|
{
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
disposed = true;
|
disposed = true;
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
}
|
}
|
||||||
|
@ -63,7 +80,13 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
|
|
||||||
public bool MoveNext()
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
if (disposed || cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completionSource.TrySetCanceled(cancellationToken);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (disposed)
|
||||||
{
|
{
|
||||||
completionSource.TrySetResult(false);
|
completionSource.TrySetResult(false);
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -7,7 +7,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
{
|
{
|
||||||
public static partial class UniTaskAsyncEnumerable
|
public static partial class UniTaskAsyncEnumerable
|
||||||
{
|
{
|
||||||
public static IUniTaskAsyncEnumerable<TProperty> EveryValueChanged<TTarget, TProperty>(TTarget target, Func<TTarget, TProperty> propertySelector, PlayerLoopTiming monitorTiming = PlayerLoopTiming.Update, IEqualityComparer<TProperty> equalityComparer = null)
|
public static IUniTaskAsyncEnumerable<TProperty> EveryValueChanged<TTarget, TProperty>(TTarget target, Func<TTarget, TProperty> propertySelector, PlayerLoopTiming monitorTiming = PlayerLoopTiming.Update, IEqualityComparer<TProperty> equalityComparer = null, bool cancelImmediately = false)
|
||||||
where TTarget : class
|
where TTarget : class
|
||||||
{
|
{
|
||||||
var unityObject = target as UnityEngine.Object;
|
var unityObject = target as UnityEngine.Object;
|
||||||
|
@ -15,11 +15,11 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
|
|
||||||
if (isUnityObject)
|
if (isUnityObject)
|
||||||
{
|
{
|
||||||
return new EveryValueChangedUnityObject<TTarget, TProperty>(target, propertySelector, equalityComparer ?? UnityEqualityComparer.GetDefault<TProperty>(), monitorTiming);
|
return new EveryValueChangedUnityObject<TTarget, TProperty>(target, propertySelector, equalityComparer ?? UnityEqualityComparer.GetDefault<TProperty>(), monitorTiming, cancelImmediately);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return new EveryValueChangedStandardObject<TTarget, TProperty>(target, propertySelector, equalityComparer ?? UnityEqualityComparer.GetDefault<TProperty>(), monitorTiming);
|
return new EveryValueChangedStandardObject<TTarget, TProperty>(target, propertySelector, equalityComparer ?? UnityEqualityComparer.GetDefault<TProperty>(), monitorTiming, cancelImmediately);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,18 +30,20 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
readonly Func<TTarget, TProperty> propertySelector;
|
readonly Func<TTarget, TProperty> propertySelector;
|
||||||
readonly IEqualityComparer<TProperty> equalityComparer;
|
readonly IEqualityComparer<TProperty> equalityComparer;
|
||||||
readonly PlayerLoopTiming monitorTiming;
|
readonly PlayerLoopTiming monitorTiming;
|
||||||
|
readonly bool cancelImmediately;
|
||||||
|
|
||||||
public EveryValueChangedUnityObject(TTarget target, Func<TTarget, TProperty> propertySelector, IEqualityComparer<TProperty> equalityComparer, PlayerLoopTiming monitorTiming)
|
public EveryValueChangedUnityObject(TTarget target, Func<TTarget, TProperty> propertySelector, IEqualityComparer<TProperty> equalityComparer, PlayerLoopTiming monitorTiming, bool cancelImmediately)
|
||||||
{
|
{
|
||||||
this.target = target;
|
this.target = target;
|
||||||
this.propertySelector = propertySelector;
|
this.propertySelector = propertySelector;
|
||||||
this.equalityComparer = equalityComparer;
|
this.equalityComparer = equalityComparer;
|
||||||
this.monitorTiming = monitorTiming;
|
this.monitorTiming = monitorTiming;
|
||||||
|
this.cancelImmediately = cancelImmediately;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IUniTaskAsyncEnumerator<TProperty> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
public IUniTaskAsyncEnumerator<TProperty> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return new _EveryValueChanged(target, propertySelector, equalityComparer, monitorTiming, cancellationToken);
|
return new _EveryValueChanged(target, propertySelector, equalityComparer, monitorTiming, cancellationToken, cancelImmediately);
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class _EveryValueChanged : MoveNextSource, IUniTaskAsyncEnumerator<TProperty>, IPlayerLoopItem
|
sealed class _EveryValueChanged : MoveNextSource, IUniTaskAsyncEnumerator<TProperty>, IPlayerLoopItem
|
||||||
|
@ -50,13 +52,14 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
readonly UnityEngine.Object targetAsUnityObject;
|
readonly UnityEngine.Object targetAsUnityObject;
|
||||||
readonly IEqualityComparer<TProperty> equalityComparer;
|
readonly IEqualityComparer<TProperty> equalityComparer;
|
||||||
readonly Func<TTarget, TProperty> propertySelector;
|
readonly Func<TTarget, TProperty> propertySelector;
|
||||||
CancellationToken cancellationToken;
|
readonly CancellationToken cancellationToken;
|
||||||
|
readonly CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
|
||||||
bool first;
|
bool first;
|
||||||
TProperty currentValue;
|
TProperty currentValue;
|
||||||
bool disposed;
|
bool disposed;
|
||||||
|
|
||||||
public _EveryValueChanged(TTarget target, Func<TTarget, TProperty> propertySelector, IEqualityComparer<TProperty> equalityComparer, PlayerLoopTiming monitorTiming, CancellationToken cancellationToken)
|
public _EveryValueChanged(TTarget target, Func<TTarget, TProperty> propertySelector, IEqualityComparer<TProperty> equalityComparer, PlayerLoopTiming monitorTiming, CancellationToken cancellationToken, bool cancelImmediately)
|
||||||
{
|
{
|
||||||
this.target = target;
|
this.target = target;
|
||||||
this.targetAsUnityObject = target as UnityEngine.Object;
|
this.targetAsUnityObject = target as UnityEngine.Object;
|
||||||
|
@ -64,6 +67,16 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
this.equalityComparer = equalityComparer;
|
this.equalityComparer = equalityComparer;
|
||||||
this.cancellationToken = cancellationToken;
|
this.cancellationToken = cancellationToken;
|
||||||
this.first = true;
|
this.first = true;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var source = (_EveryValueChanged)state;
|
||||||
|
source.completionSource.TrySetCanceled(source.cancellationToken);
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(this, 2);
|
TaskTracker.TrackActiveTask(this, 2);
|
||||||
PlayerLoopHelper.AddAction(monitorTiming, this);
|
PlayerLoopHelper.AddAction(monitorTiming, this);
|
||||||
}
|
}
|
||||||
|
@ -72,8 +85,15 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
|
|
||||||
public UniTask<bool> MoveNextAsync()
|
public UniTask<bool> MoveNextAsync()
|
||||||
{
|
{
|
||||||
// return false instead of throw
|
if (disposed) return CompletedTasks.False;
|
||||||
if (disposed || cancellationToken.IsCancellationRequested) return CompletedTasks.False;
|
|
||||||
|
completionSource.Reset();
|
||||||
|
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completionSource.TrySetCanceled(cancellationToken);
|
||||||
|
return new UniTask<bool>(this, completionSource.Version);
|
||||||
|
}
|
||||||
|
|
||||||
if (first)
|
if (first)
|
||||||
{
|
{
|
||||||
|
@ -86,7 +106,6 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
return CompletedTasks.True;
|
return CompletedTasks.True;
|
||||||
}
|
}
|
||||||
|
|
||||||
completionSource.Reset();
|
|
||||||
return new UniTask<bool>(this, completionSource.Version);
|
return new UniTask<bool>(this, completionSource.Version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,6 +113,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
{
|
{
|
||||||
if (!disposed)
|
if (!disposed)
|
||||||
{
|
{
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
disposed = true;
|
disposed = true;
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
}
|
}
|
||||||
|
@ -102,13 +122,18 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
|
|
||||||
public bool MoveNext()
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
if (disposed || cancellationToken.IsCancellationRequested || targetAsUnityObject == null) // destroyed = cancel.
|
if (disposed || targetAsUnityObject == null)
|
||||||
{
|
{
|
||||||
completionSource.TrySetResult(false);
|
completionSource.TrySetResult(false);
|
||||||
DisposeAsync().Forget();
|
DisposeAsync().Forget();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completionSource.TrySetCanceled(cancellationToken);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
TProperty nextValue = default(TProperty);
|
TProperty nextValue = default(TProperty);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -139,18 +164,20 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
readonly Func<TTarget, TProperty> propertySelector;
|
readonly Func<TTarget, TProperty> propertySelector;
|
||||||
readonly IEqualityComparer<TProperty> equalityComparer;
|
readonly IEqualityComparer<TProperty> equalityComparer;
|
||||||
readonly PlayerLoopTiming monitorTiming;
|
readonly PlayerLoopTiming monitorTiming;
|
||||||
|
readonly bool cancelImmediately;
|
||||||
|
|
||||||
public EveryValueChangedStandardObject(TTarget target, Func<TTarget, TProperty> propertySelector, IEqualityComparer<TProperty> equalityComparer, PlayerLoopTiming monitorTiming)
|
public EveryValueChangedStandardObject(TTarget target, Func<TTarget, TProperty> propertySelector, IEqualityComparer<TProperty> equalityComparer, PlayerLoopTiming monitorTiming, bool cancelImmediately)
|
||||||
{
|
{
|
||||||
this.target = new WeakReference<TTarget>(target, false);
|
this.target = new WeakReference<TTarget>(target, false);
|
||||||
this.propertySelector = propertySelector;
|
this.propertySelector = propertySelector;
|
||||||
this.equalityComparer = equalityComparer;
|
this.equalityComparer = equalityComparer;
|
||||||
this.monitorTiming = monitorTiming;
|
this.monitorTiming = monitorTiming;
|
||||||
|
this.cancelImmediately = cancelImmediately;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IUniTaskAsyncEnumerator<TProperty> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
public IUniTaskAsyncEnumerator<TProperty> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return new _EveryValueChanged(target, propertySelector, equalityComparer, monitorTiming, cancellationToken);
|
return new _EveryValueChanged(target, propertySelector, equalityComparer, monitorTiming, cancellationToken, cancelImmediately);
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class _EveryValueChanged : MoveNextSource, IUniTaskAsyncEnumerator<TProperty>, IPlayerLoopItem
|
sealed class _EveryValueChanged : MoveNextSource, IUniTaskAsyncEnumerator<TProperty>, IPlayerLoopItem
|
||||||
|
@ -158,19 +185,30 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
readonly WeakReference<TTarget> target;
|
readonly WeakReference<TTarget> target;
|
||||||
readonly IEqualityComparer<TProperty> equalityComparer;
|
readonly IEqualityComparer<TProperty> equalityComparer;
|
||||||
readonly Func<TTarget, TProperty> propertySelector;
|
readonly Func<TTarget, TProperty> propertySelector;
|
||||||
CancellationToken cancellationToken;
|
readonly CancellationToken cancellationToken;
|
||||||
|
readonly CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
|
||||||
bool first;
|
bool first;
|
||||||
TProperty currentValue;
|
TProperty currentValue;
|
||||||
bool disposed;
|
bool disposed;
|
||||||
|
|
||||||
public _EveryValueChanged(WeakReference<TTarget> target, Func<TTarget, TProperty> propertySelector, IEqualityComparer<TProperty> equalityComparer, PlayerLoopTiming monitorTiming, CancellationToken cancellationToken)
|
public _EveryValueChanged(WeakReference<TTarget> target, Func<TTarget, TProperty> propertySelector, IEqualityComparer<TProperty> equalityComparer, PlayerLoopTiming monitorTiming, CancellationToken cancellationToken, bool cancelImmediately)
|
||||||
{
|
{
|
||||||
this.target = target;
|
this.target = target;
|
||||||
this.propertySelector = propertySelector;
|
this.propertySelector = propertySelector;
|
||||||
this.equalityComparer = equalityComparer;
|
this.equalityComparer = equalityComparer;
|
||||||
this.cancellationToken = cancellationToken;
|
this.cancellationToken = cancellationToken;
|
||||||
this.first = true;
|
this.first = true;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var source = (_EveryValueChanged)state;
|
||||||
|
source.completionSource.TrySetCanceled(source.cancellationToken);
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(this, 2);
|
TaskTracker.TrackActiveTask(this, 2);
|
||||||
PlayerLoopHelper.AddAction(monitorTiming, this);
|
PlayerLoopHelper.AddAction(monitorTiming, this);
|
||||||
}
|
}
|
||||||
|
@ -179,7 +217,15 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
|
|
||||||
public UniTask<bool> MoveNextAsync()
|
public UniTask<bool> MoveNextAsync()
|
||||||
{
|
{
|
||||||
if (disposed || cancellationToken.IsCancellationRequested) return CompletedTasks.False;
|
if (disposed) return CompletedTasks.False;
|
||||||
|
|
||||||
|
completionSource.Reset();
|
||||||
|
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completionSource.TrySetCanceled(cancellationToken);
|
||||||
|
return new UniTask<bool>(this, completionSource.Version);
|
||||||
|
}
|
||||||
|
|
||||||
if (first)
|
if (first)
|
||||||
{
|
{
|
||||||
|
@ -192,7 +238,6 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
return CompletedTasks.True;
|
return CompletedTasks.True;
|
||||||
}
|
}
|
||||||
|
|
||||||
completionSource.Reset();
|
|
||||||
return new UniTask<bool>(this, completionSource.Version);
|
return new UniTask<bool>(this, completionSource.Version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,6 +245,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
{
|
{
|
||||||
if (!disposed)
|
if (!disposed)
|
||||||
{
|
{
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
disposed = true;
|
disposed = true;
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
}
|
}
|
||||||
|
@ -208,13 +254,19 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
|
|
||||||
public bool MoveNext()
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
if (disposed || cancellationToken.IsCancellationRequested || !target.TryGetTarget(out var t))
|
if (disposed || !target.TryGetTarget(out var t))
|
||||||
{
|
{
|
||||||
completionSource.TrySetResult(false);
|
completionSource.TrySetResult(false);
|
||||||
DisposeAsync().Forget();
|
DisposeAsync().Forget();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completionSource.TrySetCanceled(cancellationToken);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
TProperty nextValue = default(TProperty);
|
TProperty nextValue = default(TProperty);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,32 +6,32 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
{
|
{
|
||||||
public static partial class UniTaskAsyncEnumerable
|
public static partial class UniTaskAsyncEnumerable
|
||||||
{
|
{
|
||||||
public static IUniTaskAsyncEnumerable<AsyncUnit> Timer(TimeSpan dueTime, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool ignoreTimeScale = false)
|
public static IUniTaskAsyncEnumerable<AsyncUnit> Timer(TimeSpan dueTime, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool ignoreTimeScale = false, bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
return new Timer(dueTime, null, updateTiming, ignoreTimeScale);
|
return new Timer(dueTime, null, updateTiming, ignoreTimeScale, cancelImmediately);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<AsyncUnit> Timer(TimeSpan dueTime, TimeSpan period, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool ignoreTimeScale = false)
|
public static IUniTaskAsyncEnumerable<AsyncUnit> Timer(TimeSpan dueTime, TimeSpan period, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool ignoreTimeScale = false, bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
return new Timer(dueTime, period, updateTiming, ignoreTimeScale);
|
return new Timer(dueTime, period, updateTiming, ignoreTimeScale, cancelImmediately);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<AsyncUnit> Interval(TimeSpan period, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool ignoreTimeScale = false)
|
public static IUniTaskAsyncEnumerable<AsyncUnit> Interval(TimeSpan period, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool ignoreTimeScale = false, bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
return new Timer(period, period, updateTiming, ignoreTimeScale);
|
return new Timer(period, period, updateTiming, ignoreTimeScale, cancelImmediately);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<AsyncUnit> TimerFrame(int dueTimeFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update)
|
public static IUniTaskAsyncEnumerable<AsyncUnit> TimerFrame(int dueTimeFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
if (dueTimeFrameCount < 0)
|
if (dueTimeFrameCount < 0)
|
||||||
{
|
{
|
||||||
throw new ArgumentOutOfRangeException("Delay does not allow minus delayFrameCount. dueTimeFrameCount:" + dueTimeFrameCount);
|
throw new ArgumentOutOfRangeException("Delay does not allow minus delayFrameCount. dueTimeFrameCount:" + dueTimeFrameCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new TimerFrame(dueTimeFrameCount, null, updateTiming);
|
return new TimerFrame(dueTimeFrameCount, null, updateTiming, cancelImmediately);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<AsyncUnit> TimerFrame(int dueTimeFrameCount, int periodFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update)
|
public static IUniTaskAsyncEnumerable<AsyncUnit> TimerFrame(int dueTimeFrameCount, int periodFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
if (dueTimeFrameCount < 0)
|
if (dueTimeFrameCount < 0)
|
||||||
{
|
{
|
||||||
|
@ -42,16 +42,16 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
throw new ArgumentOutOfRangeException("Delay does not allow minus periodFrameCount. periodFrameCount:" + dueTimeFrameCount);
|
throw new ArgumentOutOfRangeException("Delay does not allow minus periodFrameCount. periodFrameCount:" + dueTimeFrameCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new TimerFrame(dueTimeFrameCount, periodFrameCount, updateTiming);
|
return new TimerFrame(dueTimeFrameCount, periodFrameCount, updateTiming, cancelImmediately);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskAsyncEnumerable<AsyncUnit> IntervalFrame(int intervalFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update)
|
public static IUniTaskAsyncEnumerable<AsyncUnit> IntervalFrame(int intervalFrameCount, PlayerLoopTiming updateTiming = PlayerLoopTiming.Update, bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
if (intervalFrameCount < 0)
|
if (intervalFrameCount < 0)
|
||||||
{
|
{
|
||||||
throw new ArgumentOutOfRangeException("Delay does not allow minus intervalFrameCount. intervalFrameCount:" + intervalFrameCount);
|
throw new ArgumentOutOfRangeException("Delay does not allow minus intervalFrameCount. intervalFrameCount:" + intervalFrameCount);
|
||||||
}
|
}
|
||||||
return new TimerFrame(intervalFrameCount, intervalFrameCount, updateTiming);
|
return new TimerFrame(intervalFrameCount, intervalFrameCount, updateTiming, cancelImmediately);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,18 +61,20 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
readonly TimeSpan dueTime;
|
readonly TimeSpan dueTime;
|
||||||
readonly TimeSpan? period;
|
readonly TimeSpan? period;
|
||||||
readonly bool ignoreTimeScale;
|
readonly bool ignoreTimeScale;
|
||||||
|
readonly bool cancelImmediately;
|
||||||
|
|
||||||
public Timer(TimeSpan dueTime, TimeSpan? period, PlayerLoopTiming updateTiming, bool ignoreTimeScale)
|
public Timer(TimeSpan dueTime, TimeSpan? period, PlayerLoopTiming updateTiming, bool ignoreTimeScale, bool cancelImmediately)
|
||||||
{
|
{
|
||||||
this.updateTiming = updateTiming;
|
this.updateTiming = updateTiming;
|
||||||
this.dueTime = dueTime;
|
this.dueTime = dueTime;
|
||||||
this.period = period;
|
this.period = period;
|
||||||
this.ignoreTimeScale = ignoreTimeScale;
|
this.ignoreTimeScale = ignoreTimeScale;
|
||||||
|
this.cancelImmediately = cancelImmediately;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IUniTaskAsyncEnumerator<AsyncUnit> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
public IUniTaskAsyncEnumerator<AsyncUnit> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return new _Timer(dueTime, period, updateTiming, ignoreTimeScale, cancellationToken);
|
return new _Timer(dueTime, period, updateTiming, ignoreTimeScale, cancellationToken, cancelImmediately);
|
||||||
}
|
}
|
||||||
|
|
||||||
class _Timer : MoveNextSource, IUniTaskAsyncEnumerator<AsyncUnit>, IPlayerLoopItem
|
class _Timer : MoveNextSource, IUniTaskAsyncEnumerator<AsyncUnit>, IPlayerLoopItem
|
||||||
|
@ -81,7 +83,8 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
readonly float? period;
|
readonly float? period;
|
||||||
readonly PlayerLoopTiming updateTiming;
|
readonly PlayerLoopTiming updateTiming;
|
||||||
readonly bool ignoreTimeScale;
|
readonly bool ignoreTimeScale;
|
||||||
CancellationToken cancellationToken;
|
readonly CancellationToken cancellationToken;
|
||||||
|
readonly CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
|
||||||
int initialFrame;
|
int initialFrame;
|
||||||
float elapsed;
|
float elapsed;
|
||||||
|
@ -89,7 +92,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
bool completed;
|
bool completed;
|
||||||
bool disposed;
|
bool disposed;
|
||||||
|
|
||||||
public _Timer(TimeSpan dueTime, TimeSpan? period, PlayerLoopTiming updateTiming, bool ignoreTimeScale, CancellationToken cancellationToken)
|
public _Timer(TimeSpan dueTime, TimeSpan? period, PlayerLoopTiming updateTiming, bool ignoreTimeScale, CancellationToken cancellationToken, bool cancelImmediately)
|
||||||
{
|
{
|
||||||
this.dueTime = (float)dueTime.TotalSeconds;
|
this.dueTime = (float)dueTime.TotalSeconds;
|
||||||
this.period = (period == null) ? null : (float?)period.Value.TotalSeconds;
|
this.period = (period == null) ? null : (float?)period.Value.TotalSeconds;
|
||||||
|
@ -105,6 +108,16 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
this.updateTiming = updateTiming;
|
this.updateTiming = updateTiming;
|
||||||
this.ignoreTimeScale = ignoreTimeScale;
|
this.ignoreTimeScale = ignoreTimeScale;
|
||||||
this.cancellationToken = cancellationToken;
|
this.cancellationToken = cancellationToken;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var source = (_Timer)state;
|
||||||
|
source.completionSource.TrySetCanceled(source.cancellationToken);
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(this, 2);
|
TaskTracker.TrackActiveTask(this, 2);
|
||||||
PlayerLoopHelper.AddAction(updateTiming, this);
|
PlayerLoopHelper.AddAction(updateTiming, this);
|
||||||
}
|
}
|
||||||
|
@ -114,12 +127,16 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
public UniTask<bool> MoveNextAsync()
|
public UniTask<bool> MoveNextAsync()
|
||||||
{
|
{
|
||||||
// return false instead of throw
|
// return false instead of throw
|
||||||
if (disposed || cancellationToken.IsCancellationRequested || completed) return CompletedTasks.False;
|
if (disposed || completed) return CompletedTasks.False;
|
||||||
|
|
||||||
// reset value here.
|
// reset value here.
|
||||||
this.elapsed = 0;
|
this.elapsed = 0;
|
||||||
|
|
||||||
completionSource.Reset();
|
completionSource.Reset();
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completionSource.TrySetCanceled(cancellationToken);
|
||||||
|
}
|
||||||
return new UniTask<bool>(this, completionSource.Version);
|
return new UniTask<bool>(this, completionSource.Version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,6 +144,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
{
|
{
|
||||||
if (!disposed)
|
if (!disposed)
|
||||||
{
|
{
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
disposed = true;
|
disposed = true;
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
}
|
}
|
||||||
|
@ -135,11 +153,16 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
|
|
||||||
public bool MoveNext()
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
if (disposed || cancellationToken.IsCancellationRequested)
|
if (disposed)
|
||||||
{
|
{
|
||||||
completionSource.TrySetResult(false);
|
completionSource.TrySetResult(false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completionSource.TrySetCanceled(cancellationToken);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (dueTimePhase)
|
if (dueTimePhase)
|
||||||
{
|
{
|
||||||
|
@ -187,24 +210,27 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
readonly PlayerLoopTiming updateTiming;
|
readonly PlayerLoopTiming updateTiming;
|
||||||
readonly int dueTimeFrameCount;
|
readonly int dueTimeFrameCount;
|
||||||
readonly int? periodFrameCount;
|
readonly int? periodFrameCount;
|
||||||
|
readonly bool cancelImmediately;
|
||||||
|
|
||||||
public TimerFrame(int dueTimeFrameCount, int? periodFrameCount, PlayerLoopTiming updateTiming)
|
public TimerFrame(int dueTimeFrameCount, int? periodFrameCount, PlayerLoopTiming updateTiming, bool cancelImmediately)
|
||||||
{
|
{
|
||||||
this.updateTiming = updateTiming;
|
this.updateTiming = updateTiming;
|
||||||
this.dueTimeFrameCount = dueTimeFrameCount;
|
this.dueTimeFrameCount = dueTimeFrameCount;
|
||||||
this.periodFrameCount = periodFrameCount;
|
this.periodFrameCount = periodFrameCount;
|
||||||
|
this.cancelImmediately = cancelImmediately;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IUniTaskAsyncEnumerator<AsyncUnit> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
public IUniTaskAsyncEnumerator<AsyncUnit> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return new _TimerFrame(dueTimeFrameCount, periodFrameCount, updateTiming, cancellationToken);
|
return new _TimerFrame(dueTimeFrameCount, periodFrameCount, updateTiming, cancellationToken, cancelImmediately);
|
||||||
}
|
}
|
||||||
|
|
||||||
class _TimerFrame : MoveNextSource, IUniTaskAsyncEnumerator<AsyncUnit>, IPlayerLoopItem
|
class _TimerFrame : MoveNextSource, IUniTaskAsyncEnumerator<AsyncUnit>, IPlayerLoopItem
|
||||||
{
|
{
|
||||||
readonly int dueTimeFrameCount;
|
readonly int dueTimeFrameCount;
|
||||||
readonly int? periodFrameCount;
|
readonly int? periodFrameCount;
|
||||||
CancellationToken cancellationToken;
|
readonly CancellationToken cancellationToken;
|
||||||
|
readonly CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
|
||||||
int initialFrame;
|
int initialFrame;
|
||||||
int currentFrame;
|
int currentFrame;
|
||||||
|
@ -212,7 +238,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
bool completed;
|
bool completed;
|
||||||
bool disposed;
|
bool disposed;
|
||||||
|
|
||||||
public _TimerFrame(int dueTimeFrameCount, int? periodFrameCount, PlayerLoopTiming updateTiming, CancellationToken cancellationToken)
|
public _TimerFrame(int dueTimeFrameCount, int? periodFrameCount, PlayerLoopTiming updateTiming, CancellationToken cancellationToken, bool cancelImmediately)
|
||||||
{
|
{
|
||||||
if (dueTimeFrameCount <= 0) dueTimeFrameCount = 0;
|
if (dueTimeFrameCount <= 0) dueTimeFrameCount = 0;
|
||||||
if (periodFrameCount != null)
|
if (periodFrameCount != null)
|
||||||
|
@ -226,6 +252,15 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
this.periodFrameCount = periodFrameCount;
|
this.periodFrameCount = periodFrameCount;
|
||||||
this.cancellationToken = cancellationToken;
|
this.cancellationToken = cancellationToken;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var source = (_TimerFrame)state;
|
||||||
|
source.completionSource.TrySetCanceled(source.cancellationToken);
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(this, 2);
|
TaskTracker.TrackActiveTask(this, 2);
|
||||||
PlayerLoopHelper.AddAction(updateTiming, this);
|
PlayerLoopHelper.AddAction(updateTiming, this);
|
||||||
}
|
}
|
||||||
|
@ -234,13 +269,15 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
|
|
||||||
public UniTask<bool> MoveNextAsync()
|
public UniTask<bool> MoveNextAsync()
|
||||||
{
|
{
|
||||||
// return false instead of throw
|
if (disposed || completed) return CompletedTasks.False;
|
||||||
if (disposed || cancellationToken.IsCancellationRequested || completed) return CompletedTasks.False;
|
|
||||||
|
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completionSource.TrySetCanceled(cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
// reset value here.
|
// reset value here.
|
||||||
this.currentFrame = 0;
|
this.currentFrame = 0;
|
||||||
|
|
||||||
completionSource.Reset();
|
completionSource.Reset();
|
||||||
return new UniTask<bool>(this, completionSource.Version);
|
return new UniTask<bool>(this, completionSource.Version);
|
||||||
}
|
}
|
||||||
|
@ -249,6 +286,7 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
{
|
{
|
||||||
if (!disposed)
|
if (!disposed)
|
||||||
{
|
{
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
disposed = true;
|
disposed = true;
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
}
|
}
|
||||||
|
@ -257,7 +295,12 @@ namespace Cysharp.Threading.Tasks.Linq
|
||||||
|
|
||||||
public bool MoveNext()
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
if (disposed || cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completionSource.TrySetCanceled(cancellationToken);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (disposed)
|
||||||
{
|
{
|
||||||
completionSource.TrySetResult(false);
|
completionSource.TrySetResult(false);
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -285,7 +285,11 @@ namespace Cysharp.Threading.Tasks
|
||||||
return dest.ToArray();
|
return dest.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if UNITY_2020_1_OR_NEWER
|
||||||
|
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterAssembliesLoaded)]
|
||||||
|
#else
|
||||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
||||||
|
#endif
|
||||||
static void Init()
|
static void Init()
|
||||||
{
|
{
|
||||||
// capture default(unity) sync-context.
|
// capture default(unity) sync-context.
|
||||||
|
|
|
@ -20,8 +20,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
ITriggerHandler<T> head; // head.prev is last
|
ITriggerHandler<T> head; // head.prev is last
|
||||||
ITriggerHandler<T> iteratingHead;
|
ITriggerHandler<T> iteratingHead;
|
||||||
|
|
||||||
bool preserveRemoveSelf;
|
|
||||||
ITriggerHandler<T> iteratingNode;
|
ITriggerHandler<T> iteratingNode;
|
||||||
|
|
||||||
void LogError(Exception ex)
|
void LogError(Exception ex)
|
||||||
|
@ -55,18 +53,9 @@ namespace Cysharp.Threading.Tasks
|
||||||
Remove(h);
|
Remove(h);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (preserveRemoveSelf)
|
// If `h` itself is removed by OnNext, h.Next is null.
|
||||||
{
|
// Therefore, instead of looking at h.Next, the `iteratingNode` reference itself is replaced.
|
||||||
preserveRemoveSelf = false;
|
h = h == iteratingNode ? h.Next : iteratingNode;
|
||||||
iteratingNode = null;
|
|
||||||
var next = h.Next;
|
|
||||||
Remove(h);
|
|
||||||
h = next;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
h = h.Next;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
iteratingNode = null;
|
iteratingNode = null;
|
||||||
|
@ -97,9 +86,8 @@ namespace Cysharp.Threading.Tasks
|
||||||
LogError(ex);
|
LogError(ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
preserveRemoveSelf = false;
|
var next = h == iteratingNode ? h.Next : iteratingNode;
|
||||||
iteratingNode = null;
|
iteratingNode = null;
|
||||||
var next = h.Next;
|
|
||||||
Remove(h);
|
Remove(h);
|
||||||
h = next;
|
h = next;
|
||||||
}
|
}
|
||||||
|
@ -132,9 +120,8 @@ namespace Cysharp.Threading.Tasks
|
||||||
LogError(ex);
|
LogError(ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
preserveRemoveSelf = false;
|
var next = h == iteratingNode ? h.Next : iteratingNode;
|
||||||
iteratingNode = null;
|
iteratingNode = null;
|
||||||
var next = h.Next;
|
|
||||||
Remove(h);
|
Remove(h);
|
||||||
h = next;
|
h = next;
|
||||||
}
|
}
|
||||||
|
@ -167,9 +154,8 @@ namespace Cysharp.Threading.Tasks
|
||||||
LogError(ex);
|
LogError(ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
preserveRemoveSelf = false;
|
var next = h == iteratingNode ? h.Next : iteratingNode;
|
||||||
iteratingNode = null;
|
iteratingNode = null;
|
||||||
var next = h.Next;
|
|
||||||
Remove(h);
|
Remove(h);
|
||||||
h = next;
|
h = next;
|
||||||
}
|
}
|
||||||
|
@ -241,13 +227,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
if (handler == null) throw new ArgumentNullException(nameof(handler));
|
if (handler == null) throw new ArgumentNullException(nameof(handler));
|
||||||
|
|
||||||
if (iteratingNode != null && iteratingNode == handler)
|
|
||||||
{
|
|
||||||
// if remove self, reserve remove self after invoke completed.
|
|
||||||
preserveRemoveSelf = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var prev = handler.Prev;
|
var prev = handler.Prev;
|
||||||
var next = handler.Next;
|
var next = handler.Next;
|
||||||
|
|
||||||
|
@ -260,17 +239,19 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
head = next;
|
head = next;
|
||||||
}
|
}
|
||||||
else if (handler == iteratingHead)
|
|
||||||
{
|
|
||||||
iteratingHead = next;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// when handler is head, prev indicate last so don't use it.
|
// when handler is head, prev indicate last so don't use it.
|
||||||
if (prev != null)
|
else if (prev != null)
|
||||||
{
|
{
|
||||||
prev.Next = next;
|
prev.Next = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (handler == iteratingNode)
|
||||||
|
{
|
||||||
|
iteratingNode = next;
|
||||||
|
}
|
||||||
|
if (handler == iteratingHead)
|
||||||
|
{
|
||||||
|
iteratingHead = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (head != null)
|
if (head != null)
|
||||||
|
@ -307,5 +288,4 @@ namespace Cysharp.Threading.Tasks
|
||||||
handler.Next = null;
|
handler.Next = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,13 +32,11 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
if (cancellationTokenSource == null)
|
if (cancellationTokenSource == null)
|
||||||
{
|
{
|
||||||
cancellationTokenSource = new CancellationTokenSource();
|
cancellationTokenSource = new CancellationTokenSource();
|
||||||
}
|
|
||||||
|
|
||||||
if (!awakeCalled)
|
if (!awakeCalled)
|
||||||
{
|
{
|
||||||
PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, new AwakeMonitor(this));
|
PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, new AwakeMonitor(this));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return cancellationTokenSource.Token;
|
return cancellationTokenSource.Token;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,7 +81,7 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
|
|
||||||
public bool MoveNext()
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
if (trigger.called) return false;
|
if (trigger.called || trigger.awakeCalled) return false;
|
||||||
if (trigger == null)
|
if (trigger == null)
|
||||||
{
|
{
|
||||||
trigger.OnDestroy();
|
trigger.OnDestroy();
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
#pragma warning disable 0649
|
#pragma warning disable 0649
|
||||||
|
|
||||||
|
#if UNITASK_NETCORE || UNITY_2022_3_OR_NEWER
|
||||||
|
#define SUPPORT_VALUETASK
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if SUPPORT_VALUETASK
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Threading.Tasks.Sources;
|
using System.Threading.Tasks.Sources;
|
||||||
|
@ -10,7 +16,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
public static ValueTask AsValueTask(this in UniTask task)
|
public static ValueTask AsValueTask(this in UniTask task)
|
||||||
{
|
{
|
||||||
#if NETSTANDARD2_0
|
#if (UNITASK_NETCORE && NETSTANDARD2_0)
|
||||||
return new ValueTask(new UniTaskValueTaskSource(task), 0);
|
return new ValueTask(new UniTaskValueTaskSource(task), 0);
|
||||||
#else
|
#else
|
||||||
return task;
|
return task;
|
||||||
|
@ -19,7 +25,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
public static ValueTask<T> AsValueTask<T>(this in UniTask<T> task)
|
public static ValueTask<T> AsValueTask<T>(this in UniTask<T> task)
|
||||||
{
|
{
|
||||||
#if NETSTANDARD2_0
|
#if (UNITASK_NETCORE && NETSTANDARD2_0)
|
||||||
return new ValueTask<T>(new UniTaskValueTaskSource<T>(task), 0);
|
return new ValueTask<T>(new UniTaskValueTaskSource<T>(task), 0);
|
||||||
#else
|
#else
|
||||||
return task;
|
return task;
|
||||||
|
@ -36,7 +42,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
await task;
|
await task;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if NETSTANDARD2_0
|
#if (UNITASK_NETCORE && NETSTANDARD2_0)
|
||||||
|
|
||||||
class UniTaskValueTaskSource : IValueTaskSource
|
class UniTaskValueTaskSource : IValueTaskSource
|
||||||
{
|
{
|
||||||
|
@ -95,3 +101,4 @@ namespace Cysharp.Threading.Tasks
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
|
@ -1,5 +1,5 @@
|
||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 12bdad0556e999f4aa82da29415d361f
|
guid: d38f0478933be42d895c37b862540a1c
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
|
@ -33,14 +33,14 @@ namespace Cysharp.Threading.Tasks
|
||||||
return new YieldAwaitable(timing);
|
return new YieldAwaitable(timing);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask Yield(CancellationToken cancellationToken)
|
public static UniTask Yield(CancellationToken cancellationToken, bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
return new UniTask(YieldPromise.Create(PlayerLoopTiming.Update, cancellationToken, out var token), token);
|
return new UniTask(YieldPromise.Create(PlayerLoopTiming.Update, cancellationToken, cancelImmediately, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask Yield(PlayerLoopTiming timing, CancellationToken cancellationToken)
|
public static UniTask Yield(PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
return new UniTask(YieldPromise.Create(timing, cancellationToken, out var token), token);
|
return new UniTask(YieldPromise.Create(timing, cancellationToken, cancelImmediately, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -48,7 +48,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static UniTask NextFrame()
|
public static UniTask NextFrame()
|
||||||
{
|
{
|
||||||
return new UniTask(NextFramePromise.Create(PlayerLoopTiming.Update, CancellationToken.None, out var token), token);
|
return new UniTask(NextFramePromise.Create(PlayerLoopTiming.Update, CancellationToken.None, false, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -56,25 +56,31 @@ namespace Cysharp.Threading.Tasks
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static UniTask NextFrame(PlayerLoopTiming timing)
|
public static UniTask NextFrame(PlayerLoopTiming timing)
|
||||||
{
|
{
|
||||||
return new UniTask(NextFramePromise.Create(timing, CancellationToken.None, out var token), token);
|
return new UniTask(NextFramePromise.Create(timing, CancellationToken.None, false, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Similar as UniTask.Yield but guaranteed run on next frame.
|
/// Similar as UniTask.Yield but guaranteed run on next frame.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static UniTask NextFrame(CancellationToken cancellationToken)
|
public static UniTask NextFrame(CancellationToken cancellationToken, bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
return new UniTask(NextFramePromise.Create(PlayerLoopTiming.Update, cancellationToken, out var token), token);
|
return new UniTask(NextFramePromise.Create(PlayerLoopTiming.Update, cancellationToken, cancelImmediately, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Similar as UniTask.Yield but guaranteed run on next frame.
|
/// Similar as UniTask.Yield but guaranteed run on next frame.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static UniTask NextFrame(PlayerLoopTiming timing, CancellationToken cancellationToken)
|
public static UniTask NextFrame(PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
return new UniTask(NextFramePromise.Create(timing, cancellationToken, out var token), token);
|
return new UniTask(NextFramePromise.Create(timing, cancellationToken, cancelImmediately, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if UNITY_2023_1_OR_NEWER
|
||||||
|
public static async UniTask WaitForEndOfFrame(CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
await Awaitable.EndOfFrameAsync(cancellationToken);
|
||||||
|
}
|
||||||
|
#else
|
||||||
[Obsolete("Use WaitForEndOfFrame(MonoBehaviour) instead or UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate). Equivalent for coroutine's WaitForEndOfFrame requires MonoBehaviour(runner of Coroutine).")]
|
[Obsolete("Use WaitForEndOfFrame(MonoBehaviour) instead or UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate). Equivalent for coroutine's WaitForEndOfFrame requires MonoBehaviour(runner of Coroutine).")]
|
||||||
public static YieldAwaitable WaitForEndOfFrame()
|
public static YieldAwaitable WaitForEndOfFrame()
|
||||||
{
|
{
|
||||||
|
@ -82,14 +88,21 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
|
|
||||||
[Obsolete("Use WaitForEndOfFrame(MonoBehaviour) instead or UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate). Equivalent for coroutine's WaitForEndOfFrame requires MonoBehaviour(runner of Coroutine).")]
|
[Obsolete("Use WaitForEndOfFrame(MonoBehaviour) instead or UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate). Equivalent for coroutine's WaitForEndOfFrame requires MonoBehaviour(runner of Coroutine).")]
|
||||||
public static UniTask WaitForEndOfFrame(CancellationToken cancellationToken)
|
public static UniTask WaitForEndOfFrame(CancellationToken cancellationToken, bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
return UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate, cancellationToken);
|
return UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate, cancellationToken, cancelImmediately);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public static UniTask WaitForEndOfFrame(MonoBehaviour coroutineRunner)
|
||||||
|
{
|
||||||
|
var source = WaitForEndOfFramePromise.Create(coroutineRunner, CancellationToken.None, false, out var token);
|
||||||
|
return new UniTask(source, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask WaitForEndOfFrame(MonoBehaviour coroutineRunner, CancellationToken cancellationToken = default)
|
public static UniTask WaitForEndOfFrame(MonoBehaviour coroutineRunner, CancellationToken cancellationToken, bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
var source = WaitForEndOfFramePromise.Create(coroutineRunner, cancellationToken, out var token);
|
var source = WaitForEndOfFramePromise.Create(coroutineRunner, cancellationToken, cancelImmediately, out var token);
|
||||||
return new UniTask(source, token);
|
return new UniTask(source, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,40 +119,50 @@ namespace Cysharp.Threading.Tasks
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Same as UniTask.Yield(PlayerLoopTiming.LastFixedUpdate, cancellationToken).
|
/// Same as UniTask.Yield(PlayerLoopTiming.LastFixedUpdate, cancellationToken).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static UniTask WaitForFixedUpdate(CancellationToken cancellationToken)
|
public static UniTask WaitForFixedUpdate(CancellationToken cancellationToken, bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
return UniTask.Yield(PlayerLoopTiming.LastFixedUpdate, cancellationToken);
|
return UniTask.Yield(PlayerLoopTiming.LastFixedUpdate, cancellationToken, cancelImmediately);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask DelayFrame(int delayFrameCount, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask WaitForSeconds(float duration, bool ignoreTimeScale = false, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
||||||
|
{
|
||||||
|
return Delay(Mathf.RoundToInt(1000 * duration), ignoreTimeScale, delayTiming, cancellationToken, cancelImmediately);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UniTask WaitForSeconds(int duration, bool ignoreTimeScale = false, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
||||||
|
{
|
||||||
|
return Delay(1000 * duration, ignoreTimeScale, delayTiming, cancellationToken, cancelImmediately);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UniTask DelayFrame(int delayFrameCount, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
if (delayFrameCount < 0)
|
if (delayFrameCount < 0)
|
||||||
{
|
{
|
||||||
throw new ArgumentOutOfRangeException("Delay does not allow minus delayFrameCount. delayFrameCount:" + delayFrameCount);
|
throw new ArgumentOutOfRangeException("Delay does not allow minus delayFrameCount. delayFrameCount:" + delayFrameCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new UniTask(DelayFramePromise.Create(delayFrameCount, delayTiming, cancellationToken, out var token), token);
|
return new UniTask(DelayFramePromise.Create(delayFrameCount, delayTiming, cancellationToken, cancelImmediately, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask Delay(int millisecondsDelay, bool ignoreTimeScale = false, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask Delay(int millisecondsDelay, bool ignoreTimeScale = false, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
var delayTimeSpan = TimeSpan.FromMilliseconds(millisecondsDelay);
|
var delayTimeSpan = TimeSpan.FromMilliseconds(millisecondsDelay);
|
||||||
return Delay(delayTimeSpan, ignoreTimeScale, delayTiming, cancellationToken);
|
return Delay(delayTimeSpan, ignoreTimeScale, delayTiming, cancellationToken, cancelImmediately);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask Delay(TimeSpan delayTimeSpan, bool ignoreTimeScale = false, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask Delay(TimeSpan delayTimeSpan, bool ignoreTimeScale = false, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
var delayType = ignoreTimeScale ? DelayType.UnscaledDeltaTime : DelayType.DeltaTime;
|
var delayType = ignoreTimeScale ? DelayType.UnscaledDeltaTime : DelayType.DeltaTime;
|
||||||
return Delay(delayTimeSpan, delayType, delayTiming, cancellationToken);
|
return Delay(delayTimeSpan, delayType, delayTiming, cancellationToken, cancelImmediately);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask Delay(int millisecondsDelay, DelayType delayType, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask Delay(int millisecondsDelay, DelayType delayType, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
var delayTimeSpan = TimeSpan.FromMilliseconds(millisecondsDelay);
|
var delayTimeSpan = TimeSpan.FromMilliseconds(millisecondsDelay);
|
||||||
return Delay(delayTimeSpan, delayType, delayTiming, cancellationToken);
|
return Delay(delayTimeSpan, delayType, delayTiming, cancellationToken, cancelImmediately);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask Delay(TimeSpan delayTimeSpan, DelayType delayType, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask Delay(TimeSpan delayTimeSpan, DelayType delayType, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
if (delayTimeSpan < TimeSpan.Zero)
|
if (delayTimeSpan < TimeSpan.Zero)
|
||||||
{
|
{
|
||||||
|
@ -158,16 +181,16 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
case DelayType.UnscaledDeltaTime:
|
case DelayType.UnscaledDeltaTime:
|
||||||
{
|
{
|
||||||
return new UniTask(DelayIgnoreTimeScalePromise.Create(delayTimeSpan, delayTiming, cancellationToken, out var token), token);
|
return new UniTask(DelayIgnoreTimeScalePromise.Create(delayTimeSpan, delayTiming, cancellationToken, cancelImmediately, out var token), token);
|
||||||
}
|
}
|
||||||
case DelayType.Realtime:
|
case DelayType.Realtime:
|
||||||
{
|
{
|
||||||
return new UniTask(DelayRealtimePromise.Create(delayTimeSpan, delayTiming, cancellationToken, out var token), token);
|
return new UniTask(DelayRealtimePromise.Create(delayTimeSpan, delayTiming, cancellationToken, cancelImmediately, out var token), token);
|
||||||
}
|
}
|
||||||
case DelayType.DeltaTime:
|
case DelayType.DeltaTime:
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
return new UniTask(DelayPromise.Create(delayTimeSpan, delayTiming, cancellationToken, out var token), token);
|
return new UniTask(DelayPromise.Create(delayTimeSpan, delayTiming, cancellationToken, cancelImmediately, out var token), token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -184,13 +207,15 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
|
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
bool cancelImmediately;
|
||||||
UniTaskCompletionSourceCore<object> core;
|
UniTaskCompletionSourceCore<object> core;
|
||||||
|
|
||||||
YieldPromise()
|
YieldPromise()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource Create(PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource Create(PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
@ -202,8 +227,17 @@ namespace Cysharp.Threading.Tasks
|
||||||
result = new YieldPromise();
|
result = new YieldPromise();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.cancelImmediately = cancelImmediately;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var promise = (YieldPromise)state;
|
||||||
|
promise.core.TrySetCanceled(promise.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
@ -220,9 +254,16 @@ namespace Cysharp.Threading.Tasks
|
||||||
core.GetResult(token);
|
core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
{
|
||||||
|
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
||||||
{
|
{
|
||||||
TryReturn();
|
TryReturn();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public UniTaskStatus GetStatus(short token)
|
public UniTaskStatus GetStatus(short token)
|
||||||
|
@ -257,6 +298,8 @@ namespace Cysharp.Threading.Tasks
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
core.Reset();
|
core.Reset();
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
|
cancelImmediately = default;
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -273,14 +316,16 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
|
|
||||||
int frameCount;
|
int frameCount;
|
||||||
CancellationToken cancellationToken;
|
|
||||||
UniTaskCompletionSourceCore<AsyncUnit> core;
|
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||||
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
bool cancelImmediately;
|
||||||
|
|
||||||
NextFramePromise()
|
NextFramePromise()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource Create(PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource Create(PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
@ -294,6 +339,16 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
result.frameCount = PlayerLoopHelper.IsMainThread ? Time.frameCount : -1;
|
result.frameCount = PlayerLoopHelper.IsMainThread ? Time.frameCount : -1;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.cancelImmediately = cancelImmediately;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var promise = (NextFramePromise)state;
|
||||||
|
promise.core.TrySetCanceled(promise.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
@ -310,9 +365,16 @@ namespace Cysharp.Threading.Tasks
|
||||||
core.GetResult(token);
|
core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
{
|
||||||
|
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
||||||
{
|
{
|
||||||
TryReturn();
|
TryReturn();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public UniTaskStatus GetStatus(short token)
|
public UniTaskStatus GetStatus(short token)
|
||||||
|
@ -352,6 +414,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
core.Reset();
|
core.Reset();
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -367,14 +430,16 @@ namespace Cysharp.Threading.Tasks
|
||||||
TaskPool.RegisterSizeGetter(typeof(WaitForEndOfFramePromise), () => pool.Size);
|
TaskPool.RegisterSizeGetter(typeof(WaitForEndOfFramePromise), () => pool.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
CancellationToken cancellationToken;
|
|
||||||
UniTaskCompletionSourceCore<object> core;
|
UniTaskCompletionSourceCore<object> core;
|
||||||
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
bool cancelImmediately;
|
||||||
|
|
||||||
WaitForEndOfFramePromise()
|
WaitForEndOfFramePromise()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource Create(MonoBehaviour coroutineRunner, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource Create(MonoBehaviour coroutineRunner, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
@ -387,6 +452,16 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
|
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.cancelImmediately = cancelImmediately;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var promise = (WaitForEndOfFramePromise)state;
|
||||||
|
promise.core.TrySetCanceled(promise.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
@ -403,9 +478,16 @@ namespace Cysharp.Threading.Tasks
|
||||||
core.GetResult(token);
|
core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
{
|
||||||
|
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
||||||
{
|
{
|
||||||
TryReturn();
|
TryReturn();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public UniTaskStatus GetStatus(short token)
|
public UniTaskStatus GetStatus(short token)
|
||||||
|
@ -429,6 +511,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
core.Reset();
|
core.Reset();
|
||||||
Reset(); // Reset Enumerator
|
Reset(); // Reset Enumerator
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -477,6 +560,8 @@ namespace Cysharp.Threading.Tasks
|
||||||
int initialFrame;
|
int initialFrame;
|
||||||
int delayFrameCount;
|
int delayFrameCount;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
bool cancelImmediately;
|
||||||
|
|
||||||
int currentFrameCount;
|
int currentFrameCount;
|
||||||
UniTaskCompletionSourceCore<AsyncUnit> core;
|
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||||
|
@ -485,7 +570,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource Create(int delayFrameCount, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource Create(int delayFrameCount, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
@ -500,6 +585,16 @@ namespace Cysharp.Threading.Tasks
|
||||||
result.delayFrameCount = delayFrameCount;
|
result.delayFrameCount = delayFrameCount;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
result.initialFrame = PlayerLoopHelper.IsMainThread ? Time.frameCount : -1;
|
result.initialFrame = PlayerLoopHelper.IsMainThread ? Time.frameCount : -1;
|
||||||
|
result.cancelImmediately = cancelImmediately;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var promise = (DelayFramePromise)state;
|
||||||
|
promise.core.TrySetCanceled(promise.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
@ -516,9 +611,16 @@ namespace Cysharp.Threading.Tasks
|
||||||
core.GetResult(token);
|
core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
{
|
||||||
|
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
||||||
{
|
{
|
||||||
TryReturn();
|
TryReturn();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public UniTaskStatus GetStatus(short token)
|
public UniTaskStatus GetStatus(short token)
|
||||||
|
@ -587,6 +689,8 @@ namespace Cysharp.Threading.Tasks
|
||||||
currentFrameCount = default;
|
currentFrameCount = default;
|
||||||
delayFrameCount = default;
|
delayFrameCount = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
|
cancelImmediately = default;
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -606,6 +710,8 @@ namespace Cysharp.Threading.Tasks
|
||||||
float delayTimeSpan;
|
float delayTimeSpan;
|
||||||
float elapsed;
|
float elapsed;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
bool cancelImmediately;
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<object> core;
|
UniTaskCompletionSourceCore<object> core;
|
||||||
|
|
||||||
|
@ -613,7 +719,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource Create(TimeSpan delayTimeSpan, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource Create(TimeSpan delayTimeSpan, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
@ -629,6 +735,16 @@ namespace Cysharp.Threading.Tasks
|
||||||
result.delayTimeSpan = (float)delayTimeSpan.TotalSeconds;
|
result.delayTimeSpan = (float)delayTimeSpan.TotalSeconds;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
result.initialFrame = PlayerLoopHelper.IsMainThread ? Time.frameCount : -1;
|
result.initialFrame = PlayerLoopHelper.IsMainThread ? Time.frameCount : -1;
|
||||||
|
result.cancelImmediately = cancelImmediately;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var promise = (DelayPromise)state;
|
||||||
|
promise.core.TrySetCanceled(promise.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
@ -645,9 +761,16 @@ namespace Cysharp.Threading.Tasks
|
||||||
core.GetResult(token);
|
core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
{
|
||||||
|
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
||||||
{
|
{
|
||||||
TryReturn();
|
TryReturn();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public UniTaskStatus GetStatus(short token)
|
public UniTaskStatus GetStatus(short token)
|
||||||
|
@ -698,6 +821,8 @@ namespace Cysharp.Threading.Tasks
|
||||||
delayTimeSpan = default;
|
delayTimeSpan = default;
|
||||||
elapsed = default;
|
elapsed = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
|
cancelImmediately = default;
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -717,6 +842,8 @@ namespace Cysharp.Threading.Tasks
|
||||||
float elapsed;
|
float elapsed;
|
||||||
int initialFrame;
|
int initialFrame;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
bool cancelImmediately;
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<object> core;
|
UniTaskCompletionSourceCore<object> core;
|
||||||
|
|
||||||
|
@ -724,7 +851,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource Create(TimeSpan delayFrameTimeSpan, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource Create(TimeSpan delayFrameTimeSpan, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
@ -740,6 +867,16 @@ namespace Cysharp.Threading.Tasks
|
||||||
result.delayFrameTimeSpan = (float)delayFrameTimeSpan.TotalSeconds;
|
result.delayFrameTimeSpan = (float)delayFrameTimeSpan.TotalSeconds;
|
||||||
result.initialFrame = PlayerLoopHelper.IsMainThread ? Time.frameCount : -1;
|
result.initialFrame = PlayerLoopHelper.IsMainThread ? Time.frameCount : -1;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.cancelImmediately = cancelImmediately;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var promise = (DelayIgnoreTimeScalePromise)state;
|
||||||
|
promise.core.TrySetCanceled(promise.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
@ -756,9 +893,16 @@ namespace Cysharp.Threading.Tasks
|
||||||
core.GetResult(token);
|
core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
{
|
||||||
|
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
||||||
{
|
{
|
||||||
TryReturn();
|
TryReturn();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public UniTaskStatus GetStatus(short token)
|
public UniTaskStatus GetStatus(short token)
|
||||||
|
@ -809,6 +953,8 @@ namespace Cysharp.Threading.Tasks
|
||||||
delayFrameTimeSpan = default;
|
delayFrameTimeSpan = default;
|
||||||
elapsed = default;
|
elapsed = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
|
cancelImmediately = default;
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -827,6 +973,8 @@ namespace Cysharp.Threading.Tasks
|
||||||
long delayTimeSpanTicks;
|
long delayTimeSpanTicks;
|
||||||
ValueStopwatch stopwatch;
|
ValueStopwatch stopwatch;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
bool cancelImmediately;
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<AsyncUnit> core;
|
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||||
|
|
||||||
|
@ -834,7 +982,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource Create(TimeSpan delayTimeSpan, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource Create(TimeSpan delayTimeSpan, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
@ -849,6 +997,16 @@ namespace Cysharp.Threading.Tasks
|
||||||
result.stopwatch = ValueStopwatch.StartNew();
|
result.stopwatch = ValueStopwatch.StartNew();
|
||||||
result.delayTimeSpanTicks = delayTimeSpan.Ticks;
|
result.delayTimeSpanTicks = delayTimeSpan.Ticks;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.cancelImmediately = cancelImmediately;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var promise = (DelayRealtimePromise)state;
|
||||||
|
promise.core.TrySetCanceled(promise.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
@ -865,9 +1023,16 @@ namespace Cysharp.Threading.Tasks
|
||||||
core.GetResult(token);
|
core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
{
|
||||||
|
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
||||||
{
|
{
|
||||||
TryReturn();
|
TryReturn();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public UniTaskStatus GetStatus(short token)
|
public UniTaskStatus GetStatus(short token)
|
||||||
|
@ -914,6 +1079,8 @@ namespace Cysharp.Threading.Tasks
|
||||||
core.Reset();
|
core.Reset();
|
||||||
stopwatch = default;
|
stopwatch = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
|
cancelImmediately = default;
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,6 +81,16 @@ namespace Cysharp.Threading.Tasks
|
||||||
return factory();
|
return factory();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static UniTask Create(Func<CancellationToken, UniTask> factory, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return factory(cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UniTask Create<T>(T state, Func<T, UniTask> factory)
|
||||||
|
{
|
||||||
|
return factory(state);
|
||||||
|
}
|
||||||
|
|
||||||
public static UniTask<T> Create<T>(Func<UniTask<T>> factory)
|
public static UniTask<T> Create<T>(Func<UniTask<T>> factory)
|
||||||
{
|
{
|
||||||
return factory();
|
return factory();
|
||||||
|
@ -137,11 +147,19 @@ namespace Cysharp.Threading.Tasks
|
||||||
return () => asyncAction(cancellationToken).Forget();
|
return () => asyncAction(cancellationToken).Forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// helper of create add UniTaskVoid to delegate.
|
||||||
|
/// </summary>
|
||||||
|
public static Action Action<T>(T state, Func<T, UniTaskVoid> asyncAction)
|
||||||
|
{
|
||||||
|
return () => asyncAction(state).Forget();
|
||||||
|
}
|
||||||
|
|
||||||
#if UNITY_2018_3_OR_NEWER
|
#if UNITY_2018_3_OR_NEWER
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create async void(UniTaskVoid) UnityAction.
|
/// Create async void(UniTaskVoid) UnityAction.
|
||||||
/// For exampe: onClick.AddListener(UniTask.UnityAction(async () => { /* */ } ))
|
/// For example: onClick.AddListener(UniTask.UnityAction(async () => { /* */ } ))
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static UnityEngine.Events.UnityAction UnityAction(Func<UniTaskVoid> asyncAction)
|
public static UnityEngine.Events.UnityAction UnityAction(Func<UniTaskVoid> asyncAction)
|
||||||
{
|
{
|
||||||
|
@ -150,13 +168,94 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create async void(UniTaskVoid) UnityAction.
|
/// Create async void(UniTaskVoid) UnityAction.
|
||||||
/// For exampe: onClick.AddListener(UniTask.UnityAction(FooAsync, this.GetCancellationTokenOnDestroy()))
|
/// For example: onClick.AddListener(UniTask.UnityAction(FooAsync, this.GetCancellationTokenOnDestroy()))
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static UnityEngine.Events.UnityAction UnityAction(Func<CancellationToken, UniTaskVoid> asyncAction, CancellationToken cancellationToken)
|
public static UnityEngine.Events.UnityAction UnityAction(Func<CancellationToken, UniTaskVoid> asyncAction, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return () => asyncAction(cancellationToken).Forget();
|
return () => asyncAction(cancellationToken).Forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create async void(UniTaskVoid) UnityAction.
|
||||||
|
/// For example: onClick.AddListener(UniTask.UnityAction(FooAsync, Argument))
|
||||||
|
/// </summary>
|
||||||
|
public static UnityEngine.Events.UnityAction UnityAction<T>(T state, Func<T, UniTaskVoid> asyncAction)
|
||||||
|
{
|
||||||
|
return () => asyncAction(state).Forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create async void(UniTaskVoid) UnityAction.
|
||||||
|
/// For example: onClick.AddListener(UniTask.UnityAction(async (T arg) => { /* */ } ))
|
||||||
|
/// </summary>
|
||||||
|
public static UnityEngine.Events.UnityAction<T> UnityAction<T>(Func<T, UniTaskVoid> asyncAction)
|
||||||
|
{
|
||||||
|
return (arg) => asyncAction(arg).Forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create async void(UniTaskVoid) UnityAction.
|
||||||
|
/// For example: onClick.AddListener(UniTask.UnityAction(async (T0 arg0, T1 arg1) => { /* */ } ))
|
||||||
|
/// </summary>
|
||||||
|
public static UnityEngine.Events.UnityAction<T0, T1> UnityAction<T0, T1>(Func<T0, T1, UniTaskVoid> asyncAction)
|
||||||
|
{
|
||||||
|
return (arg0, arg1) => asyncAction(arg0, arg1).Forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create async void(UniTaskVoid) UnityAction.
|
||||||
|
/// For example: onClick.AddListener(UniTask.UnityAction(async (T0 arg0, T1 arg1, T2 arg2) => { /* */ } ))
|
||||||
|
/// </summary>
|
||||||
|
public static UnityEngine.Events.UnityAction<T0, T1, T2> UnityAction<T0, T1, T2>(Func<T0, T1, T2, UniTaskVoid> asyncAction)
|
||||||
|
{
|
||||||
|
return (arg0, arg1, arg2) => asyncAction(arg0, arg1, arg2).Forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create async void(UniTaskVoid) UnityAction.
|
||||||
|
/// For example: onClick.AddListener(UniTask.UnityAction(async (T0 arg0, T1 arg1, T2 arg2, T3 arg3) => { /* */ } ))
|
||||||
|
/// </summary>
|
||||||
|
public static UnityEngine.Events.UnityAction<T0, T1, T2, T3> UnityAction<T0, T1, T2, T3>(Func<T0, T1, T2, T3, UniTaskVoid> asyncAction)
|
||||||
|
{
|
||||||
|
return (arg0, arg1, arg2, arg3) => asyncAction(arg0, arg1, arg2, arg3).Forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
// <summary>
|
||||||
|
/// Create async void(UniTaskVoid) UnityAction.
|
||||||
|
/// For example: onClick.AddListener(UniTask.UnityAction(async (T arg, CancellationToken cancellationToken) => { /* */ } ))
|
||||||
|
/// </summary>
|
||||||
|
public static UnityEngine.Events.UnityAction<T> UnityAction<T>(Func<T, CancellationToken, UniTaskVoid> asyncAction, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return (arg) => asyncAction(arg, cancellationToken).Forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create async void(UniTaskVoid) UnityAction.
|
||||||
|
/// For example: onClick.AddListener(UniTask.UnityAction(async (T0 arg0, T1 arg1, CancellationToken cancellationToken) => { /* */ } ))
|
||||||
|
/// </summary>
|
||||||
|
public static UnityEngine.Events.UnityAction<T0, T1> UnityAction<T0, T1>(Func<T0, T1, CancellationToken, UniTaskVoid> asyncAction, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return (arg0, arg1) => asyncAction(arg0, arg1, cancellationToken).Forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create async void(UniTaskVoid) UnityAction.
|
||||||
|
/// For example: onClick.AddListener(UniTask.UnityAction(async (T0 arg0, T1 arg1, T2 arg2, CancellationToken cancellationToken) => { /* */ } ))
|
||||||
|
/// </summary>
|
||||||
|
public static UnityEngine.Events.UnityAction<T0, T1, T2> UnityAction<T0, T1, T2>(Func<T0, T1, T2, CancellationToken, UniTaskVoid> asyncAction, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return (arg0, arg1, arg2) => asyncAction(arg0, arg1, arg2, cancellationToken).Forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create async void(UniTaskVoid) UnityAction.
|
||||||
|
/// For example: onClick.AddListener(UniTask.UnityAction(async (T0 arg0, T1 arg1, T2 arg2, T3 arg3, CancellationToken cancellationToken) => { /* */ } ))
|
||||||
|
/// </summary>
|
||||||
|
public static UnityEngine.Events.UnityAction<T0, T1, T2, T3> UnityAction<T0, T1, T2, T3>(Func<T0, T1, T2, T3, CancellationToken, UniTaskVoid> asyncAction, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return (arg0, arg1, arg2, arg3) => asyncAction(arg0, arg1, arg2, arg3, cancellationToken).Forget();
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -175,6 +274,22 @@ namespace Cysharp.Threading.Tasks
|
||||||
return new UniTask<T>(new DeferPromise<T>(factory), 0);
|
return new UniTask<T>(new DeferPromise<T>(factory), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defer the task creation just before call await.
|
||||||
|
/// </summary>
|
||||||
|
public static UniTask Defer<TState>(TState state, Func<TState, UniTask> factory)
|
||||||
|
{
|
||||||
|
return new UniTask(new DeferPromiseWithState<TState>(state, factory), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defer the task creation just before call await.
|
||||||
|
/// </summary>
|
||||||
|
public static UniTask<TResult> Defer<TState, TResult>(TState state, Func<TState, UniTask<TResult>> factory)
|
||||||
|
{
|
||||||
|
return new UniTask<TResult>(new DeferPromiseWithState<TState, TResult>(state, factory), 0);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Never complete.
|
/// Never complete.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -438,6 +553,93 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sealed class DeferPromiseWithState<TState> : IUniTaskSource
|
||||||
|
{
|
||||||
|
Func<TState, UniTask> factory;
|
||||||
|
TState argument;
|
||||||
|
UniTask task;
|
||||||
|
UniTask.Awaiter awaiter;
|
||||||
|
|
||||||
|
public DeferPromiseWithState(TState argument, Func<TState, UniTask> factory)
|
||||||
|
{
|
||||||
|
this.argument = argument;
|
||||||
|
this.factory = factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetResult(short token)
|
||||||
|
{
|
||||||
|
awaiter.GetResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTaskStatus GetStatus(short token)
|
||||||
|
{
|
||||||
|
var f = Interlocked.Exchange(ref factory, null);
|
||||||
|
if (f != null)
|
||||||
|
{
|
||||||
|
task = f(argument);
|
||||||
|
awaiter = task.GetAwaiter();
|
||||||
|
}
|
||||||
|
|
||||||
|
return task.Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnCompleted(Action<object> continuation, object state, short token)
|
||||||
|
{
|
||||||
|
awaiter.SourceOnCompleted(continuation, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTaskStatus UnsafeGetStatus()
|
||||||
|
{
|
||||||
|
return task.Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class DeferPromiseWithState<TState, TResult> : IUniTaskSource<TResult>
|
||||||
|
{
|
||||||
|
Func<TState, UniTask<TResult>> factory;
|
||||||
|
TState argument;
|
||||||
|
UniTask<TResult> task;
|
||||||
|
UniTask<TResult>.Awaiter awaiter;
|
||||||
|
|
||||||
|
public DeferPromiseWithState(TState argument, Func<TState, UniTask<TResult>> factory)
|
||||||
|
{
|
||||||
|
this.argument = argument;
|
||||||
|
this.factory = factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TResult GetResult(short token)
|
||||||
|
{
|
||||||
|
return awaiter.GetResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IUniTaskSource.GetResult(short token)
|
||||||
|
{
|
||||||
|
awaiter.GetResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTaskStatus GetStatus(short token)
|
||||||
|
{
|
||||||
|
var f = Interlocked.Exchange(ref factory, null);
|
||||||
|
if (f != null)
|
||||||
|
{
|
||||||
|
task = f(argument);
|
||||||
|
awaiter = task.GetAwaiter();
|
||||||
|
}
|
||||||
|
|
||||||
|
return task.Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnCompleted(Action<object> continuation, object state, short token)
|
||||||
|
{
|
||||||
|
awaiter.SourceOnCompleted(continuation, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTaskStatus UnsafeGetStatus()
|
||||||
|
{
|
||||||
|
return task.Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sealed class NeverPromise<T> : IUniTaskSource<T>
|
sealed class NeverPromise<T> : IUniTaskSource<T>
|
||||||
{
|
{
|
||||||
static readonly Action<object> cancellationCallback = CancellationCallback;
|
static readonly Action<object> cancellationCallback = CancellationCallback;
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics.Tracing;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Cysharp.Threading.Tasks.Internal;
|
using Cysharp.Threading.Tasks.Internal;
|
||||||
|
|
||||||
|
@ -9,30 +10,40 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
public partial struct UniTask
|
public partial struct UniTask
|
||||||
{
|
{
|
||||||
public static UniTask WaitUntil(Func<bool> predicate, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask WaitUntil(Func<bool> predicate, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
return new UniTask(WaitUntilPromise.Create(predicate, timing, cancellationToken, out var token), token);
|
return new UniTask(WaitUntilPromise.Create(predicate, timing, cancellationToken, cancelImmediately, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask WaitWhile(Func<bool> predicate, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask WaitUntil<T>(T state, Func<T, bool> predicate, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
return new UniTask(WaitWhilePromise.Create(predicate, timing, cancellationToken, out var token), token);
|
return new UniTask(WaitUntilPromise<T>.Create(state, predicate, timing, cancellationToken, cancelImmediately, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask WaitUntilCanceled(CancellationToken cancellationToken, PlayerLoopTiming timing = PlayerLoopTiming.Update)
|
public static UniTask WaitWhile(Func<bool> predicate, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
return new UniTask(WaitUntilCanceledPromise.Create(cancellationToken, timing, out var token), token);
|
return new UniTask(WaitWhilePromise.Create(predicate, timing, cancellationToken, cancelImmediately, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask<U> WaitUntilValueChanged<T, U>(T target, Func<T, U> monitorFunction, PlayerLoopTiming monitorTiming = PlayerLoopTiming.Update, IEqualityComparer<U> equalityComparer = null, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask WaitWhile<T>(T state, Func<T, bool> predicate, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
||||||
|
{
|
||||||
|
return new UniTask(WaitWhilePromise<T>.Create(state, predicate, timing, cancellationToken, cancelImmediately, out var token), token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UniTask WaitUntilCanceled(CancellationToken cancellationToken, PlayerLoopTiming timing = PlayerLoopTiming.Update, bool completeImmediately = false)
|
||||||
|
{
|
||||||
|
return new UniTask(WaitUntilCanceledPromise.Create(cancellationToken, timing, completeImmediately, out var token), token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UniTask<U> WaitUntilValueChanged<T, U>(T target, Func<T, U> monitorFunction, PlayerLoopTiming monitorTiming = PlayerLoopTiming.Update, IEqualityComparer<U> equalityComparer = null, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
||||||
where T : class
|
where T : class
|
||||||
{
|
{
|
||||||
var unityObject = target as UnityEngine.Object;
|
var unityObject = target as UnityEngine.Object;
|
||||||
var isUnityObject = target is UnityEngine.Object; // don't use (unityObject == null)
|
var isUnityObject = target is UnityEngine.Object; // don't use (unityObject == null)
|
||||||
|
|
||||||
return new UniTask<U>(isUnityObject
|
return new UniTask<U>(isUnityObject
|
||||||
? WaitUntilValueChangedUnityObjectPromise<T, U>.Create(target, monitorFunction, equalityComparer, monitorTiming, cancellationToken, out var token)
|
? WaitUntilValueChangedUnityObjectPromise<T, U>.Create(target, monitorFunction, equalityComparer, monitorTiming, cancellationToken, cancelImmediately, out var token)
|
||||||
: WaitUntilValueChangedStandardObjectPromise<T, U>.Create(target, monitorFunction, equalityComparer, monitorTiming, cancellationToken, out token), token);
|
: WaitUntilValueChangedStandardObjectPromise<T, U>.Create(target, monitorFunction, equalityComparer, monitorTiming, cancellationToken, cancelImmediately, out token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class WaitUntilPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<WaitUntilPromise>
|
sealed class WaitUntilPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<WaitUntilPromise>
|
||||||
|
@ -48,6 +59,8 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
Func<bool> predicate;
|
Func<bool> predicate;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
bool cancelImmediately;
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<object> core;
|
UniTaskCompletionSourceCore<object> core;
|
||||||
|
|
||||||
|
@ -55,7 +68,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource Create(Func<bool> predicate, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource Create(Func<bool> predicate, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
@ -69,6 +82,16 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
result.predicate = predicate;
|
result.predicate = predicate;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.cancelImmediately = cancelImmediately;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var promise = (WaitUntilPromise)state;
|
||||||
|
promise.core.TrySetCanceled(promise.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
@ -85,9 +108,16 @@ namespace Cysharp.Threading.Tasks
|
||||||
core.GetResult(token);
|
core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
{
|
||||||
|
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
||||||
{
|
{
|
||||||
TryReturn();
|
TryReturn();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public UniTaskStatus GetStatus(short token)
|
public UniTaskStatus GetStatus(short token)
|
||||||
|
@ -136,31 +166,36 @@ namespace Cysharp.Threading.Tasks
|
||||||
core.Reset();
|
core.Reset();
|
||||||
predicate = default;
|
predicate = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
|
cancelImmediately = default;
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class WaitWhilePromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<WaitWhilePromise>
|
sealed class WaitUntilPromise<T> : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<WaitUntilPromise<T>>
|
||||||
{
|
{
|
||||||
static TaskPool<WaitWhilePromise> pool;
|
static TaskPool<WaitUntilPromise<T>> pool;
|
||||||
WaitWhilePromise nextNode;
|
WaitUntilPromise<T> nextNode;
|
||||||
public ref WaitWhilePromise NextNode => ref nextNode;
|
public ref WaitUntilPromise<T> NextNode => ref nextNode;
|
||||||
|
|
||||||
static WaitWhilePromise()
|
static WaitUntilPromise()
|
||||||
{
|
{
|
||||||
TaskPool.RegisterSizeGetter(typeof(WaitWhilePromise), () => pool.Size);
|
TaskPool.RegisterSizeGetter(typeof(WaitUntilPromise<T>), () => pool.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
Func<bool> predicate;
|
Func<T, bool> predicate;
|
||||||
|
T argument;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
bool cancelImmediately;
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<object> core;
|
UniTaskCompletionSourceCore<object> core;
|
||||||
|
|
||||||
WaitWhilePromise()
|
WaitUntilPromise()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource Create(Func<bool> predicate, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource Create(T argument, Func<T, bool> predicate, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
@ -169,11 +204,22 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
if (!pool.TryPop(out var result))
|
if (!pool.TryPop(out var result))
|
||||||
{
|
{
|
||||||
result = new WaitWhilePromise();
|
result = new WaitUntilPromise<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
result.predicate = predicate;
|
result.predicate = predicate;
|
||||||
|
result.argument = argument;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.cancelImmediately = cancelImmediately;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var promise = (WaitUntilPromise<T>)state;
|
||||||
|
promise.core.TrySetCanceled(promise.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
@ -190,9 +236,143 @@ namespace Cysharp.Threading.Tasks
|
||||||
core.GetResult(token);
|
core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
{
|
||||||
|
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
||||||
{
|
{
|
||||||
TryReturn();
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!predicate(argument))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
core.TrySetException(ex);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
core.TrySetResult(null);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TryReturn()
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
core.Reset();
|
||||||
|
predicate = default;
|
||||||
|
argument = default;
|
||||||
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
|
cancelImmediately = default;
|
||||||
|
return pool.TryPush(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class WaitWhilePromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<WaitWhilePromise>
|
||||||
|
{
|
||||||
|
static TaskPool<WaitWhilePromise> pool;
|
||||||
|
WaitWhilePromise nextNode;
|
||||||
|
public ref WaitWhilePromise NextNode => ref nextNode;
|
||||||
|
|
||||||
|
static WaitWhilePromise()
|
||||||
|
{
|
||||||
|
TaskPool.RegisterSizeGetter(typeof(WaitWhilePromise), () => pool.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
Func<bool> predicate;
|
||||||
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
bool cancelImmediately;
|
||||||
|
|
||||||
|
UniTaskCompletionSourceCore<object> core;
|
||||||
|
|
||||||
|
WaitWhilePromise()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IUniTaskSource Create(Func<bool> predicate, 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 WaitWhilePromise();
|
||||||
|
}
|
||||||
|
|
||||||
|
result.predicate = predicate;
|
||||||
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.cancelImmediately = cancelImmediately;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var promise = (WaitWhilePromise)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)
|
public UniTaskStatus GetStatus(short token)
|
||||||
|
@ -241,30 +421,36 @@ namespace Cysharp.Threading.Tasks
|
||||||
core.Reset();
|
core.Reset();
|
||||||
predicate = default;
|
predicate = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
|
cancelImmediately = default;
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class WaitUntilCanceledPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<WaitUntilCanceledPromise>
|
sealed class WaitWhilePromise<T> : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<WaitWhilePromise<T>>
|
||||||
{
|
{
|
||||||
static TaskPool<WaitUntilCanceledPromise> pool;
|
static TaskPool<WaitWhilePromise<T>> pool;
|
||||||
WaitUntilCanceledPromise nextNode;
|
WaitWhilePromise<T> nextNode;
|
||||||
public ref WaitUntilCanceledPromise NextNode => ref nextNode;
|
public ref WaitWhilePromise<T> NextNode => ref nextNode;
|
||||||
|
|
||||||
static WaitUntilCanceledPromise()
|
static WaitWhilePromise()
|
||||||
{
|
{
|
||||||
TaskPool.RegisterSizeGetter(typeof(WaitUntilCanceledPromise), () => pool.Size);
|
TaskPool.RegisterSizeGetter(typeof(WaitWhilePromise<T>), () => pool.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Func<T, bool> predicate;
|
||||||
|
T argument;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
bool cancelImmediately;
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<object> core;
|
UniTaskCompletionSourceCore<object> core;
|
||||||
|
|
||||||
WaitUntilCanceledPromise()
|
WaitWhilePromise()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource Create(CancellationToken cancellationToken, PlayerLoopTiming timing, out short token)
|
public static IUniTaskSource Create(T argument, Func<T, bool> predicate, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
@ -273,10 +459,22 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
if (!pool.TryPop(out var result))
|
if (!pool.TryPop(out var result))
|
||||||
{
|
{
|
||||||
result = new WaitUntilCanceledPromise();
|
result = new WaitWhilePromise<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result.predicate = predicate;
|
||||||
|
result.argument = argument;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.cancelImmediately = cancelImmediately;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var promise = (WaitWhilePromise<T>)state;
|
||||||
|
promise.core.TrySetCanceled(promise.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
@ -293,9 +491,141 @@ namespace Cysharp.Threading.Tasks
|
||||||
core.GetResult(token);
|
core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
{
|
||||||
|
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
||||||
{
|
{
|
||||||
TryReturn();
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (predicate(argument))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
core.TrySetException(ex);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
core.TrySetResult(null);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TryReturn()
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
core.Reset();
|
||||||
|
predicate = default;
|
||||||
|
argument = default;
|
||||||
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
|
cancelImmediately = default;
|
||||||
|
return pool.TryPush(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class WaitUntilCanceledPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<WaitUntilCanceledPromise>
|
||||||
|
{
|
||||||
|
static TaskPool<WaitUntilCanceledPromise> pool;
|
||||||
|
WaitUntilCanceledPromise nextNode;
|
||||||
|
public ref WaitUntilCanceledPromise NextNode => ref nextNode;
|
||||||
|
|
||||||
|
static WaitUntilCanceledPromise()
|
||||||
|
{
|
||||||
|
TaskPool.RegisterSizeGetter(typeof(WaitUntilCanceledPromise), () => pool.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
bool cancelImmediately;
|
||||||
|
|
||||||
|
UniTaskCompletionSourceCore<object> core;
|
||||||
|
|
||||||
|
WaitUntilCanceledPromise()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IUniTaskSource Create(CancellationToken cancellationToken, PlayerLoopTiming timing, bool cancelImmediately, out short token)
|
||||||
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pool.TryPop(out var result))
|
||||||
|
{
|
||||||
|
result = new WaitUntilCanceledPromise();
|
||||||
|
}
|
||||||
|
|
||||||
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.cancelImmediately = cancelImmediately;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var promise = (WaitUntilCanceledPromise)state;
|
||||||
|
promise.core.TrySetResult(null);
|
||||||
|
}, 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)
|
public UniTaskStatus GetStatus(short token)
|
||||||
|
@ -329,6 +659,8 @@ namespace Cysharp.Threading.Tasks
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
core.Reset();
|
core.Reset();
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
|
cancelImmediately = default;
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -351,6 +683,8 @@ namespace Cysharp.Threading.Tasks
|
||||||
Func<T, U> monitorFunction;
|
Func<T, U> monitorFunction;
|
||||||
IEqualityComparer<U> equalityComparer;
|
IEqualityComparer<U> equalityComparer;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
bool cancelImmediately;
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<U> core;
|
UniTaskCompletionSourceCore<U> core;
|
||||||
|
|
||||||
|
@ -358,7 +692,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource<U> Create(T target, Func<T, U> monitorFunction, IEqualityComparer<U> equalityComparer, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource<U> Create(T target, Func<T, U> monitorFunction, IEqualityComparer<U> equalityComparer, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
@ -376,6 +710,16 @@ namespace Cysharp.Threading.Tasks
|
||||||
result.currentValue = monitorFunction(target);
|
result.currentValue = monitorFunction(target);
|
||||||
result.equalityComparer = equalityComparer ?? UnityEqualityComparer.GetDefault<U>();
|
result.equalityComparer = equalityComparer ?? UnityEqualityComparer.GetDefault<U>();
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.cancelImmediately = cancelImmediately;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var promise = (WaitUntilValueChangedUnityObjectPromise<T, U>)state;
|
||||||
|
promise.core.TrySetCanceled(promise.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
@ -392,9 +736,16 @@ namespace Cysharp.Threading.Tasks
|
||||||
return core.GetResult(token);
|
return core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
{
|
||||||
|
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
||||||
{
|
{
|
||||||
TryReturn();
|
TryReturn();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IUniTaskSource.GetResult(short token)
|
void IUniTaskSource.GetResult(short token)
|
||||||
|
@ -453,6 +804,8 @@ namespace Cysharp.Threading.Tasks
|
||||||
monitorFunction = default;
|
monitorFunction = default;
|
||||||
equalityComparer = default;
|
equalityComparer = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
|
cancelImmediately = default;
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -474,6 +827,8 @@ namespace Cysharp.Threading.Tasks
|
||||||
Func<T, U> monitorFunction;
|
Func<T, U> monitorFunction;
|
||||||
IEqualityComparer<U> equalityComparer;
|
IEqualityComparer<U> equalityComparer;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
bool cancelImmediately;
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<U> core;
|
UniTaskCompletionSourceCore<U> core;
|
||||||
|
|
||||||
|
@ -481,7 +836,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource<U> Create(T target, Func<T, U> monitorFunction, IEqualityComparer<U> equalityComparer, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource<U> Create(T target, Func<T, U> monitorFunction, IEqualityComparer<U> equalityComparer, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
@ -498,6 +853,16 @@ namespace Cysharp.Threading.Tasks
|
||||||
result.currentValue = monitorFunction(target);
|
result.currentValue = monitorFunction(target);
|
||||||
result.equalityComparer = equalityComparer ?? UnityEqualityComparer.GetDefault<U>();
|
result.equalityComparer = equalityComparer ?? UnityEqualityComparer.GetDefault<U>();
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.cancelImmediately = cancelImmediately;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var promise = (WaitUntilValueChangedStandardObjectPromise<T, U>)state;
|
||||||
|
promise.core.TrySetCanceled(promise.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
@ -514,9 +879,16 @@ namespace Cysharp.Threading.Tasks
|
||||||
return core.GetResult(token);
|
return core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
{
|
||||||
|
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
||||||
{
|
{
|
||||||
TryReturn();
|
TryReturn();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IUniTaskSource.GetResult(short token)
|
void IUniTaskSource.GetResult(short token)
|
||||||
|
@ -575,6 +947,8 @@ namespace Cysharp.Threading.Tasks
|
||||||
monitorFunction = default;
|
monitorFunction = default;
|
||||||
equalityComparer = default;
|
equalityComparer = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
|
cancelImmediately = default;
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,183 @@
|
||||||
|
using Cysharp.Threading.Tasks.Internal;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.ExceptionServices;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace Cysharp.Threading.Tasks
|
||||||
|
{
|
||||||
|
public partial struct UniTask
|
||||||
|
{
|
||||||
|
public static IUniTaskAsyncEnumerable<WhenEachResult<T>> WhenEach<T>(IEnumerable<UniTask<T>> tasks)
|
||||||
|
{
|
||||||
|
return new WhenEachEnumerable<T>(tasks);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IUniTaskAsyncEnumerable<WhenEachResult<T>> WhenEach<T>(params UniTask<T>[] tasks)
|
||||||
|
{
|
||||||
|
return new WhenEachEnumerable<T>(tasks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly struct WhenEachResult<T>
|
||||||
|
{
|
||||||
|
public T Result { get; }
|
||||||
|
public Exception Exception { get; }
|
||||||
|
|
||||||
|
//[MemberNotNullWhen(false, nameof(Exception))]
|
||||||
|
public bool IsCompletedSuccessfully => Exception == null;
|
||||||
|
|
||||||
|
//[MemberNotNullWhen(true, nameof(Exception))]
|
||||||
|
public bool IsFaulted => Exception != null;
|
||||||
|
|
||||||
|
public WhenEachResult(T result)
|
||||||
|
{
|
||||||
|
this.Result = result;
|
||||||
|
this.Exception = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WhenEachResult(Exception exception)
|
||||||
|
{
|
||||||
|
if (exception == null) throw new ArgumentNullException(nameof(exception));
|
||||||
|
this.Result = default;
|
||||||
|
this.Exception = exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TryThrow()
|
||||||
|
{
|
||||||
|
if (IsFaulted)
|
||||||
|
{
|
||||||
|
ExceptionDispatchInfo.Capture(Exception).Throw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public T GetResult()
|
||||||
|
{
|
||||||
|
if (IsFaulted)
|
||||||
|
{
|
||||||
|
ExceptionDispatchInfo.Capture(Exception).Throw();
|
||||||
|
}
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
if (IsCompletedSuccessfully)
|
||||||
|
{
|
||||||
|
return Result?.ToString() ?? "";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return $"Exception{{{Exception.Message}}}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal enum WhenEachState : byte
|
||||||
|
{
|
||||||
|
NotRunning,
|
||||||
|
Running,
|
||||||
|
Completed
|
||||||
|
}
|
||||||
|
|
||||||
|
internal sealed class WhenEachEnumerable<T> : IUniTaskAsyncEnumerable<WhenEachResult<T>>
|
||||||
|
{
|
||||||
|
IEnumerable<UniTask<T>> source;
|
||||||
|
|
||||||
|
public WhenEachEnumerable(IEnumerable<UniTask<T>> source)
|
||||||
|
{
|
||||||
|
this.source = source;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IUniTaskAsyncEnumerator<WhenEachResult<T>> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
return new Enumerator(source, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class Enumerator : IUniTaskAsyncEnumerator<WhenEachResult<T>>
|
||||||
|
{
|
||||||
|
readonly IEnumerable<UniTask<T>> source;
|
||||||
|
CancellationToken cancellationToken;
|
||||||
|
|
||||||
|
Channel<WhenEachResult<T>> channel;
|
||||||
|
IUniTaskAsyncEnumerator<WhenEachResult<T>> channelEnumerator;
|
||||||
|
int completeCount;
|
||||||
|
WhenEachState state;
|
||||||
|
|
||||||
|
public Enumerator(IEnumerable<UniTask<T>> source, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
this.source = source;
|
||||||
|
this.cancellationToken = cancellationToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WhenEachResult<T> Current => channelEnumerator.Current;
|
||||||
|
|
||||||
|
public UniTask<bool> MoveNextAsync()
|
||||||
|
{
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
if (state == WhenEachState.NotRunning)
|
||||||
|
{
|
||||||
|
state = WhenEachState.Running;
|
||||||
|
channel = Channel.CreateSingleConsumerUnbounded<WhenEachResult<T>>();
|
||||||
|
channelEnumerator = channel.Reader.ReadAllAsync().GetAsyncEnumerator(cancellationToken);
|
||||||
|
|
||||||
|
if (source is UniTask<T>[] array)
|
||||||
|
{
|
||||||
|
ConsumeAll(this, array, array.Length);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
using (var rentArray = ArrayPoolUtil.Materialize(source))
|
||||||
|
{
|
||||||
|
ConsumeAll(this, rentArray.Array, rentArray.Length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return channelEnumerator.MoveNextAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ConsumeAll(Enumerator self, UniTask<T>[] array, int length)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
RunWhenEachTask(self, array[i], length).Forget();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async UniTaskVoid RunWhenEachTask(Enumerator self, UniTask<T> task, int length)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var result = await task;
|
||||||
|
self.channel.Writer.TryWrite(new WhenEachResult<T>(result));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
self.channel.Writer.TryWrite(new WhenEachResult<T>(ex));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Interlocked.Increment(ref self.completeCount) == length)
|
||||||
|
{
|
||||||
|
self.state = WhenEachState.Completed;
|
||||||
|
self.channel.Writer.TryComplete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async UniTask DisposeAsync()
|
||||||
|
{
|
||||||
|
if (channelEnumerator != null)
|
||||||
|
{
|
||||||
|
await channelEnumerator.DisposeAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state != WhenEachState.Completed)
|
||||||
|
{
|
||||||
|
state = WhenEachState.Completed;
|
||||||
|
channel.Writer.TryComplete(new OperationCanceledException());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 8760bbbab905a534eb6fb7b61b736926
|
guid: 7cac24fdda5112047a1cd3dd66b542c4
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
|
@ -1,6 +1,10 @@
|
||||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||||
#pragma warning disable CS0436
|
#pragma warning disable CS0436
|
||||||
|
|
||||||
|
#if UNITASK_NETCORE || UNITY_2022_3_OR_NEWER
|
||||||
|
#define SUPPORT_VALUETASK
|
||||||
|
#endif
|
||||||
|
|
||||||
using Cysharp.Threading.Tasks.CompilerServices;
|
using Cysharp.Threading.Tasks.CompilerServices;
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
@ -69,7 +73,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
return new UniTask<bool>(new IsCanceledSource(source), token);
|
return new UniTask<bool>(new IsCanceledSource(source), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !UNITY_2018_3_OR_NEWER
|
#if SUPPORT_VALUETASK
|
||||||
|
|
||||||
public static implicit operator System.Threading.Tasks.ValueTask(in UniTask self)
|
public static implicit operator System.Threading.Tasks.ValueTask(in UniTask self)
|
||||||
{
|
{
|
||||||
|
@ -78,7 +82,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
return default;
|
return default;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if NETSTANDARD2_0
|
#if (UNITASK_NETCORE && NETSTANDARD2_0)
|
||||||
return self.AsValueTask();
|
return self.AsValueTask();
|
||||||
#else
|
#else
|
||||||
return new System.Threading.Tasks.ValueTask(self.source, self.token);
|
return new System.Threading.Tasks.ValueTask(self.source, self.token);
|
||||||
|
@ -118,7 +122,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
this.source.GetResult(this.token);
|
this.source.GetResult(this.token);
|
||||||
return CompletedTasks.AsyncUnit;
|
return CompletedTasks.AsyncUnit;
|
||||||
}
|
}
|
||||||
else if(this.source is IUniTaskSource<AsyncUnit> asyncUnitSource)
|
else if (this.source is IUniTaskSource<AsyncUnit> asyncUnitSource)
|
||||||
{
|
{
|
||||||
return new UniTask<AsyncUnit>(asyncUnitSource, this.token);
|
return new UniTask<AsyncUnit>(asyncUnitSource, this.token);
|
||||||
}
|
}
|
||||||
|
@ -440,7 +444,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
return self.AsUniTask();
|
return self.AsUniTask();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !UNITY_2018_3_OR_NEWER
|
#if SUPPORT_VALUETASK
|
||||||
|
|
||||||
public static implicit operator System.Threading.Tasks.ValueTask<T>(in UniTask<T> self)
|
public static implicit operator System.Threading.Tasks.ValueTask<T>(in UniTask<T> self)
|
||||||
{
|
{
|
||||||
|
@ -449,7 +453,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
return new System.Threading.Tasks.ValueTask<T>(self.result);
|
return new System.Threading.Tasks.ValueTask<T>(self.result);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if NETSTANDARD2_0
|
#if (UNITASK_NETCORE && NETSTANDARD2_0)
|
||||||
return self.AsValueTask();
|
return self.AsValueTask();
|
||||||
#else
|
#else
|
||||||
return new System.Threading.Tasks.ValueTask<T>(self.source, self.token);
|
return new System.Threading.Tasks.ValueTask<T>(self.source, self.token);
|
||||||
|
|
|
@ -137,8 +137,8 @@ namespace Cysharp.Threading.Tasks
|
||||||
if (continuation != null || Interlocked.CompareExchange(ref this.continuation, UniTaskCompletionSourceCoreShared.s_sentinel, null) != null)
|
if (continuation != null || Interlocked.CompareExchange(ref this.continuation, UniTaskCompletionSourceCoreShared.s_sentinel, null) != null)
|
||||||
{
|
{
|
||||||
continuation(continuationState);
|
continuation(continuationState);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -165,8 +165,8 @@ namespace Cysharp.Threading.Tasks
|
||||||
if (continuation != null || Interlocked.CompareExchange(ref this.continuation, UniTaskCompletionSourceCoreShared.s_sentinel, null) != null)
|
if (continuation != null || Interlocked.CompareExchange(ref this.continuation, UniTaskCompletionSourceCoreShared.s_sentinel, null) != null)
|
||||||
{
|
{
|
||||||
continuation(continuationState);
|
continuation(continuationState);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -184,8 +184,8 @@ namespace Cysharp.Threading.Tasks
|
||||||
if (continuation != null || Interlocked.CompareExchange(ref this.continuation, UniTaskCompletionSourceCoreShared.s_sentinel, null) != null)
|
if (continuation != null || Interlocked.CompareExchange(ref this.continuation, UniTaskCompletionSourceCoreShared.s_sentinel, null) != null)
|
||||||
{
|
{
|
||||||
continuation(continuationState);
|
continuation(continuationState);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -328,6 +328,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<AsyncUnit> core;
|
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||||
|
short version;
|
||||||
|
|
||||||
AutoResetUniTaskCompletionSource()
|
AutoResetUniTaskCompletionSource()
|
||||||
{
|
{
|
||||||
|
@ -340,6 +341,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
result = new AutoResetUniTaskCompletionSource();
|
result = new AutoResetUniTaskCompletionSource();
|
||||||
}
|
}
|
||||||
|
result.version = result.core.Version;
|
||||||
TaskTracker.TrackActiveTask(result, 2);
|
TaskTracker.TrackActiveTask(result, 2);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -383,19 +385,19 @@ namespace Cysharp.Threading.Tasks
|
||||||
[DebuggerHidden]
|
[DebuggerHidden]
|
||||||
public bool TrySetResult()
|
public bool TrySetResult()
|
||||||
{
|
{
|
||||||
return core.TrySetResult(AsyncUnit.Default);
|
return version == core.Version && core.TrySetResult(AsyncUnit.Default);
|
||||||
}
|
}
|
||||||
|
|
||||||
[DebuggerHidden]
|
[DebuggerHidden]
|
||||||
public bool TrySetCanceled(CancellationToken cancellationToken = default)
|
public bool TrySetCanceled(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return core.TrySetCanceled(cancellationToken);
|
return version == core.Version && core.TrySetCanceled(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
[DebuggerHidden]
|
[DebuggerHidden]
|
||||||
public bool TrySetException(Exception exception)
|
public bool TrySetException(Exception exception)
|
||||||
{
|
{
|
||||||
return core.TrySetException(exception);
|
return version == core.Version && core.TrySetException(exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
[DebuggerHidden]
|
[DebuggerHidden]
|
||||||
|
@ -409,7 +411,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
TryReturn();
|
TryReturn();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[DebuggerHidden]
|
[DebuggerHidden]
|
||||||
|
@ -451,6 +452,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<T> core;
|
UniTaskCompletionSourceCore<T> core;
|
||||||
|
short version;
|
||||||
|
|
||||||
AutoResetUniTaskCompletionSource()
|
AutoResetUniTaskCompletionSource()
|
||||||
{
|
{
|
||||||
|
@ -463,6 +465,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
result = new AutoResetUniTaskCompletionSource<T>();
|
result = new AutoResetUniTaskCompletionSource<T>();
|
||||||
}
|
}
|
||||||
|
result.version = result.core.Version;
|
||||||
TaskTracker.TrackActiveTask(result, 2);
|
TaskTracker.TrackActiveTask(result, 2);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -506,19 +509,19 @@ namespace Cysharp.Threading.Tasks
|
||||||
[DebuggerHidden]
|
[DebuggerHidden]
|
||||||
public bool TrySetResult(T result)
|
public bool TrySetResult(T result)
|
||||||
{
|
{
|
||||||
return core.TrySetResult(result);
|
return version == core.Version && core.TrySetResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
[DebuggerHidden]
|
[DebuggerHidden]
|
||||||
public bool TrySetCanceled(CancellationToken cancellationToken = default)
|
public bool TrySetCanceled(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return core.TrySetCanceled(cancellationToken);
|
return version == core.Version && core.TrySetCanceled(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
[DebuggerHidden]
|
[DebuggerHidden]
|
||||||
public bool TrySetException(Exception exception)
|
public bool TrySetException(Exception exception)
|
||||||
{
|
{
|
||||||
return core.TrySetException(exception);
|
return version == core.Version && core.TrySetException(exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
[DebuggerHidden]
|
[DebuggerHidden]
|
||||||
|
|
|
@ -28,7 +28,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
p.TrySetCanceled();
|
p.TrySetCanceled();
|
||||||
break;
|
break;
|
||||||
case TaskStatus.Faulted:
|
case TaskStatus.Faulted:
|
||||||
p.TrySetException(x.Exception);
|
p.TrySetException(x.Exception.InnerException ?? x.Exception);
|
||||||
break;
|
break;
|
||||||
case TaskStatus.RanToCompletion:
|
case TaskStatus.RanToCompletion:
|
||||||
p.TrySetResult(x.Result);
|
p.TrySetResult(x.Result);
|
||||||
|
@ -58,7 +58,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
p.TrySetCanceled();
|
p.TrySetCanceled();
|
||||||
break;
|
break;
|
||||||
case TaskStatus.Faulted:
|
case TaskStatus.Faulted:
|
||||||
p.TrySetException(x.Exception);
|
p.TrySetException(x.Exception.InnerException ?? x.Exception);
|
||||||
break;
|
break;
|
||||||
case TaskStatus.RanToCompletion:
|
case TaskStatus.RanToCompletion:
|
||||||
p.TrySetResult();
|
p.TrySetResult();
|
||||||
|
@ -201,6 +201,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
task.Forget();
|
||||||
return UniTask.FromCanceled(cancellationToken);
|
return UniTask.FromCanceled(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,6 +225,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
task.Forget();
|
||||||
return UniTask.FromCanceled<T>(cancellationToken);
|
return UniTask.FromCanceled<T>(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -454,7 +456,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Timeout with suppress OperationCanceledException. Returns (bool, IsCacneled).
|
/// Timeout with suppress OperationCanceledException. Returns (bool, IsCanceled).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static async UniTask<bool> TimeoutWithoutException(this UniTask task, TimeSpan timeout, DelayType delayType = DelayType.DeltaTime, PlayerLoopTiming timeoutCheckTiming = PlayerLoopTiming.Update, CancellationTokenSource taskCancellationTokenSource = null)
|
public static async UniTask<bool> TimeoutWithoutException(this UniTask task, TimeSpan timeout, DelayType delayType = DelayType.DeltaTime, PlayerLoopTiming timeoutCheckTiming = PlayerLoopTiming.Update, CancellationTokenSource taskCancellationTokenSource = null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -24,12 +24,17 @@ namespace Cysharp.Threading.Tasks
|
||||||
return AwaitForAllAssets(asyncOperation, null, PlayerLoopTiming.Update, cancellationToken: cancellationToken);
|
return AwaitForAllAssets(asyncOperation, null, PlayerLoopTiming.Update, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask<UnityEngine.Object[]> AwaitForAllAssets(this AssetBundleRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask<UnityEngine.Object[]> AwaitForAllAssets(this AssetBundleRequest asyncOperation, CancellationToken cancellationToken, bool cancelImmediately)
|
||||||
|
{
|
||||||
|
return AwaitForAllAssets(asyncOperation, progress: null, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UniTask<UnityEngine.Object[]> AwaitForAllAssets(this AssetBundleRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<UnityEngine.Object[]>(cancellationToken);
|
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<UnityEngine.Object[]>(cancellationToken);
|
||||||
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.allAssets);
|
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.allAssets);
|
||||||
return new UniTask<UnityEngine.Object[]>(AssetBundleRequestAllAssetsConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, out var token), token);
|
return new UniTask<UnityEngine.Object[]>(AssetBundleRequestAllAssetsConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, cancelImmediately, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct AssetBundleRequestAllAssetsAwaiter : ICriticalNotifyCompletion
|
public struct AssetBundleRequestAllAssetsAwaiter : ICriticalNotifyCompletion
|
||||||
|
@ -95,15 +100,20 @@ namespace Cysharp.Threading.Tasks
|
||||||
AssetBundleRequest asyncOperation;
|
AssetBundleRequest asyncOperation;
|
||||||
IProgress<float> progress;
|
IProgress<float> progress;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
bool cancelImmediately;
|
||||||
|
bool completed;
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<UnityEngine.Object[]> core;
|
UniTaskCompletionSourceCore<UnityEngine.Object[]> core;
|
||||||
|
|
||||||
|
Action<AsyncOperation> continuationAction;
|
||||||
|
|
||||||
AssetBundleRequestAllAssetsConfiguredSource()
|
AssetBundleRequestAllAssetsConfiguredSource()
|
||||||
{
|
{
|
||||||
|
continuationAction = Continuation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource<UnityEngine.Object[]> Create(AssetBundleRequest asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource<UnityEngine.Object[]> Create(AssetBundleRequest asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
@ -118,6 +128,19 @@ namespace Cysharp.Threading.Tasks
|
||||||
result.asyncOperation = asyncOperation;
|
result.asyncOperation = asyncOperation;
|
||||||
result.progress = progress;
|
result.progress = progress;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.cancelImmediately = cancelImmediately;
|
||||||
|
result.completed = false;
|
||||||
|
|
||||||
|
asyncOperation.completed += result.continuationAction;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var source = (AssetBundleRequestAllAssetsConfiguredSource)state;
|
||||||
|
source.core.TrySetCanceled(source.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
@ -134,9 +157,16 @@ namespace Cysharp.Threading.Tasks
|
||||||
return core.GetResult(token);
|
return core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
{
|
||||||
|
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
||||||
{
|
{
|
||||||
TryReturn();
|
TryReturn();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IUniTaskSource.GetResult(short token)
|
void IUniTaskSource.GetResult(short token)
|
||||||
|
@ -161,6 +191,12 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
public bool MoveNext()
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
|
// Already completed
|
||||||
|
if (completed || asyncOperation == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
core.TrySetCanceled(cancellationToken);
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
@ -188,8 +224,28 @@ namespace Cysharp.Threading.Tasks
|
||||||
asyncOperation = default;
|
asyncOperation = default;
|
||||||
progress = default;
|
progress = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
|
cancelImmediately = default;
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Continuation(AsyncOperation _)
|
||||||
|
{
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
completed = true;
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
core.TrySetResult(asyncOperation.allAssets);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,10 +20,15 @@ namespace Cysharp.Threading.Tasks
|
||||||
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask<AsyncGPUReadbackRequest> ToUniTask(this AsyncGPUReadbackRequest asyncOperation, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask<AsyncGPUReadbackRequest> WithCancellation(this AsyncGPUReadbackRequest asyncOperation, CancellationToken cancellationToken, bool cancelImmediately)
|
||||||
|
{
|
||||||
|
return ToUniTask(asyncOperation, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UniTask<AsyncGPUReadbackRequest> ToUniTask(this AsyncGPUReadbackRequest asyncOperation, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
if (asyncOperation.done) return UniTask.FromResult(asyncOperation);
|
if (asyncOperation.done) return UniTask.FromResult(asyncOperation);
|
||||||
return new UniTask<AsyncGPUReadbackRequest>(AsyncGPUReadbackRequestAwaiterConfiguredSource.Create(asyncOperation, timing, cancellationToken, out var token), token);
|
return new UniTask<AsyncGPUReadbackRequest>(AsyncGPUReadbackRequestAwaiterConfiguredSource.Create(asyncOperation, timing, cancellationToken, cancelImmediately, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class AsyncGPUReadbackRequestAwaiterConfiguredSource : IUniTaskSource<AsyncGPUReadbackRequest>, IPlayerLoopItem, ITaskPoolNode<AsyncGPUReadbackRequestAwaiterConfiguredSource>
|
sealed class AsyncGPUReadbackRequestAwaiterConfiguredSource : IUniTaskSource<AsyncGPUReadbackRequest>, IPlayerLoopItem, ITaskPoolNode<AsyncGPUReadbackRequestAwaiterConfiguredSource>
|
||||||
|
@ -39,15 +44,15 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
AsyncGPUReadbackRequest asyncOperation;
|
AsyncGPUReadbackRequest asyncOperation;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
bool cancelImmediately;
|
||||||
UniTaskCompletionSourceCore<AsyncGPUReadbackRequest> core;
|
UniTaskCompletionSourceCore<AsyncGPUReadbackRequest> core;
|
||||||
|
|
||||||
AsyncGPUReadbackRequestAwaiterConfiguredSource()
|
AsyncGPUReadbackRequestAwaiterConfiguredSource()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource<AsyncGPUReadbackRequest> Create(AsyncGPUReadbackRequest asyncOperation, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource<AsyncGPUReadbackRequest> Create(AsyncGPUReadbackRequest asyncOperation, PlayerLoopTiming timing, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
@ -61,6 +66,16 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
result.asyncOperation = asyncOperation;
|
result.asyncOperation = asyncOperation;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.cancelImmediately = cancelImmediately;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var promise = (AsyncGPUReadbackRequestAwaiterConfiguredSource)state;
|
||||||
|
promise.core.TrySetCanceled(promise.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
@ -77,9 +92,16 @@ namespace Cysharp.Threading.Tasks
|
||||||
return core.GetResult(token);
|
return core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
{
|
||||||
|
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
||||||
{
|
{
|
||||||
TryReturn();
|
TryReturn();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IUniTaskSource.GetResult(short token)
|
void IUniTaskSource.GetResult(short token)
|
||||||
|
@ -131,6 +153,8 @@ namespace Cysharp.Threading.Tasks
|
||||||
core.Reset();
|
core.Reset();
|
||||||
asyncOperation = default;
|
asyncOperation = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
|
cancelImmediately = default;
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,386 @@
|
||||||
|
// AsyncInstantiateOperation was added since Unity 2022.3.20 / 2023.3.0b7
|
||||||
|
#if UNITY_2022_3 && !(UNITY_2022_3_0 || UNITY_2022_3_1 || UNITY_2022_3_2 || UNITY_2022_3_3 || UNITY_2022_3_4 || UNITY_2022_3_5 || UNITY_2022_3_6 || UNITY_2022_3_7 || UNITY_2022_3_8 || UNITY_2022_3_9 || UNITY_2022_3_10 || UNITY_2022_3_11 || UNITY_2022_3_12 || UNITY_2022_3_13 || UNITY_2022_3_14 || UNITY_2022_3_15 || UNITY_2022_3_16 || UNITY_2022_3_17 || UNITY_2022_3_18 || UNITY_2022_3_19)
|
||||||
|
#define UNITY_2022_SUPPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if UNITY_2022_SUPPORT || UNITY_2023_3_OR_NEWER
|
||||||
|
|
||||||
|
using Cysharp.Threading.Tasks.Internal;
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Cysharp.Threading.Tasks
|
||||||
|
{
|
||||||
|
public static class AsyncInstantiateOperationExtensions
|
||||||
|
{
|
||||||
|
// AsyncInstantiateOperation<T> has GetAwaiter so no need to impl
|
||||||
|
// public static UniTask<T[]>.Awaiter GetAwaiter<T>(this AsyncInstantiateOperation<T> operation) where T : Object
|
||||||
|
|
||||||
|
public static UniTask<UnityEngine.Object[]> WithCancellation<T>(this AsyncInstantiateOperation asyncOperation, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UniTask<UnityEngine.Object[]> WithCancellation<T>(this AsyncInstantiateOperation asyncOperation, CancellationToken cancellationToken, bool cancelImmediately)
|
||||||
|
{
|
||||||
|
return ToUniTask(asyncOperation, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UniTask<UnityEngine.Object[]> ToUniTask(this AsyncInstantiateOperation asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
||||||
|
{
|
||||||
|
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||||
|
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<UnityEngine.Object[]>(cancellationToken);
|
||||||
|
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.Result);
|
||||||
|
return new UniTask<UnityEngine.Object[]>(AsyncInstantiateOperationConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, cancelImmediately, out var token), token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UniTask<T[]> WithCancellation<T>(this AsyncInstantiateOperation<T> asyncOperation, CancellationToken cancellationToken)
|
||||||
|
where T : UnityEngine.Object
|
||||||
|
{
|
||||||
|
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UniTask<T[]> WithCancellation<T>(this AsyncInstantiateOperation<T> asyncOperation, CancellationToken cancellationToken, bool cancelImmediately)
|
||||||
|
where T : UnityEngine.Object
|
||||||
|
{
|
||||||
|
return ToUniTask(asyncOperation, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UniTask<T[]> ToUniTask<T>(this AsyncInstantiateOperation<T> asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
||||||
|
where T : UnityEngine.Object
|
||||||
|
{
|
||||||
|
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||||
|
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<T[]>(cancellationToken);
|
||||||
|
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.Result);
|
||||||
|
return new UniTask<T[]>(AsyncInstantiateOperationConfiguredSource<T>.Create(asyncOperation, timing, progress, cancellationToken, cancelImmediately, out var token), token);
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class AsyncInstantiateOperationConfiguredSource : IUniTaskSource<UnityEngine.Object[]>, IPlayerLoopItem, ITaskPoolNode<AsyncInstantiateOperationConfiguredSource>
|
||||||
|
{
|
||||||
|
static TaskPool<AsyncInstantiateOperationConfiguredSource> pool;
|
||||||
|
AsyncInstantiateOperationConfiguredSource nextNode;
|
||||||
|
public ref AsyncInstantiateOperationConfiguredSource NextNode => ref nextNode;
|
||||||
|
|
||||||
|
static AsyncInstantiateOperationConfiguredSource()
|
||||||
|
{
|
||||||
|
TaskPool.RegisterSizeGetter(typeof(AsyncInstantiateOperationConfiguredSource), () => pool.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
AsyncInstantiateOperation asyncOperation;
|
||||||
|
IProgress<float> progress;
|
||||||
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
bool cancelImmediately;
|
||||||
|
bool completed;
|
||||||
|
|
||||||
|
UniTaskCompletionSourceCore<UnityEngine.Object[]> core;
|
||||||
|
|
||||||
|
Action<AsyncOperation> continuationAction;
|
||||||
|
|
||||||
|
AsyncInstantiateOperationConfiguredSource()
|
||||||
|
{
|
||||||
|
continuationAction = Continuation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IUniTaskSource<UnityEngine.Object[]> Create(AsyncInstantiateOperation asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
return AutoResetUniTaskCompletionSource<UnityEngine.Object[]>.CreateFromCanceled(cancellationToken, out token);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pool.TryPop(out var result))
|
||||||
|
{
|
||||||
|
result = new AsyncInstantiateOperationConfiguredSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
result.asyncOperation = asyncOperation;
|
||||||
|
result.progress = progress;
|
||||||
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.cancelImmediately = cancelImmediately;
|
||||||
|
result.completed = false;
|
||||||
|
|
||||||
|
asyncOperation.completed += result.continuationAction;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var source = (AsyncInstantiateOperationConfiguredSource)state;
|
||||||
|
source.core.TrySetCanceled(source.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
PlayerLoopHelper.AddAction(timing, result);
|
||||||
|
|
||||||
|
token = result.core.Version;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UnityEngine.Object[] GetResult(short token)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return core.GetResult(token);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IUniTaskSource.GetResult(short token)
|
||||||
|
{
|
||||||
|
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 bool MoveNext()
|
||||||
|
{
|
||||||
|
// Already completed
|
||||||
|
if (completed || asyncOperation == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (progress != null)
|
||||||
|
{
|
||||||
|
progress.Report(asyncOperation.progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (asyncOperation.isDone)
|
||||||
|
{
|
||||||
|
core.TrySetResult(asyncOperation.Result);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TryReturn()
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
core.Reset();
|
||||||
|
asyncOperation.completed -= continuationAction;
|
||||||
|
asyncOperation = default;
|
||||||
|
progress = default;
|
||||||
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
|
cancelImmediately = default;
|
||||||
|
return pool.TryPush(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Continuation(AsyncOperation _)
|
||||||
|
{
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
completed = true;
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
core.TrySetResult(asyncOperation.Result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class AsyncInstantiateOperationConfiguredSource<T> : IUniTaskSource<T[]>, IPlayerLoopItem, ITaskPoolNode<AsyncInstantiateOperationConfiguredSource<T>>
|
||||||
|
where T : UnityEngine.Object
|
||||||
|
{
|
||||||
|
static TaskPool<AsyncInstantiateOperationConfiguredSource<T>> pool;
|
||||||
|
AsyncInstantiateOperationConfiguredSource<T> nextNode;
|
||||||
|
public ref AsyncInstantiateOperationConfiguredSource<T> NextNode => ref nextNode;
|
||||||
|
|
||||||
|
static AsyncInstantiateOperationConfiguredSource()
|
||||||
|
{
|
||||||
|
TaskPool.RegisterSizeGetter(typeof(AsyncInstantiateOperationConfiguredSource<T>), () => pool.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
AsyncInstantiateOperation<T> asyncOperation;
|
||||||
|
IProgress<float> progress;
|
||||||
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
bool cancelImmediately;
|
||||||
|
bool completed;
|
||||||
|
|
||||||
|
UniTaskCompletionSourceCore<T[]> core;
|
||||||
|
|
||||||
|
Action<AsyncOperation> continuationAction;
|
||||||
|
|
||||||
|
AsyncInstantiateOperationConfiguredSource()
|
||||||
|
{
|
||||||
|
continuationAction = Continuation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IUniTaskSource<T[]> Create(AsyncInstantiateOperation<T> asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
return AutoResetUniTaskCompletionSource<T[]>.CreateFromCanceled(cancellationToken, out token);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pool.TryPop(out var result))
|
||||||
|
{
|
||||||
|
result = new AsyncInstantiateOperationConfiguredSource<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
result.asyncOperation = asyncOperation;
|
||||||
|
result.progress = progress;
|
||||||
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.cancelImmediately = cancelImmediately;
|
||||||
|
result.completed = false;
|
||||||
|
|
||||||
|
asyncOperation.completed += result.continuationAction;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var source = (AsyncInstantiateOperationConfiguredSource<T>)state;
|
||||||
|
source.core.TrySetCanceled(source.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
PlayerLoopHelper.AddAction(timing, result);
|
||||||
|
|
||||||
|
token = result.core.Version;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T[] GetResult(short token)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return core.GetResult(token);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IUniTaskSource.GetResult(short token)
|
||||||
|
{
|
||||||
|
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 bool MoveNext()
|
||||||
|
{
|
||||||
|
// Already completed
|
||||||
|
if (completed || asyncOperation == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (progress != null)
|
||||||
|
{
|
||||||
|
progress.Report(asyncOperation.progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (asyncOperation.isDone)
|
||||||
|
{
|
||||||
|
core.TrySetResult(asyncOperation.Result);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TryReturn()
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
core.Reset();
|
||||||
|
asyncOperation.completed -= continuationAction;
|
||||||
|
asyncOperation = default;
|
||||||
|
progress = default;
|
||||||
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
|
cancelImmediately = default;
|
||||||
|
return pool.TryPush(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Continuation(AsyncOperation _)
|
||||||
|
{
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
completed = true;
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
core.TrySetResult(asyncOperation.Result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,8 +1,7 @@
|
||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 3518da33b6245d341a0ef3670ee9268b
|
guid: 8321f4244edfdcd4798b4fcc92a736c9
|
||||||
timeCreated: 1488689723
|
|
||||||
licenseType: Pro
|
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
defaultReferences: []
|
defaultReferences: []
|
||||||
executionOrder: 0
|
executionOrder: 0
|
|
@ -17,7 +17,6 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
#if !UNITY_2023_1_OR_NEWER
|
#if !UNITY_2023_1_OR_NEWER
|
||||||
// from Unity2023.1.0a15, AsyncOperationAwaitableExtensions.GetAwaiter is defined in UnityEngine.
|
// from Unity2023.1.0a15, AsyncOperationAwaitableExtensions.GetAwaiter is defined in UnityEngine.
|
||||||
|
|
||||||
public static AsyncOperationAwaiter GetAwaiter(this AsyncOperation asyncOperation)
|
public static AsyncOperationAwaiter GetAwaiter(this AsyncOperation asyncOperation)
|
||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||||
|
@ -30,12 +29,17 @@ namespace Cysharp.Threading.Tasks
|
||||||
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask ToUniTask(this AsyncOperation asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask WithCancellation(this AsyncOperation asyncOperation, CancellationToken cancellationToken, bool cancelImmediately)
|
||||||
|
{
|
||||||
|
return ToUniTask(asyncOperation, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UniTask ToUniTask(this AsyncOperation asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled(cancellationToken);
|
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled(cancellationToken);
|
||||||
if (asyncOperation.isDone) return UniTask.CompletedTask;
|
if (asyncOperation.isDone) return UniTask.CompletedTask;
|
||||||
return new UniTask(AsyncOperationConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, out var token), token);
|
return new UniTask(AsyncOperationConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, cancelImmediately, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct AsyncOperationAwaiter : ICriticalNotifyCompletion
|
public struct AsyncOperationAwaiter : ICriticalNotifyCompletion
|
||||||
|
@ -92,15 +96,20 @@ namespace Cysharp.Threading.Tasks
|
||||||
AsyncOperation asyncOperation;
|
AsyncOperation asyncOperation;
|
||||||
IProgress<float> progress;
|
IProgress<float> progress;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
bool cancelImmediately;
|
||||||
|
bool completed;
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<AsyncUnit> core;
|
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||||
|
|
||||||
|
Action<AsyncOperation> continuationAction;
|
||||||
|
|
||||||
AsyncOperationConfiguredSource()
|
AsyncOperationConfiguredSource()
|
||||||
{
|
{
|
||||||
|
continuationAction = Continuation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource Create(AsyncOperation asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource Create(AsyncOperation asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
@ -115,6 +124,19 @@ namespace Cysharp.Threading.Tasks
|
||||||
result.asyncOperation = asyncOperation;
|
result.asyncOperation = asyncOperation;
|
||||||
result.progress = progress;
|
result.progress = progress;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.cancelImmediately = cancelImmediately;
|
||||||
|
result.completed = false;
|
||||||
|
|
||||||
|
asyncOperation.completed += result.continuationAction;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var source = (AsyncOperationConfiguredSource)state;
|
||||||
|
source.core.TrySetCanceled(source.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
@ -131,9 +153,16 @@ namespace Cysharp.Threading.Tasks
|
||||||
core.GetResult(token);
|
core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
{
|
||||||
|
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
||||||
{
|
{
|
||||||
TryReturn();
|
TryReturn();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -154,6 +183,12 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
public bool MoveNext()
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
|
// Already completed
|
||||||
|
if (completed || asyncOperation == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
core.TrySetCanceled(cancellationToken);
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
@ -178,11 +213,31 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
core.Reset();
|
core.Reset();
|
||||||
|
asyncOperation.completed -= continuationAction;
|
||||||
asyncOperation = default;
|
asyncOperation = default;
|
||||||
progress = default;
|
progress = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
|
cancelImmediately = default;
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Continuation(AsyncOperation _)
|
||||||
|
{
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
completed = true;
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
core.TrySetResult(AsyncUnit.Default);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -200,12 +255,17 @@ namespace Cysharp.Threading.Tasks
|
||||||
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask<UnityEngine.Object> ToUniTask(this ResourceRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask<UnityEngine.Object> WithCancellation(this ResourceRequest asyncOperation, CancellationToken cancellationToken, bool cancelImmediately)
|
||||||
|
{
|
||||||
|
return ToUniTask(asyncOperation, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UniTask<UnityEngine.Object> ToUniTask(this ResourceRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<UnityEngine.Object>(cancellationToken);
|
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<UnityEngine.Object>(cancellationToken);
|
||||||
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.asset);
|
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.asset);
|
||||||
return new UniTask<UnityEngine.Object>(ResourceRequestConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, out var token), token);
|
return new UniTask<UnityEngine.Object>(ResourceRequestConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, cancelImmediately, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct ResourceRequestAwaiter : ICriticalNotifyCompletion
|
public struct ResourceRequestAwaiter : ICriticalNotifyCompletion
|
||||||
|
@ -266,15 +326,20 @@ namespace Cysharp.Threading.Tasks
|
||||||
ResourceRequest asyncOperation;
|
ResourceRequest asyncOperation;
|
||||||
IProgress<float> progress;
|
IProgress<float> progress;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
bool cancelImmediately;
|
||||||
|
bool completed;
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<UnityEngine.Object> core;
|
UniTaskCompletionSourceCore<UnityEngine.Object> core;
|
||||||
|
|
||||||
|
Action<AsyncOperation> continuationAction;
|
||||||
|
|
||||||
ResourceRequestConfiguredSource()
|
ResourceRequestConfiguredSource()
|
||||||
{
|
{
|
||||||
|
continuationAction = Continuation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource<UnityEngine.Object> Create(ResourceRequest asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource<UnityEngine.Object> Create(ResourceRequest asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
@ -289,6 +354,19 @@ namespace Cysharp.Threading.Tasks
|
||||||
result.asyncOperation = asyncOperation;
|
result.asyncOperation = asyncOperation;
|
||||||
result.progress = progress;
|
result.progress = progress;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.cancelImmediately = cancelImmediately;
|
||||||
|
result.completed = false;
|
||||||
|
|
||||||
|
asyncOperation.completed += result.continuationAction;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var source = (ResourceRequestConfiguredSource)state;
|
||||||
|
source.core.TrySetCanceled(source.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
@ -305,9 +383,16 @@ namespace Cysharp.Threading.Tasks
|
||||||
return core.GetResult(token);
|
return core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
{
|
||||||
|
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
||||||
{
|
{
|
||||||
TryReturn();
|
TryReturn();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IUniTaskSource.GetResult(short token)
|
void IUniTaskSource.GetResult(short token)
|
||||||
|
@ -332,6 +417,12 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
public bool MoveNext()
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
|
// Already completed
|
||||||
|
if (completed || asyncOperation == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
core.TrySetCanceled(cancellationToken);
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
@ -356,11 +447,31 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
core.Reset();
|
core.Reset();
|
||||||
|
asyncOperation.completed -= continuationAction;
|
||||||
asyncOperation = default;
|
asyncOperation = default;
|
||||||
progress = default;
|
progress = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
|
cancelImmediately = default;
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Continuation(AsyncOperation _)
|
||||||
|
{
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
completed = true;
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
core.TrySetResult(asyncOperation.asset);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -379,12 +490,17 @@ namespace Cysharp.Threading.Tasks
|
||||||
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask<UnityEngine.Object> ToUniTask(this AssetBundleRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask<UnityEngine.Object> WithCancellation(this AssetBundleRequest asyncOperation, CancellationToken cancellationToken, bool cancelImmediately)
|
||||||
|
{
|
||||||
|
return ToUniTask(asyncOperation, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UniTask<UnityEngine.Object> ToUniTask(this AssetBundleRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<UnityEngine.Object>(cancellationToken);
|
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<UnityEngine.Object>(cancellationToken);
|
||||||
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.asset);
|
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.asset);
|
||||||
return new UniTask<UnityEngine.Object>(AssetBundleRequestConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, out var token), token);
|
return new UniTask<UnityEngine.Object>(AssetBundleRequestConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, cancelImmediately, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct AssetBundleRequestAwaiter : ICriticalNotifyCompletion
|
public struct AssetBundleRequestAwaiter : ICriticalNotifyCompletion
|
||||||
|
@ -445,15 +561,20 @@ namespace Cysharp.Threading.Tasks
|
||||||
AssetBundleRequest asyncOperation;
|
AssetBundleRequest asyncOperation;
|
||||||
IProgress<float> progress;
|
IProgress<float> progress;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
bool cancelImmediately;
|
||||||
|
bool completed;
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<UnityEngine.Object> core;
|
UniTaskCompletionSourceCore<UnityEngine.Object> core;
|
||||||
|
|
||||||
|
Action<AsyncOperation> continuationAction;
|
||||||
|
|
||||||
AssetBundleRequestConfiguredSource()
|
AssetBundleRequestConfiguredSource()
|
||||||
{
|
{
|
||||||
|
continuationAction = Continuation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource<UnityEngine.Object> Create(AssetBundleRequest asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource<UnityEngine.Object> Create(AssetBundleRequest asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
@ -468,6 +589,19 @@ namespace Cysharp.Threading.Tasks
|
||||||
result.asyncOperation = asyncOperation;
|
result.asyncOperation = asyncOperation;
|
||||||
result.progress = progress;
|
result.progress = progress;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.cancelImmediately = cancelImmediately;
|
||||||
|
result.completed = false;
|
||||||
|
|
||||||
|
asyncOperation.completed += result.continuationAction;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var source = (AssetBundleRequestConfiguredSource)state;
|
||||||
|
source.core.TrySetCanceled(source.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
@ -484,9 +618,16 @@ namespace Cysharp.Threading.Tasks
|
||||||
return core.GetResult(token);
|
return core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
{
|
||||||
|
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
||||||
{
|
{
|
||||||
TryReturn();
|
TryReturn();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IUniTaskSource.GetResult(short token)
|
void IUniTaskSource.GetResult(short token)
|
||||||
|
@ -511,6 +652,12 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
public bool MoveNext()
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
|
// Already completed
|
||||||
|
if (completed || asyncOperation == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
core.TrySetCanceled(cancellationToken);
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
@ -535,11 +682,31 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
core.Reset();
|
core.Reset();
|
||||||
|
asyncOperation.completed -= continuationAction;
|
||||||
asyncOperation = default;
|
asyncOperation = default;
|
||||||
progress = default;
|
progress = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
|
cancelImmediately = default;
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Continuation(AsyncOperation _)
|
||||||
|
{
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
completed = true;
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
core.TrySetResult(asyncOperation.asset);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -559,12 +726,17 @@ namespace Cysharp.Threading.Tasks
|
||||||
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask<AssetBundle> ToUniTask(this AssetBundleCreateRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask<AssetBundle> WithCancellation(this AssetBundleCreateRequest asyncOperation, CancellationToken cancellationToken, bool cancelImmediately)
|
||||||
|
{
|
||||||
|
return ToUniTask(asyncOperation, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UniTask<AssetBundle> ToUniTask(this AssetBundleCreateRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<AssetBundle>(cancellationToken);
|
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<AssetBundle>(cancellationToken);
|
||||||
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.assetBundle);
|
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.assetBundle);
|
||||||
return new UniTask<AssetBundle>(AssetBundleCreateRequestConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, out var token), token);
|
return new UniTask<AssetBundle>(AssetBundleCreateRequestConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, cancelImmediately, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct AssetBundleCreateRequestAwaiter : ICriticalNotifyCompletion
|
public struct AssetBundleCreateRequestAwaiter : ICriticalNotifyCompletion
|
||||||
|
@ -625,15 +797,20 @@ namespace Cysharp.Threading.Tasks
|
||||||
AssetBundleCreateRequest asyncOperation;
|
AssetBundleCreateRequest asyncOperation;
|
||||||
IProgress<float> progress;
|
IProgress<float> progress;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
bool cancelImmediately;
|
||||||
|
bool completed;
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<AssetBundle> core;
|
UniTaskCompletionSourceCore<AssetBundle> core;
|
||||||
|
|
||||||
|
Action<AsyncOperation> continuationAction;
|
||||||
|
|
||||||
AssetBundleCreateRequestConfiguredSource()
|
AssetBundleCreateRequestConfiguredSource()
|
||||||
{
|
{
|
||||||
|
continuationAction = Continuation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource<AssetBundle> Create(AssetBundleCreateRequest asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource<AssetBundle> Create(AssetBundleCreateRequest asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
@ -648,6 +825,19 @@ namespace Cysharp.Threading.Tasks
|
||||||
result.asyncOperation = asyncOperation;
|
result.asyncOperation = asyncOperation;
|
||||||
result.progress = progress;
|
result.progress = progress;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.cancelImmediately = cancelImmediately;
|
||||||
|
result.completed = false;
|
||||||
|
|
||||||
|
asyncOperation.completed += result.continuationAction;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var source = (AssetBundleCreateRequestConfiguredSource)state;
|
||||||
|
source.core.TrySetCanceled(source.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
@ -664,9 +854,16 @@ namespace Cysharp.Threading.Tasks
|
||||||
return core.GetResult(token);
|
return core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
{
|
||||||
|
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
||||||
{
|
{
|
||||||
TryReturn();
|
TryReturn();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IUniTaskSource.GetResult(short token)
|
void IUniTaskSource.GetResult(short token)
|
||||||
|
@ -691,6 +888,12 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
public bool MoveNext()
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
|
// Already completed
|
||||||
|
if (completed || asyncOperation == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
core.TrySetCanceled(cancellationToken);
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
@ -715,11 +918,31 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
core.Reset();
|
core.Reset();
|
||||||
|
asyncOperation.completed -= continuationAction;
|
||||||
asyncOperation = default;
|
asyncOperation = default;
|
||||||
progress = default;
|
progress = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
|
cancelImmediately = default;
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Continuation(AsyncOperation _)
|
||||||
|
{
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
completed = true;
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
core.TrySetResult(asyncOperation.assetBundle);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -739,7 +962,12 @@ namespace Cysharp.Threading.Tasks
|
||||||
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask<UnityWebRequest> ToUniTask(this UnityWebRequestAsyncOperation asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask<UnityWebRequest> WithCancellation(this UnityWebRequestAsyncOperation asyncOperation, CancellationToken cancellationToken, bool cancelImmediately)
|
||||||
|
{
|
||||||
|
return ToUniTask(asyncOperation, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UniTask<UnityWebRequest> ToUniTask(this UnityWebRequestAsyncOperation asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<UnityWebRequest>(cancellationToken);
|
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<UnityWebRequest>(cancellationToken);
|
||||||
|
@ -751,7 +979,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
return UniTask.FromResult(asyncOperation.webRequest);
|
return UniTask.FromResult(asyncOperation.webRequest);
|
||||||
}
|
}
|
||||||
return new UniTask<UnityWebRequest>(UnityWebRequestAsyncOperationConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, out var token), token);
|
return new UniTask<UnityWebRequest>(UnityWebRequestAsyncOperationConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, cancelImmediately, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct UnityWebRequestAsyncOperationAwaiter : ICriticalNotifyCompletion
|
public struct UnityWebRequestAsyncOperationAwaiter : ICriticalNotifyCompletion
|
||||||
|
@ -820,15 +1048,20 @@ namespace Cysharp.Threading.Tasks
|
||||||
UnityWebRequestAsyncOperation asyncOperation;
|
UnityWebRequestAsyncOperation asyncOperation;
|
||||||
IProgress<float> progress;
|
IProgress<float> progress;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
bool cancelImmediately;
|
||||||
|
bool completed;
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<UnityWebRequest> core;
|
UniTaskCompletionSourceCore<UnityWebRequest> core;
|
||||||
|
|
||||||
|
Action<AsyncOperation> continuationAction;
|
||||||
|
|
||||||
UnityWebRequestAsyncOperationConfiguredSource()
|
UnityWebRequestAsyncOperationConfiguredSource()
|
||||||
{
|
{
|
||||||
|
continuationAction = Continuation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IUniTaskSource<UnityWebRequest> Create(UnityWebRequestAsyncOperation asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, out short token)
|
public static IUniTaskSource<UnityWebRequest> Create(UnityWebRequestAsyncOperation asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
@ -843,6 +1076,20 @@ namespace Cysharp.Threading.Tasks
|
||||||
result.asyncOperation = asyncOperation;
|
result.asyncOperation = asyncOperation;
|
||||||
result.progress = progress;
|
result.progress = progress;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.cancelImmediately = cancelImmediately;
|
||||||
|
result.completed = false;
|
||||||
|
|
||||||
|
asyncOperation.completed += result.continuationAction;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var source = (UnityWebRequestAsyncOperationConfiguredSource)state;
|
||||||
|
source.asyncOperation.webRequest.Abort();
|
||||||
|
source.core.TrySetCanceled(source.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
@ -859,9 +1106,16 @@ namespace Cysharp.Threading.Tasks
|
||||||
return core.GetResult(token);
|
return core.GetResult(token);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
{
|
||||||
|
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
||||||
{
|
{
|
||||||
TryReturn();
|
TryReturn();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IUniTaskSource.GetResult(short token)
|
void IUniTaskSource.GetResult(short token)
|
||||||
|
@ -886,6 +1140,12 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
public bool MoveNext()
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
|
// Already completed
|
||||||
|
if (completed || asyncOperation == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
asyncOperation.webRequest.Abort();
|
asyncOperation.webRequest.Abort();
|
||||||
|
@ -918,11 +1178,35 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
core.Reset();
|
core.Reset();
|
||||||
|
asyncOperation.completed -= continuationAction;
|
||||||
asyncOperation = default;
|
asyncOperation = default;
|
||||||
progress = default;
|
progress = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
|
cancelImmediately = default;
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Continuation(AsyncOperation _)
|
||||||
|
{
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
completed = true;
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
}
|
||||||
|
else if (asyncOperation.webRequest.IsError())
|
||||||
|
{
|
||||||
|
core.TrySetException(new UnityWebRequestException(asyncOperation.webRequest));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
core.TrySetResult(asyncOperation.webRequest);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
Func<string, string> ToUniTaskReturnType = x => (x == "void") ? "UniTask" : $"UniTask<{x}>";
|
Func<string, string> ToUniTaskReturnType = x => (x == "void") ? "UniTask" : $"UniTask<{x}>";
|
||||||
Func<string, string> ToIUniTaskSourceReturnType = x => (x == "void") ? "IUniTaskSource" : $"IUniTaskSource<{x}>";
|
Func<string, string> ToIUniTaskSourceReturnType = x => (x == "void") ? "IUniTaskSource" : $"IUniTaskSource<{x}>";
|
||||||
|
Func<(string typeName, string returnType, string returnField), bool> IsAsyncOperationBase = x => x.typeName == "AsyncOperation";
|
||||||
Func<(string typeName, string returnType, string returnField), bool> IsUnityWebRequest = x => x.returnType == "UnityWebRequest";
|
Func<(string typeName, string returnType, string returnField), bool> IsUnityWebRequest = x => x.returnType == "UnityWebRequest";
|
||||||
Func<(string typeName, string returnType, string returnField), bool> IsAssetBundleModule = x => x.typeName == "AssetBundleRequest" || x.typeName == "AssetBundleCreateRequest";
|
Func<(string typeName, string returnType, string returnField), bool> IsAssetBundleModule = x => x.typeName == "AssetBundleRequest" || x.typeName == "AssetBundleCreateRequest";
|
||||||
Func<(string typeName, string returnType, string returnField), bool> IsVoid = x => x.returnType == "void";
|
Func<(string typeName, string returnType, string returnField), bool> IsVoid = x => x.returnType == "void";
|
||||||
|
@ -43,18 +44,30 @@ namespace Cysharp.Threading.Tasks
|
||||||
<# } #>
|
<# } #>
|
||||||
#region <#= t.typeName #>
|
#region <#= t.typeName #>
|
||||||
|
|
||||||
|
<# if (IsAsyncOperationBase(t)) { #>
|
||||||
|
#if !UNITY_2023_1_OR_NEWER
|
||||||
|
// from Unity2023.1.0a15, AsyncOperationAwaitableExtensions.GetAwaiter is defined in UnityEngine.
|
||||||
|
<# } #>
|
||||||
public static <#= t.typeName #>Awaiter GetAwaiter(this <#= t.typeName #> asyncOperation)
|
public static <#= t.typeName #>Awaiter GetAwaiter(this <#= t.typeName #> asyncOperation)
|
||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||||
return new <#= t.typeName #>Awaiter(asyncOperation);
|
return new <#= t.typeName #>Awaiter(asyncOperation);
|
||||||
}
|
}
|
||||||
|
<# if (IsAsyncOperationBase(t)) { #>
|
||||||
|
#endif
|
||||||
|
<# } #>
|
||||||
|
|
||||||
public static <#= ToUniTaskReturnType(t.returnType) #> WithCancellation(this <#= t.typeName #> asyncOperation, CancellationToken cancellationToken)
|
public static <#= ToUniTaskReturnType(t.returnType) #> WithCancellation(this <#= t.typeName #> asyncOperation, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <#= ToUniTaskReturnType(t.returnType) #> ToUniTask(this <#= t.typeName #> asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static <#= ToUniTaskReturnType(t.returnType) #> WithCancellation(this <#= t.typeName #> asyncOperation, CancellationToken cancellationToken, bool cancelImmediately)
|
||||||
|
{
|
||||||
|
return ToUniTask(asyncOperation, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <#= ToUniTaskReturnType(t.returnType) #> ToUniTask(this <#= t.typeName #> asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false)
|
||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
||||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<#= IsVoid(t) ? "" : "<" + t.returnType + ">" #>(cancellationToken);
|
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<#= IsVoid(t) ? "" : "<" + t.returnType + ">" #>(cancellationToken);
|
||||||
|
@ -70,7 +83,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
<# } else { #>
|
<# } else { #>
|
||||||
if (asyncOperation.isDone) return <#= IsVoid(t) ? "UniTask.CompletedTask" : $"UniTask.FromResult(asyncOperation.{t.returnField})" #>;
|
if (asyncOperation.isDone) return <#= IsVoid(t) ? "UniTask.CompletedTask" : $"UniTask.FromResult(asyncOperation.{t.returnField})" #>;
|
||||||
<# } #>
|
<# } #>
|
||||||
return new <#= ToUniTaskReturnType(t.returnType) #>(<#= t.typeName #>ConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, out var token), token);
|
return new <#= ToUniTaskReturnType(t.returnType) #>(<#= t.typeName #>ConfiguredSource.Create(asyncOperation, timing, progress, cancellationToken, cancelImmediately, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct <#= t.typeName #>Awaiter : ICriticalNotifyCompletion
|
public struct <#= t.typeName #>Awaiter : ICriticalNotifyCompletion
|
||||||
|
@ -151,15 +164,20 @@ namespace Cysharp.Threading.Tasks
|
||||||
<#= t.typeName #> asyncOperation;
|
<#= t.typeName #> asyncOperation;
|
||||||
IProgress<float> progress;
|
IProgress<float> progress;
|
||||||
CancellationToken cancellationToken;
|
CancellationToken cancellationToken;
|
||||||
|
CancellationTokenRegistration cancellationTokenRegistration;
|
||||||
|
bool cancelImmediately;
|
||||||
|
bool completed;
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<<#= IsVoid(t) ? "AsyncUnit" : t.returnType #>> core;
|
UniTaskCompletionSourceCore<<#= IsVoid(t) ? "AsyncUnit" : t.returnType #>> core;
|
||||||
|
|
||||||
|
Action<AsyncOperation> continuationAction;
|
||||||
|
|
||||||
<#= t.typeName #>ConfiguredSource()
|
<#= t.typeName #>ConfiguredSource()
|
||||||
{
|
{
|
||||||
|
continuationAction = Continuation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <#= ToIUniTaskSourceReturnType(t.returnType) #> Create(<#= t.typeName #> asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, out short token)
|
public static <#= ToIUniTaskSourceReturnType(t.returnType) #> Create(<#= t.typeName #> asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, bool cancelImmediately, out short token)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
@ -174,6 +192,22 @@ namespace Cysharp.Threading.Tasks
|
||||||
result.asyncOperation = asyncOperation;
|
result.asyncOperation = asyncOperation;
|
||||||
result.progress = progress;
|
result.progress = progress;
|
||||||
result.cancellationToken = cancellationToken;
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.cancelImmediately = cancelImmediately;
|
||||||
|
result.completed = false;
|
||||||
|
|
||||||
|
asyncOperation.completed += result.continuationAction;
|
||||||
|
|
||||||
|
if (cancelImmediately && cancellationToken.CanBeCanceled)
|
||||||
|
{
|
||||||
|
result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
|
||||||
|
{
|
||||||
|
var source = (<#= t.typeName #>ConfiguredSource)state;
|
||||||
|
<# if(IsUnityWebRequest(t)) { #>
|
||||||
|
source.asyncOperation.webRequest.Abort();
|
||||||
|
<# } #>
|
||||||
|
source.core.TrySetCanceled(source.cancellationToken);
|
||||||
|
}, result);
|
||||||
|
}
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
@ -194,10 +228,13 @@ namespace Cysharp.Threading.Tasks
|
||||||
<# } #>
|
<# } #>
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
{
|
||||||
|
if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
|
||||||
{
|
{
|
||||||
TryReturn();
|
TryReturn();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
<# if (!IsVoid(t)) { #>
|
<# if (!IsVoid(t)) { #>
|
||||||
void IUniTaskSource.GetResult(short token)
|
void IUniTaskSource.GetResult(short token)
|
||||||
|
@ -223,6 +260,12 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
public bool MoveNext()
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
|
// Already completed
|
||||||
|
if (completed || asyncOperation == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
<# if(IsUnityWebRequest(t)) { #>
|
<# if(IsUnityWebRequest(t)) { #>
|
||||||
|
@ -261,11 +304,42 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
TaskTracker.RemoveTracking(this);
|
TaskTracker.RemoveTracking(this);
|
||||||
core.Reset();
|
core.Reset();
|
||||||
|
asyncOperation.completed -= continuationAction;
|
||||||
asyncOperation = default;
|
asyncOperation = default;
|
||||||
progress = default;
|
progress = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
cancellationTokenRegistration.Dispose();
|
||||||
|
cancelImmediately = default;
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Continuation(AsyncOperation _)
|
||||||
|
{
|
||||||
|
if (completed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
completed = true;
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
}
|
||||||
|
<# if(IsUnityWebRequest(t)) { #>
|
||||||
|
else if (asyncOperation.webRequest.IsError())
|
||||||
|
{
|
||||||
|
core.TrySetException(new UnityWebRequestException(asyncOperation.webRequest));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
core.TrySetResult(asyncOperation.webRequest);
|
||||||
|
}
|
||||||
|
<# } else { #>
|
||||||
|
else
|
||||||
|
{
|
||||||
|
core.TrySetResult(<#= IsVoid(t) ? "AsyncUnit.Default" : $"asyncOperation.{t.returnField}" #>);
|
||||||
|
}
|
||||||
|
<# } #>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
|
@ -339,7 +339,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
void InvokeCore(string item1, int item2, int item3)
|
void InvokeCore(string item1, int item2, int item3)
|
||||||
{
|
{
|
||||||
innerEvent.Invoke(item1, item2, item3);
|
Invoke((item1, item2, item3));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
@ -673,7 +673,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
if (cancellationToken2.CanBeCanceled)
|
if (cancellationToken2.CanBeCanceled)
|
||||||
{
|
{
|
||||||
registration2 = cancellationToken1.RegisterWithoutCaptureExecutionContext(cancel2, this);
|
registration2 = cancellationToken2.RegisterWithoutCaptureExecutionContext(cancel2, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -793,7 +793,7 @@ namespace Cysharp.Threading.Tasks
|
||||||
}
|
}
|
||||||
if (cancellationToken2.CanBeCanceled)
|
if (cancellationToken2.CanBeCanceled)
|
||||||
{
|
{
|
||||||
registration2 = cancellationToken1.RegisterWithoutCaptureExecutionContext(cancel2, this);
|
registration2 = cancellationToken2.RegisterWithoutCaptureExecutionContext(cancel2, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
#if UNITY_2023_1_OR_NEWER
|
||||||
|
namespace Cysharp.Threading.Tasks
|
||||||
|
{
|
||||||
|
public static class UnityAwaitableExtensions
|
||||||
|
{
|
||||||
|
public static async UniTask AsUniTask(this UnityEngine.Awaitable awaitable)
|
||||||
|
{
|
||||||
|
await awaitable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async UniTask<T> AsUniTask<T>(this UnityEngine.Awaitable<T> awaitable)
|
||||||
|
{
|
||||||
|
return await awaitable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,3 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: c29533c9e4284dee914b71a6579ea274
|
||||||
|
timeCreated: 1698895807
|
|
@ -12,17 +12,17 @@ namespace Cysharp.Threading.Tasks
|
||||||
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
||||||
// <string> -> Text
|
// <string> -> Text
|
||||||
|
|
||||||
public static void BindTo(this IUniTaskAsyncEnumerable<string> source, Text text, bool rebindOnError = true)
|
public static void BindTo(this IUniTaskAsyncEnumerable<string> source, UnityEngine.UI.Text text, bool rebindOnError = true)
|
||||||
{
|
{
|
||||||
BindToCore(source, text, text.GetCancellationTokenOnDestroy(), rebindOnError).Forget();
|
BindToCore(source, text, text.GetCancellationTokenOnDestroy(), rebindOnError).Forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void BindTo(this IUniTaskAsyncEnumerable<string> source, Text text, CancellationToken cancellationToken, bool rebindOnError = true)
|
public static void BindTo(this IUniTaskAsyncEnumerable<string> source, UnityEngine.UI.Text text, CancellationToken cancellationToken, bool rebindOnError = true)
|
||||||
{
|
{
|
||||||
BindToCore(source, text, cancellationToken, rebindOnError).Forget();
|
BindToCore(source, text, cancellationToken, rebindOnError).Forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
static async UniTaskVoid BindToCore(IUniTaskAsyncEnumerable<string> source, Text text, CancellationToken cancellationToken, bool rebindOnError)
|
static async UniTaskVoid BindToCore(IUniTaskAsyncEnumerable<string> source, UnityEngine.UI.Text text, CancellationToken cancellationToken, bool rebindOnError)
|
||||||
{
|
{
|
||||||
var repeat = false;
|
var repeat = false;
|
||||||
BIND_AGAIN:
|
BIND_AGAIN:
|
||||||
|
@ -68,22 +68,22 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
// <T> -> Text
|
// <T> -> Text
|
||||||
|
|
||||||
public static void BindTo<T>(this IUniTaskAsyncEnumerable<T> source, Text text, bool rebindOnError = true)
|
public static void BindTo<T>(this IUniTaskAsyncEnumerable<T> source, UnityEngine.UI.Text text, bool rebindOnError = true)
|
||||||
{
|
{
|
||||||
BindToCore(source, text, text.GetCancellationTokenOnDestroy(), rebindOnError).Forget();
|
BindToCore(source, text, text.GetCancellationTokenOnDestroy(), rebindOnError).Forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void BindTo<T>(this IUniTaskAsyncEnumerable<T> source, Text text, CancellationToken cancellationToken, bool rebindOnError = true)
|
public static void BindTo<T>(this IUniTaskAsyncEnumerable<T> source, UnityEngine.UI.Text text, CancellationToken cancellationToken, bool rebindOnError = true)
|
||||||
{
|
{
|
||||||
BindToCore(source, text, cancellationToken, rebindOnError).Forget();
|
BindToCore(source, text, cancellationToken, rebindOnError).Forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void BindTo<T>(this AsyncReactiveProperty<T> source, Text text, bool rebindOnError = true)
|
public static void BindTo<T>(this AsyncReactiveProperty<T> source, UnityEngine.UI.Text text, bool rebindOnError = true)
|
||||||
{
|
{
|
||||||
BindToCore(source, text, text.GetCancellationTokenOnDestroy(), rebindOnError).Forget();
|
BindToCore(source, text, text.GetCancellationTokenOnDestroy(), rebindOnError).Forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
static async UniTaskVoid BindToCore<T>(IUniTaskAsyncEnumerable<T> source, Text text, CancellationToken cancellationToken, bool rebindOnError)
|
static async UniTaskVoid BindToCore<T>(IUniTaskAsyncEnumerable<T> source, UnityEngine.UI.Text text, CancellationToken cancellationToken, bool rebindOnError)
|
||||||
{
|
{
|
||||||
var repeat = false;
|
var repeat = false;
|
||||||
BIND_AGAIN:
|
BIND_AGAIN:
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
"name": "com.cysharp.unitask",
|
"name": "com.cysharp.unitask",
|
||||||
"displayName": "UniTask",
|
"displayName": "UniTask",
|
||||||
"author": { "name": "Cysharp, Inc.", "url": "https://cysharp.co.jp/en/" },
|
"author": { "name": "Cysharp, Inc.", "url": "https://cysharp.co.jp/en/" },
|
||||||
"version": "2.3.2",
|
"version": "2.5.10",
|
||||||
"unity": "2018.4",
|
"unity": "2018.4",
|
||||||
"description": "Provides an efficient async/await integration to Unity.",
|
"description": "Provides an efficient async/await integration to Unity.",
|
||||||
"keywords": [ "async/await", "async", "Task", "UniTask" ],
|
"keywords": [ "async/await", "async", "Task", "UniTask" ],
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 959c1472a5d812843bedf9341e87af3b
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -1,133 +0,0 @@
|
||||||
#if UNITY_EDITOR
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace RuntimeUnitTestToolkit.Editor
|
|
||||||
{
|
|
||||||
// functional declarative construction like flutter.
|
|
||||||
|
|
||||||
internal interface IBuilder
|
|
||||||
{
|
|
||||||
GameObject GameObject { get; }
|
|
||||||
T GetComponent<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class Builder<T> : IBuilder
|
|
||||||
where T : Component
|
|
||||||
{
|
|
||||||
public T Component1 { get; private set; }
|
|
||||||
public GameObject GameObject { get; private set; }
|
|
||||||
|
|
||||||
public Transform Transform { get { return GameObject.transform; } }
|
|
||||||
public RectTransform RectTransform { get { return GameObject.GetComponent<RectTransform>(); } }
|
|
||||||
|
|
||||||
public Action<GameObject> SetTarget
|
|
||||||
{
|
|
||||||
set
|
|
||||||
{
|
|
||||||
value(this.GameObject);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public IBuilder Child
|
|
||||||
{
|
|
||||||
set
|
|
||||||
{
|
|
||||||
value.GameObject.transform.SetParent(GameObject.transform);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public IBuilder[] Children
|
|
||||||
{
|
|
||||||
set
|
|
||||||
{
|
|
||||||
foreach (var item in value)
|
|
||||||
{
|
|
||||||
item.GameObject.transform.SetParent(GameObject.transform);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder(string name)
|
|
||||||
{
|
|
||||||
this.GameObject = new GameObject(name);
|
|
||||||
this.Component1 = GameObject.AddComponent<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder(string name, out T referenceSelf) // out primary reference.
|
|
||||||
{
|
|
||||||
this.GameObject = new GameObject(name);
|
|
||||||
this.Component1 = GameObject.AddComponent<T>();
|
|
||||||
referenceSelf = this.Component1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TComponent GetComponent<TComponent>()
|
|
||||||
{
|
|
||||||
return this.GameObject.GetComponent<TComponent>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class Builder<T1, T2> : Builder<T1>
|
|
||||||
where T1 : Component
|
|
||||||
where T2 : Component
|
|
||||||
{
|
|
||||||
public T2 Component2 { get; private set; }
|
|
||||||
|
|
||||||
public Builder(string name)
|
|
||||||
: base(name)
|
|
||||||
{
|
|
||||||
this.Component2 = GameObject.AddComponent<T2>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder(string name, out T1 referenceSelf)
|
|
||||||
: base(name, out referenceSelf)
|
|
||||||
{
|
|
||||||
this.Component2 = GameObject.AddComponent<T2>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class Builder<T1, T2, T3> : Builder<T1, T2>
|
|
||||||
where T1 : Component
|
|
||||||
where T2 : Component
|
|
||||||
where T3 : Component
|
|
||||||
{
|
|
||||||
public T3 Component3 { get; private set; }
|
|
||||||
|
|
||||||
public Builder(string name)
|
|
||||||
: base(name)
|
|
||||||
{
|
|
||||||
this.Component3 = GameObject.AddComponent<T3>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder(string name, out T1 referenceSelf)
|
|
||||||
: base(name, out referenceSelf)
|
|
||||||
{
|
|
||||||
this.Component3 = GameObject.AddComponent<T3>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class Builder<T1, T2, T3, T4> : Builder<T1, T2, T3>
|
|
||||||
where T1 : Component
|
|
||||||
where T2 : Component
|
|
||||||
where T3 : Component
|
|
||||||
where T4 : Component
|
|
||||||
{
|
|
||||||
public T4 Component4 { get; private set; }
|
|
||||||
|
|
||||||
public Builder(string name)
|
|
||||||
: base(name)
|
|
||||||
{
|
|
||||||
this.Component4 = GameObject.AddComponent<T4>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder(string name, out T1 referenceSelf)
|
|
||||||
: base(name, out referenceSelf)
|
|
||||||
{
|
|
||||||
this.Component4 = GameObject.AddComponent<T4>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,345 +0,0 @@
|
||||||
#if UNITY_EDITOR
|
|
||||||
using UnityEditor;
|
|
||||||
|
|
||||||
// Settings MenuItems.
|
|
||||||
|
|
||||||
public static partial class UnitTestBuilder
|
|
||||||
{
|
|
||||||
[MenuItem("Test/Settings/ScriptBackend/Mono", validate = true, priority = 1)]
|
|
||||||
static bool ValidateScriptBackendMono()
|
|
||||||
{
|
|
||||||
Menu.SetChecked("Test/Settings/ScriptBackend/Mono", LoadOrGetDefaultSettings().ScriptBackend == ScriptingImplementation.Mono2x);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem("Test/Settings/ScriptBackend/Mono", validate = false, priority = 1)]
|
|
||||||
static void ScriptBackendMono()
|
|
||||||
{
|
|
||||||
var settings = LoadOrGetDefaultSettings();
|
|
||||||
settings.UseCurrentScriptBackend = false;
|
|
||||||
settings.ScriptBackend = ScriptingImplementation.Mono2x;
|
|
||||||
SaveSettings(settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem("Test/Settings/ScriptBackend/IL2CPP", validate = true, priority = 2)]
|
|
||||||
static bool ValidateScriptBackendIL2CPP()
|
|
||||||
{
|
|
||||||
Menu.SetChecked("Test/Settings/ScriptBackend/IL2CPP", LoadOrGetDefaultSettings().ScriptBackend == ScriptingImplementation.IL2CPP);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem("Test/Settings/ScriptBackend/IL2CPP", validate = false, priority = 2)]
|
|
||||||
static void ScriptBackendIL2CPP()
|
|
||||||
{
|
|
||||||
var settings = LoadOrGetDefaultSettings();
|
|
||||||
settings.UseCurrentScriptBackend = false;
|
|
||||||
settings.ScriptBackend = ScriptingImplementation.IL2CPP;
|
|
||||||
SaveSettings(settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem("Test/Settings/AutoRunPlayer", validate = true, priority = 3)]
|
|
||||||
static bool ValidateAutoRun()
|
|
||||||
{
|
|
||||||
Menu.SetChecked("Test/Settings/AutoRunPlayer", LoadOrGetDefaultSettings().AutoRunPlayer);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem("Test/Settings/AutoRunPlayer", validate = false, priority = 3)]
|
|
||||||
static void AutoRun()
|
|
||||||
{
|
|
||||||
var settings = LoadOrGetDefaultSettings();
|
|
||||||
settings.AutoRunPlayer = !settings.AutoRunPlayer;
|
|
||||||
SaveSettings(settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem("Test/Settings/Headless", validate = true, priority = 4)]
|
|
||||||
static bool ValidateHeadless()
|
|
||||||
{
|
|
||||||
Menu.SetChecked("Test/Settings/Headless", LoadOrGetDefaultSettings().Headless);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem("Test/Settings/Headless", validate = false, priority = 4)]
|
|
||||||
static void Headless()
|
|
||||||
{
|
|
||||||
var settings = LoadOrGetDefaultSettings();
|
|
||||||
settings.Headless = !settings.Headless;
|
|
||||||
SaveSettings(settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem("Test/Settings/DisableAutoClose", validate = true, priority = 5)]
|
|
||||||
static bool ValidateDisableAutoClose()
|
|
||||||
{
|
|
||||||
Menu.SetChecked("Test/Settings/DisableAutoClose", LoadOrGetDefaultSettings().DisableAutoClose);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem("Test/Settings/DisableAutoClose", validate = false, priority = 5)]
|
|
||||||
static void DisableAutoClose()
|
|
||||||
{
|
|
||||||
var settings = LoadOrGetDefaultSettings();
|
|
||||||
settings.DisableAutoClose = !settings.DisableAutoClose;
|
|
||||||
SaveSettings(settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
// generated
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
void Main()
|
|
||||||
{
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
|
|
||||||
var p = 1;
|
|
||||||
foreach (var target in Enum.GetNames(typeof(BuildTarget)))
|
|
||||||
{
|
|
||||||
var path = $"Test/Settings/BuildTarget/{target}";
|
|
||||||
var priority = p++;
|
|
||||||
|
|
||||||
var template = $@"
|
|
||||||
[MenuItem(""{path}"", validate = true, priority = {priority})]
|
|
||||||
static bool ValidateBuildTarget{target}()
|
|
||||||
{{
|
|
||||||
Menu.SetChecked(""{path}"", LoadOrGetDefaultSettings().BuildTarget == BuildTarget.{target});
|
|
||||||
return true;
|
|
||||||
}}
|
|
||||||
|
|
||||||
[MenuItem(""{path}"", validate = false, priority = {priority})]
|
|
||||||
static void BuildTarget{target}()
|
|
||||||
{{
|
|
||||||
var settings = LoadOrGetDefaultSettings();
|
|
||||||
settings.UseCurrentBuildTarget = false;
|
|
||||||
settings.BuildTarget = BuildTarget.{target};
|
|
||||||
SaveSettings(settings);
|
|
||||||
}}";
|
|
||||||
|
|
||||||
sb.AppendLine(template);
|
|
||||||
}
|
|
||||||
|
|
||||||
sb.ToString().Dump();
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum BuildTarget
|
|
||||||
{
|
|
||||||
StandaloneWindows,
|
|
||||||
StandaloneWindows64,
|
|
||||||
StandaloneLinux,
|
|
||||||
StandaloneLinux64,
|
|
||||||
StandaloneOSX,
|
|
||||||
WebGL,
|
|
||||||
iOS,
|
|
||||||
Android,
|
|
||||||
WSAPlayer,
|
|
||||||
PS4,
|
|
||||||
XboxOne,
|
|
||||||
Switch,
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
[MenuItem("Test/Settings/BuildTarget/StandaloneWindows", validate = true, priority = 1)]
|
|
||||||
static bool ValidateBuildTargetStandaloneWindows()
|
|
||||||
{
|
|
||||||
Menu.SetChecked("Test/Settings/BuildTarget/StandaloneWindows", LoadOrGetDefaultSettings().BuildTarget == BuildTarget.StandaloneWindows);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem("Test/Settings/BuildTarget/StandaloneWindows", validate = false, priority = 1)]
|
|
||||||
static void BuildTargetStandaloneWindows()
|
|
||||||
{
|
|
||||||
var settings = LoadOrGetDefaultSettings();
|
|
||||||
settings.UseCurrentBuildTarget = false;
|
|
||||||
settings.BuildTarget = BuildTarget.StandaloneWindows;
|
|
||||||
SaveSettings(settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem("Test/Settings/BuildTarget/StandaloneWindows64", validate = true, priority = 2)]
|
|
||||||
static bool ValidateBuildTargetStandaloneWindows64()
|
|
||||||
{
|
|
||||||
Menu.SetChecked("Test/Settings/BuildTarget/StandaloneWindows64", LoadOrGetDefaultSettings().BuildTarget == BuildTarget.StandaloneWindows64);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem("Test/Settings/BuildTarget/StandaloneWindows64", validate = false, priority = 2)]
|
|
||||||
static void BuildTargetStandaloneWindows64()
|
|
||||||
{
|
|
||||||
var settings = LoadOrGetDefaultSettings();
|
|
||||||
settings.UseCurrentBuildTarget = false;
|
|
||||||
settings.BuildTarget = BuildTarget.StandaloneWindows64;
|
|
||||||
SaveSettings(settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !UNITY_2019_2_OR_NEWER
|
|
||||||
|
|
||||||
[MenuItem("Test/Settings/BuildTarget/StandaloneLinux", validate = true, priority = 3)]
|
|
||||||
static bool ValidateBuildTargetStandaloneLinux()
|
|
||||||
{
|
|
||||||
Menu.SetChecked("Test/Settings/BuildTarget/StandaloneLinux", LoadOrGetDefaultSettings().BuildTarget == BuildTarget.StandaloneLinux);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem("Test/Settings/BuildTarget/StandaloneLinux", validate = false, priority = 3)]
|
|
||||||
static void BuildTargetStandaloneLinux()
|
|
||||||
{
|
|
||||||
var settings = LoadOrGetDefaultSettings();
|
|
||||||
settings.UseCurrentBuildTarget = false;
|
|
||||||
settings.BuildTarget = BuildTarget.StandaloneLinux;
|
|
||||||
SaveSettings(settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
[MenuItem("Test/Settings/BuildTarget/StandaloneLinux64", validate = true, priority = 4)]
|
|
||||||
static bool ValidateBuildTargetStandaloneLinux64()
|
|
||||||
{
|
|
||||||
Menu.SetChecked("Test/Settings/BuildTarget/StandaloneLinux64", LoadOrGetDefaultSettings().BuildTarget == BuildTarget.StandaloneLinux64);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem("Test/Settings/BuildTarget/StandaloneLinux64", validate = false, priority = 4)]
|
|
||||||
static void BuildTargetStandaloneLinux64()
|
|
||||||
{
|
|
||||||
var settings = LoadOrGetDefaultSettings();
|
|
||||||
settings.UseCurrentBuildTarget = false;
|
|
||||||
settings.BuildTarget = BuildTarget.StandaloneLinux64;
|
|
||||||
SaveSettings(settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem("Test/Settings/BuildTarget/StandaloneOSX", validate = true, priority = 5)]
|
|
||||||
static bool ValidateBuildTargetStandaloneOSX()
|
|
||||||
{
|
|
||||||
Menu.SetChecked("Test/Settings/BuildTarget/StandaloneOSX", LoadOrGetDefaultSettings().BuildTarget == BuildTarget.StandaloneOSX);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem("Test/Settings/BuildTarget/StandaloneOSX", validate = false, priority = 5)]
|
|
||||||
static void BuildTargetStandaloneOSX()
|
|
||||||
{
|
|
||||||
var settings = LoadOrGetDefaultSettings();
|
|
||||||
settings.UseCurrentBuildTarget = false;
|
|
||||||
settings.BuildTarget = BuildTarget.StandaloneOSX;
|
|
||||||
SaveSettings(settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem("Test/Settings/BuildTarget/WebGL", validate = true, priority = 6)]
|
|
||||||
static bool ValidateBuildTargetWebGL()
|
|
||||||
{
|
|
||||||
Menu.SetChecked("Test/Settings/BuildTarget/WebGL", LoadOrGetDefaultSettings().BuildTarget == BuildTarget.WebGL);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem("Test/Settings/BuildTarget/WebGL", validate = false, priority = 6)]
|
|
||||||
static void BuildTargetWebGL()
|
|
||||||
{
|
|
||||||
var settings = LoadOrGetDefaultSettings();
|
|
||||||
settings.UseCurrentBuildTarget = false;
|
|
||||||
settings.BuildTarget = BuildTarget.WebGL;
|
|
||||||
SaveSettings(settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem("Test/Settings/BuildTarget/iOS", validate = true, priority = 7)]
|
|
||||||
static bool ValidateBuildTargetiOS()
|
|
||||||
{
|
|
||||||
Menu.SetChecked("Test/Settings/BuildTarget/iOS", LoadOrGetDefaultSettings().BuildTarget == BuildTarget.iOS);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem("Test/Settings/BuildTarget/iOS", validate = false, priority = 7)]
|
|
||||||
static void BuildTargetiOS()
|
|
||||||
{
|
|
||||||
var settings = LoadOrGetDefaultSettings();
|
|
||||||
settings.UseCurrentBuildTarget = false;
|
|
||||||
settings.BuildTarget = BuildTarget.iOS;
|
|
||||||
SaveSettings(settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem("Test/Settings/BuildTarget/Android", validate = true, priority = 8)]
|
|
||||||
static bool ValidateBuildTargetAndroid()
|
|
||||||
{
|
|
||||||
Menu.SetChecked("Test/Settings/BuildTarget/Android", LoadOrGetDefaultSettings().BuildTarget == BuildTarget.Android);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem("Test/Settings/BuildTarget/Android", validate = false, priority = 8)]
|
|
||||||
static void BuildTargetAndroid()
|
|
||||||
{
|
|
||||||
var settings = LoadOrGetDefaultSettings();
|
|
||||||
settings.UseCurrentBuildTarget = false;
|
|
||||||
settings.BuildTarget = BuildTarget.Android;
|
|
||||||
SaveSettings(settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem("Test/Settings/BuildTarget/WSAPlayer", validate = true, priority = 9)]
|
|
||||||
static bool ValidateBuildTargetWSAPlayer()
|
|
||||||
{
|
|
||||||
Menu.SetChecked("Test/Settings/BuildTarget/WSAPlayer", LoadOrGetDefaultSettings().BuildTarget == BuildTarget.WSAPlayer);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem("Test/Settings/BuildTarget/WSAPlayer", validate = false, priority = 9)]
|
|
||||||
static void BuildTargetWSAPlayer()
|
|
||||||
{
|
|
||||||
var settings = LoadOrGetDefaultSettings();
|
|
||||||
settings.UseCurrentBuildTarget = false;
|
|
||||||
settings.BuildTarget = BuildTarget.WSAPlayer;
|
|
||||||
SaveSettings(settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem("Test/Settings/BuildTarget/PS4", validate = true, priority = 10)]
|
|
||||||
static bool ValidateBuildTargetPS4()
|
|
||||||
{
|
|
||||||
Menu.SetChecked("Test/Settings/BuildTarget/PS4", LoadOrGetDefaultSettings().BuildTarget == BuildTarget.PS4);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem("Test/Settings/BuildTarget/PS4", validate = false, priority = 10)]
|
|
||||||
static void BuildTargetPS4()
|
|
||||||
{
|
|
||||||
var settings = LoadOrGetDefaultSettings();
|
|
||||||
settings.UseCurrentBuildTarget = false;
|
|
||||||
settings.BuildTarget = BuildTarget.PS4;
|
|
||||||
SaveSettings(settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem("Test/Settings/BuildTarget/XboxOne", validate = true, priority = 11)]
|
|
||||||
static bool ValidateBuildTargetXboxOne()
|
|
||||||
{
|
|
||||||
Menu.SetChecked("Test/Settings/BuildTarget/XboxOne", LoadOrGetDefaultSettings().BuildTarget == BuildTarget.XboxOne);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem("Test/Settings/BuildTarget/XboxOne", validate = false, priority = 11)]
|
|
||||||
static void BuildTargetXboxOne()
|
|
||||||
{
|
|
||||||
var settings = LoadOrGetDefaultSettings();
|
|
||||||
settings.UseCurrentBuildTarget = false;
|
|
||||||
settings.BuildTarget = BuildTarget.XboxOne;
|
|
||||||
SaveSettings(settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem("Test/Settings/BuildTarget/Switch", validate = true, priority = 12)]
|
|
||||||
static bool ValidateBuildTargetSwitch()
|
|
||||||
{
|
|
||||||
Menu.SetChecked("Test/Settings/BuildTarget/Switch", LoadOrGetDefaultSettings().BuildTarget == BuildTarget.Switch);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem("Test/Settings/BuildTarget/Switch", validate = false, priority = 12)]
|
|
||||||
static void BuildTargetSwitch()
|
|
||||||
{
|
|
||||||
var settings = LoadOrGetDefaultSettings();
|
|
||||||
settings.UseCurrentBuildTarget = false;
|
|
||||||
settings.BuildTarget = BuildTarget.Switch;
|
|
||||||
SaveSettings(settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,546 +0,0 @@
|
||||||
#if UNITY_EDITOR
|
|
||||||
|
|
||||||
using RuntimeUnitTestToolkit;
|
|
||||||
using RuntimeUnitTestToolkit.Editor;
|
|
||||||
using System;
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEditor.Build.Reporting;
|
|
||||||
using UnityEditor.SceneManagement;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.EventSystems;
|
|
||||||
using UnityEngine.SceneManagement;
|
|
||||||
using UnityEngine.UI;
|
|
||||||
|
|
||||||
internal class RuntimeUnitTestSettings
|
|
||||||
{
|
|
||||||
public ScriptingImplementation ScriptBackend;
|
|
||||||
public bool UseCurrentScriptBackend;
|
|
||||||
public BuildTarget BuildTarget;
|
|
||||||
public bool UseCurrentBuildTarget;
|
|
||||||
|
|
||||||
public bool Headless;
|
|
||||||
public bool AutoRunPlayer;
|
|
||||||
public bool DisableAutoClose;
|
|
||||||
|
|
||||||
public RuntimeUnitTestSettings()
|
|
||||||
{
|
|
||||||
UseCurrentBuildTarget = true;
|
|
||||||
UseCurrentScriptBackend = true;
|
|
||||||
Headless = false;
|
|
||||||
AutoRunPlayer = true;
|
|
||||||
DisableAutoClose = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return $"{ScriptBackend} {BuildTarget} Headless:{Headless} AutoRunPlayer:{AutoRunPlayer} DisableAutoClose:{DisableAutoClose}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// no namespace(because invoke from commandline)
|
|
||||||
public static partial class UnitTestBuilder
|
|
||||||
{
|
|
||||||
const string SettingsKeyBase = "RuntimeUnitTest.Settings.";
|
|
||||||
|
|
||||||
[MenuItem("Test/BuildUnitTest")]
|
|
||||||
public static void BuildUnitTest()
|
|
||||||
{
|
|
||||||
var settings = new RuntimeUnitTestSettings(); // default
|
|
||||||
|
|
||||||
string buildPath = null;
|
|
||||||
|
|
||||||
if (Application.isBatchMode) // from commandline
|
|
||||||
{
|
|
||||||
settings.AutoRunPlayer = false;
|
|
||||||
settings.DisableAutoClose = false;
|
|
||||||
|
|
||||||
var cmdArgs = Environment.GetCommandLineArgs();
|
|
||||||
for (int i = 0; i < cmdArgs.Length; i++)
|
|
||||||
{
|
|
||||||
if (string.Equals(cmdArgs[i].Trim('-', '/'), "ScriptBackend", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
settings.UseCurrentScriptBackend = false;
|
|
||||||
var str = cmdArgs[++i];
|
|
||||||
if (str.StartsWith("mono", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
settings.ScriptBackend = ScriptingImplementation.Mono2x;
|
|
||||||
}
|
|
||||||
else if (str.StartsWith("IL2CPP", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
settings.ScriptBackend = ScriptingImplementation.IL2CPP;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
settings.ScriptBackend = (ScriptingImplementation)Enum.Parse(typeof(ScriptingImplementation), str, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (string.Equals(cmdArgs[i].Trim('-', '/'), "BuildTarget", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
settings.UseCurrentBuildTarget = false;
|
|
||||||
settings.BuildTarget = (BuildTarget)Enum.Parse(typeof(BuildTarget), cmdArgs[++i], true);
|
|
||||||
}
|
|
||||||
else if (string.Equals(cmdArgs[i].Trim('-', '/'), "Headless", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
settings.Headless = true;
|
|
||||||
}
|
|
||||||
else if (string.Equals(cmdArgs[i].Trim('-', '/'), "buildPath", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
buildPath = cmdArgs[++i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var key = SettingsKeyBase + Application.productName;
|
|
||||||
var settingsValue = EditorPrefs.GetString(key, null);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrWhiteSpace(settingsValue))
|
|
||||||
{
|
|
||||||
settings = JsonUtility.FromJson<RuntimeUnitTestSettings>(settingsValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
UnityEngine.Debug.LogError("Fail to load RuntimeUnitTest settings");
|
|
||||||
EditorPrefs.SetString(key, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (settings.UseCurrentBuildTarget)
|
|
||||||
{
|
|
||||||
settings.BuildTarget = EditorUserBuildSettings.activeBuildTarget;
|
|
||||||
}
|
|
||||||
if (settings.UseCurrentScriptBackend)
|
|
||||||
{
|
|
||||||
settings.ScriptBackend = PlayerSettings.GetScriptingBackend(ToBuildTargetGroup(settings.BuildTarget));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buildPath == null)
|
|
||||||
{
|
|
||||||
buildPath = $"bin/UnitTest/{settings.BuildTarget}_{settings.ScriptBackend}/test" + GetExtensionForBuildTarget(settings.BuildTarget);
|
|
||||||
}
|
|
||||||
|
|
||||||
var originalScene = SceneManager.GetActiveScene().path;
|
|
||||||
|
|
||||||
BuildUnitTest(buildPath, settings.ScriptBackend, settings.BuildTarget, settings.Headless, settings.AutoRunPlayer, settings.DisableAutoClose);
|
|
||||||
|
|
||||||
// reopen original scene
|
|
||||||
if (!string.IsNullOrWhiteSpace(originalScene))
|
|
||||||
{
|
|
||||||
EditorSceneManager.OpenScene(originalScene, OpenSceneMode.Single);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[MenuItem("Test/LoadUnitTestScene")]
|
|
||||||
public static void LoadUnitTestScene()
|
|
||||||
{
|
|
||||||
var scene = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single);
|
|
||||||
BuildUnitTestRunnerScene();
|
|
||||||
EditorSceneManager.MarkSceneDirty(scene);
|
|
||||||
}
|
|
||||||
|
|
||||||
static RuntimeUnitTestSettings LoadOrGetDefaultSettings()
|
|
||||||
{
|
|
||||||
var key = SettingsKeyBase + Application.productName;
|
|
||||||
|
|
||||||
var settingsValue = EditorPrefs.GetString(key, null);
|
|
||||||
RuntimeUnitTestSettings settings = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrWhiteSpace(settingsValue))
|
|
||||||
{
|
|
||||||
settings = JsonUtility.FromJson<RuntimeUnitTestSettings>(settingsValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
UnityEngine.Debug.LogError("Fail to load RuntimeUnitTest settings");
|
|
||||||
EditorPrefs.SetString(key, null);
|
|
||||||
settings = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (settings == null)
|
|
||||||
{
|
|
||||||
// default
|
|
||||||
settings = new RuntimeUnitTestSettings
|
|
||||||
{
|
|
||||||
UseCurrentBuildTarget = true,
|
|
||||||
UseCurrentScriptBackend = true,
|
|
||||||
Headless = false,
|
|
||||||
AutoRunPlayer = true,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return settings;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void SaveSettings(RuntimeUnitTestSettings settings)
|
|
||||||
{
|
|
||||||
var key = SettingsKeyBase + Application.productName;
|
|
||||||
EditorPrefs.SetString(key, JsonUtility.ToJson(settings));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void BuildUnitTest(string buildPath, ScriptingImplementation scriptBackend, BuildTarget buildTarget, bool headless, bool autoRunPlayer, bool disableAutoClose)
|
|
||||||
{
|
|
||||||
var sceneName = "Assets/TempRuntimeUnitTestScene_" + DateTimeOffset.UtcNow.ToUnixTimeSeconds();
|
|
||||||
if (disableAutoClose)
|
|
||||||
{
|
|
||||||
sceneName += "_DisableAutoClose";
|
|
||||||
}
|
|
||||||
sceneName += ".unity";
|
|
||||||
|
|
||||||
var scene = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single);
|
|
||||||
|
|
||||||
BuildUnitTestRunnerScene();
|
|
||||||
|
|
||||||
EditorSceneManager.MarkSceneDirty(scene);
|
|
||||||
AssetDatabase.SaveAssets();
|
|
||||||
EditorSceneManager.SaveScene(scene, sceneName, false);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Build(sceneName, buildPath, new RuntimeUnitTestSettings { ScriptBackend = scriptBackend, BuildTarget = buildTarget, Headless = headless, AutoRunPlayer = autoRunPlayer, DisableAutoClose = disableAutoClose });
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
AssetDatabase.DeleteAsset(sceneName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UnitTestRunner BuildUnitTestRunnerScene()
|
|
||||||
{
|
|
||||||
const string kStandardSpritePath = "UI/Skin/UISprite.psd";
|
|
||||||
const string kBackgroundSpritePath = "UI/Skin/Background.psd";
|
|
||||||
var uisprite = AssetDatabase.GetBuiltinExtraResource<Sprite>(kStandardSpritePath);
|
|
||||||
var background = AssetDatabase.GetBuiltinExtraResource<Sprite>(kBackgroundSpritePath);
|
|
||||||
|
|
||||||
ScrollRect buttonList;
|
|
||||||
VerticalLayoutGroup listLayout;
|
|
||||||
Scrollbar refListScrollbar;
|
|
||||||
ScrollRect logList;
|
|
||||||
Scrollbar refLogScrollbar;
|
|
||||||
Button clearButton;
|
|
||||||
Text logText;
|
|
||||||
|
|
||||||
// Flutter like coded build utility
|
|
||||||
|
|
||||||
var rootObject = new Builder<Camera>("SceneRoot")
|
|
||||||
{
|
|
||||||
Children = new IBuilder[] {
|
|
||||||
new Builder<EventSystem, StandaloneInputModule>("EventSystem"),
|
|
||||||
new Builder<Canvas, CanvasScaler, GraphicRaycaster>("Canvas") {
|
|
||||||
Component1 = { renderMode = RenderMode.ScreenSpaceOverlay },
|
|
||||||
Children = new IBuilder[] {
|
|
||||||
new Builder<HorizontalLayoutGroup, CanvasRenderer>("HorizontalSplitter") {
|
|
||||||
RectTransform = { anchorMin = new Vector2(0, 0), anchorMax = new Vector2(1, 1) },
|
|
||||||
Component1 = { childControlWidth = true, childControlHeight = true, spacing = 10 },
|
|
||||||
Children = new IBuilder[] {
|
|
||||||
new Builder<ScrollRect, CanvasRenderer>("ButtonList", out buttonList) {
|
|
||||||
RectTransform = { pivot = new Vector2(0.5f, 0.5f) },
|
|
||||||
Component1 = { horizontal =false, vertical = true, movementType = ScrollRect.MovementType.Clamped },
|
|
||||||
Children = new IBuilder[] {
|
|
||||||
new Builder<VerticalLayoutGroup, ContentSizeFitter>("ListLayoutToAttach", out listLayout) {
|
|
||||||
RectTransform = { anchorMin = new Vector2(0, 0), anchorMax = new Vector2(1, 1), pivot = new Vector2(0, 1) },
|
|
||||||
Component1 = { childControlWidth = true, childControlHeight = true, childForceExpandWidth = true, childForceExpandHeight = false, spacing = 10, padding = new RectOffset(10,20,10,10) },
|
|
||||||
Component2 = { horizontalFit = ContentSizeFitter.FitMode.Unconstrained, verticalFit = ContentSizeFitter.FitMode.PreferredSize },
|
|
||||||
SetTarget = self => { buttonList.content = self.GetComponent<RectTransform>(); },
|
|
||||||
Child = new Builder<Button, Image, LayoutElement>("ClearButton", out clearButton) {
|
|
||||||
Component2 = { sprite = uisprite, type = Image.Type.Sliced },
|
|
||||||
Component3 = { minHeight = 50 },
|
|
||||||
SetTarget = self => { self.GetComponent<Button>().targetGraphic = self.GetComponent<Graphic>(); },
|
|
||||||
Child = new Builder<Text>("ButtonText") {
|
|
||||||
RectTransform = { anchorMin = new Vector2(0, 0), anchorMax = new Vector2(1, 1), pivot = new Vector2(0.5f, 0.5f) },
|
|
||||||
Component1 = { text = "Clear", color = FromRGB(50, 50, 50), alignment = TextAnchor.MiddleCenter, fontSize = 24, lineSpacing = 1 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
new Builder<Scrollbar,Image>("ListScrollbar", out refListScrollbar) {
|
|
||||||
RectTransform = { anchorMin = new Vector2(1, 0), anchorMax = new Vector2(1, 1) },
|
|
||||||
Component1 = { navigation = new Navigation{ mode = Navigation.Mode.None }, direction = Scrollbar.Direction.BottomToTop, size = 1.0f },
|
|
||||||
Component2 = { sprite = background, type = Image.Type.Sliced },
|
|
||||||
SetTarget = self => { buttonList.verticalScrollbar = self.GetComponent<Scrollbar>(); },
|
|
||||||
Child = new Builder<RectTransform>("Sliding Area") {
|
|
||||||
RectTransform = { anchorMin = new Vector2(0, 0), anchorMax = new Vector2(1, 1) },
|
|
||||||
Child = new Builder<Image>("Handle") {
|
|
||||||
Component1 = { sprite = uisprite, type = Image.Type.Sliced },
|
|
||||||
SetTarget = self =>
|
|
||||||
{
|
|
||||||
refListScrollbar.targetGraphic = self.GetComponent<Graphic>();
|
|
||||||
refListScrollbar.handleRect = self.GetComponent<RectTransform>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
new Builder<ScrollRect, CanvasRenderer>("ScrollableText", out logList) {
|
|
||||||
RectTransform = { pivot = new Vector2(0.5f, 0.5f) },
|
|
||||||
Component1 = { horizontal =false, vertical = true, movementType = ScrollRect.MovementType.Elastic, elasticity = 0.1f },
|
|
||||||
Children = new IBuilder[] {
|
|
||||||
new Builder<Text, ContentSizeFitter>("Log", out logText) {
|
|
||||||
RectTransform = { anchorMin = new Vector2(0, 0), anchorMax = new Vector2(1, 1), pivot = new Vector2(0, 1) },
|
|
||||||
Component1 = { fontSize = 24, lineSpacing = 1, supportRichText = true, alignment = TextAnchor.UpperLeft, horizontalOverflow = HorizontalWrapMode.Wrap, verticalOverflow = VerticalWrapMode.Truncate },
|
|
||||||
Component2 = { horizontalFit = ContentSizeFitter.FitMode.Unconstrained, verticalFit = ContentSizeFitter.FitMode.PreferredSize },
|
|
||||||
SetTarget = self => { logList.content = self.GetComponent<RectTransform>(); }
|
|
||||||
},
|
|
||||||
new Builder<Scrollbar,Image>("LogScrollbar", out refLogScrollbar) {
|
|
||||||
RectTransform = { anchorMin = new Vector2(1, 0), anchorMax = new Vector2(1, 1) },
|
|
||||||
Component1 = { navigation = new Navigation{ mode = Navigation.Mode.None }, direction = Scrollbar.Direction.BottomToTop, size = 1.0f },
|
|
||||||
Component2 = { sprite = background, type = Image.Type.Sliced },
|
|
||||||
SetTarget = self => { logList.verticalScrollbar = self.GetComponent<Scrollbar>(); },
|
|
||||||
Child = new Builder<RectTransform>("Sliding Area2") {
|
|
||||||
RectTransform = { anchorMin = new Vector2(0, 0), anchorMax = new Vector2(1, 1) },
|
|
||||||
Child = new Builder<Image>("Handle2") {
|
|
||||||
Component1 = { sprite = uisprite, type = Image.Type.Sliced },
|
|
||||||
SetTarget = self =>
|
|
||||||
{
|
|
||||||
refLogScrollbar.targetGraphic = self.GetComponent<Graphic>();
|
|
||||||
refLogScrollbar.handleRect = self.GetComponent<RectTransform>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// size modify after build complete:)
|
|
||||||
{
|
|
||||||
var rect = GameObject.Find("HorizontalSplitter").GetComponent<RectTransform>();
|
|
||||||
rect.offsetMin = new Vector2(0, 0);
|
|
||||||
rect.offsetMax = new Vector2(0, 0);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
var rect = GameObject.Find("ListLayoutToAttach").GetComponent<RectTransform>();
|
|
||||||
rect.offsetMin = new Vector2(0, 0);
|
|
||||||
rect.offsetMax = new Vector2(0, 0);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
var rect = GameObject.Find("ListScrollbar").GetComponent<RectTransform>();
|
|
||||||
rect.offsetMin = new Vector2(0, 0);
|
|
||||||
rect.offsetMax = new Vector2(0, 0);
|
|
||||||
rect.sizeDelta = new Vector2(30, 0);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
var rect = GameObject.Find("ClearButton").GetComponent<RectTransform>();
|
|
||||||
rect.offsetMin = new Vector2(0, 0);
|
|
||||||
rect.offsetMax = new Vector2(0, 0);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
var rect = GameObject.Find("Sliding Area").GetComponent<RectTransform>();
|
|
||||||
rect.offsetMin = new Vector2(0, 0);
|
|
||||||
rect.offsetMax = new Vector2(0, 0);
|
|
||||||
rect.sizeDelta = new Vector2(-20, -20);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
var rect = GameObject.Find("Handle").GetComponent<RectTransform>();
|
|
||||||
rect.offsetMin = new Vector2(0, 0);
|
|
||||||
rect.offsetMax = new Vector2(0, 0);
|
|
||||||
rect.sizeDelta = new Vector2(20, 20);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
var rect = GameObject.Find("ButtonText").GetComponent<RectTransform>();
|
|
||||||
rect.offsetMin = new Vector2(0, 0);
|
|
||||||
rect.offsetMax = new Vector2(0, 0);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
var rect = GameObject.Find("Log").GetComponent<RectTransform>();
|
|
||||||
rect.offsetMin = new Vector2(15, 0);
|
|
||||||
rect.offsetMax = new Vector2(-20, 0);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
var rect = GameObject.Find("LogScrollbar").GetComponent<RectTransform>();
|
|
||||||
rect.offsetMin = new Vector2(-30, 0);
|
|
||||||
rect.offsetMax = new Vector2(0, 0);
|
|
||||||
rect.sizeDelta = new Vector2(30, 0);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
var rect = GameObject.Find("Sliding Area2").GetComponent<RectTransform>();
|
|
||||||
rect.offsetMin = new Vector2(0, 0);
|
|
||||||
rect.offsetMax = new Vector2(0, 0);
|
|
||||||
rect.sizeDelta = new Vector2(-20, -20);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
var rect = GameObject.Find("Handle2").GetComponent<RectTransform>();
|
|
||||||
rect.offsetMin = new Vector2(0, 0);
|
|
||||||
rect.offsetMax = new Vector2(0, 0);
|
|
||||||
rect.sizeDelta = new Vector2(20, 20);
|
|
||||||
}
|
|
||||||
|
|
||||||
// add test script
|
|
||||||
var runner = rootObject.GameObject.AddComponent<UnitTestRunner>();
|
|
||||||
runner.clearButton = clearButton;
|
|
||||||
runner.list = listLayout.gameObject.GetComponent<RectTransform>();
|
|
||||||
runner.listScrollBar = refListScrollbar;
|
|
||||||
runner.logText = logText;
|
|
||||||
runner.logScrollBar = refLogScrollbar;
|
|
||||||
|
|
||||||
return runner;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Build(string sceneName, string buildPath, RuntimeUnitTestSettings settings)
|
|
||||||
{
|
|
||||||
var options = BuildOptions.BuildScriptsOnly | BuildOptions.IncludeTestAssemblies;
|
|
||||||
if (settings.AutoRunPlayer)
|
|
||||||
{
|
|
||||||
options |= BuildOptions.AutoRunPlayer;
|
|
||||||
}
|
|
||||||
if (settings.Headless)
|
|
||||||
{
|
|
||||||
options |= BuildOptions.EnableHeadlessMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
var targetGroup = ToBuildTargetGroup(settings.BuildTarget);
|
|
||||||
var currentBackend = PlayerSettings.GetScriptingBackend(targetGroup);
|
|
||||||
if (currentBackend != settings.ScriptBackend)
|
|
||||||
{
|
|
||||||
UnityEngine.Debug.Log("Modify ScriptBackend to " + settings.ScriptBackend);
|
|
||||||
PlayerSettings.SetScriptingBackend(targetGroup, settings.ScriptBackend);
|
|
||||||
}
|
|
||||||
|
|
||||||
var buildOptions = new BuildPlayerOptions
|
|
||||||
{
|
|
||||||
target = settings.BuildTarget,
|
|
||||||
targetGroup = targetGroup,
|
|
||||||
options = options,
|
|
||||||
scenes = new[] { sceneName },
|
|
||||||
locationPathName = buildPath
|
|
||||||
};
|
|
||||||
|
|
||||||
UnityEngine.Debug.Log("UnitTest Build Start, " + settings.ToString());
|
|
||||||
|
|
||||||
var buildReport = BuildPipeline.BuildPlayer(buildOptions);
|
|
||||||
|
|
||||||
if (currentBackend != settings.ScriptBackend)
|
|
||||||
{
|
|
||||||
UnityEngine.Debug.Log("Restore ScriptBackend to " + currentBackend);
|
|
||||||
PlayerSettings.SetScriptingBackend(targetGroup, currentBackend);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buildReport.summary.result != BuildResult.Succeeded)
|
|
||||||
{
|
|
||||||
// Note: show error summary?
|
|
||||||
// Debug.LogError(buildReport.SummarizeErrors());
|
|
||||||
UnityEngine.Debug.LogError("UnitTest Build Failed.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UnityEngine.Debug.Log("UnitTest Build Completed, binary located: " + buildOptions.locationPathName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Color FromRGB(int r, int g, int b)
|
|
||||||
{
|
|
||||||
return new Color(r / 255f, g / 255f, b / 255f);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool IsWindows(BuildTarget buildTarget)
|
|
||||||
{
|
|
||||||
switch (buildTarget)
|
|
||||||
{
|
|
||||||
case BuildTarget.StandaloneWindows:
|
|
||||||
case BuildTarget.StandaloneWindows64:
|
|
||||||
case BuildTarget.WSAPlayer:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static string GetExtensionForBuildTarget(BuildTarget buildTarget)
|
|
||||||
{
|
|
||||||
switch (buildTarget)
|
|
||||||
{
|
|
||||||
case BuildTarget.StandaloneWindows:
|
|
||||||
case BuildTarget.StandaloneWindows64:
|
|
||||||
case BuildTarget.WSAPlayer:
|
|
||||||
return ".exe";
|
|
||||||
case BuildTarget.StandaloneOSX:
|
|
||||||
return ".app";
|
|
||||||
case BuildTarget.Android:
|
|
||||||
return ".apk";
|
|
||||||
default:
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static BuildTargetGroup ToBuildTargetGroup(BuildTarget buildTarget)
|
|
||||||
{
|
|
||||||
#pragma warning disable CS0618
|
|
||||||
switch (buildTarget)
|
|
||||||
{
|
|
||||||
#if UNITY_2017_3_OR_NEWER
|
|
||||||
case BuildTarget.StandaloneOSX:
|
|
||||||
#else
|
|
||||||
case BuildTarget.StandaloneOSXIntel:
|
|
||||||
case BuildTarget.StandaloneOSXIntel64:
|
|
||||||
case BuildTarget.StandaloneOSXUniversal:
|
|
||||||
#endif // UNITY_2017_3_OR_NEWER
|
|
||||||
case BuildTarget.StandaloneWindows:
|
|
||||||
case BuildTarget.StandaloneWindows64:
|
|
||||||
case BuildTarget.StandaloneLinux64:
|
|
||||||
#if !UNITY_2019_2_OR_NEWER
|
|
||||||
case BuildTarget.StandaloneLinux:
|
|
||||||
case BuildTarget.StandaloneLinuxUniversal:
|
|
||||||
#endif // !UNITY_2019_2_OR_NEWER
|
|
||||||
return BuildTargetGroup.Standalone;
|
|
||||||
case (BuildTarget)6:
|
|
||||||
case (BuildTarget)7:
|
|
||||||
case BuildTarget.WebGL:
|
|
||||||
return BuildTargetGroup.WebGL;
|
|
||||||
case BuildTarget.iOS:
|
|
||||||
return BuildTargetGroup.iOS;
|
|
||||||
case BuildTarget.PS3:
|
|
||||||
return BuildTargetGroup.PS3;
|
|
||||||
case BuildTarget.PS4:
|
|
||||||
return BuildTargetGroup.PS4;
|
|
||||||
case BuildTarget.XBOX360:
|
|
||||||
return BuildTargetGroup.XBOX360;
|
|
||||||
case BuildTarget.Android:
|
|
||||||
return BuildTargetGroup.Android;
|
|
||||||
case BuildTarget.WSAPlayer:
|
|
||||||
return BuildTargetGroup.WSA;
|
|
||||||
case BuildTarget.WP8Player:
|
|
||||||
return BuildTargetGroup.WP8;
|
|
||||||
case BuildTarget.Tizen:
|
|
||||||
return BuildTargetGroup.Tizen;
|
|
||||||
case BuildTarget.PSP2:
|
|
||||||
return BuildTargetGroup.PSP2;
|
|
||||||
case BuildTarget.PSM:
|
|
||||||
return BuildTargetGroup.PSM;
|
|
||||||
case BuildTarget.XboxOne:
|
|
||||||
return BuildTargetGroup.XboxOne;
|
|
||||||
case BuildTarget.SamsungTV:
|
|
||||||
return BuildTargetGroup.SamsungTV;
|
|
||||||
case BuildTarget.N3DS:
|
|
||||||
return BuildTargetGroup.N3DS;
|
|
||||||
case BuildTarget.WiiU:
|
|
||||||
return BuildTargetGroup.WiiU;
|
|
||||||
case BuildTarget.tvOS:
|
|
||||||
return BuildTargetGroup.tvOS;
|
|
||||||
case BuildTarget.Switch:
|
|
||||||
return BuildTargetGroup.Switch;
|
|
||||||
case BuildTarget.Lumin:
|
|
||||||
return BuildTargetGroup.Lumin;
|
|
||||||
case BuildTarget.BlackBerry:
|
|
||||||
return BuildTargetGroup.BlackBerry;
|
|
||||||
case BuildTarget.NoTarget:
|
|
||||||
default:
|
|
||||||
return BuildTargetGroup.Unknown;
|
|
||||||
}
|
|
||||||
#pragma warning restore CS0618
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,16 +0,0 @@
|
||||||
{
|
|
||||||
"name": "RuntimeUnitTestToolkit",
|
|
||||||
"references": [
|
|
||||||
],
|
|
||||||
"optionalUnityReferences": [
|
|
||||||
"TestAssemblies"
|
|
||||||
],
|
|
||||||
"includePlatforms": [],
|
|
||||||
"excludePlatforms": [],
|
|
||||||
"allowUnsafeCode": false,
|
|
||||||
"overrideReferences": false,
|
|
||||||
"precompiledReferences": [],
|
|
||||||
"autoReferenced": true,
|
|
||||||
"defineConstraints": [],
|
|
||||||
"versionDefines": []
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: 14c4fea4b238088479114ba2ffe195f9
|
|
||||||
AssemblyDefinitionImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -1,684 +0,0 @@
|
||||||
using NUnit.Framework;
|
|
||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.Events;
|
|
||||||
using UnityEngine.TestTools;
|
|
||||||
using UnityEngine.UI;
|
|
||||||
|
|
||||||
namespace RuntimeUnitTestToolkit
|
|
||||||
{
|
|
||||||
public class UnitTestRunner : MonoBehaviour
|
|
||||||
{
|
|
||||||
// object is IEnumerator or Func<IEnumerator>
|
|
||||||
Dictionary<string, List<TestKeyValuePair>> tests = new Dictionary<string, List<TestKeyValuePair>>();
|
|
||||||
|
|
||||||
List<Pair> additionalActionsOnFirst = new List<Pair>();
|
|
||||||
|
|
||||||
public Button clearButton;
|
|
||||||
public RectTransform list;
|
|
||||||
public Scrollbar listScrollBar;
|
|
||||||
|
|
||||||
public Text logText;
|
|
||||||
public Scrollbar logScrollBar;
|
|
||||||
|
|
||||||
readonly Color passColor = new Color(0f, 1f, 0f, 1f); // green
|
|
||||||
readonly Color failColor = new Color(1f, 0f, 0f, 1f); // red
|
|
||||||
readonly Color normalColor = new Color(1f, 1f, 1f, 1f); // white
|
|
||||||
|
|
||||||
bool allTestGreen = true;
|
|
||||||
bool logClear = false;
|
|
||||||
|
|
||||||
void Start()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
UnityEngine.Application.logMessageReceived += (a, b, c) =>
|
|
||||||
{
|
|
||||||
if (a.Contains("Mesh can not have more than 65000 vertices"))
|
|
||||||
{
|
|
||||||
logClear = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AppendToGraphicText("[" + c + "]" + a + "\n");
|
|
||||||
WriteToConsole("[" + c + "]" + a);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// register all test types
|
|
||||||
foreach (var item in GetTestTargetTypes())
|
|
||||||
{
|
|
||||||
RegisterAllMethods(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
var executeAll = new List<Func<Coroutine>>();
|
|
||||||
foreach (var ___item in tests)
|
|
||||||
{
|
|
||||||
var actionList = ___item; // be careful, capture in lambda
|
|
||||||
|
|
||||||
executeAll.Add(() => StartCoroutine(RunTestInCoroutine(actionList)));
|
|
||||||
Add(actionList.Key, () => StartCoroutine(RunTestInCoroutine(actionList)));
|
|
||||||
}
|
|
||||||
|
|
||||||
var executeAllButton = Add("Run All Tests", () => StartCoroutine(ExecuteAllInCoroutine(executeAll)));
|
|
||||||
|
|
||||||
clearButton.gameObject.GetComponent<Image>().color = new Color(170 / 255f, 170 / 255f, 170 / 255f, 1);
|
|
||||||
executeAllButton.gameObject.GetComponent<Image>().color = new Color(250 / 255f, 150 / 255f, 150 / 255f, 1);
|
|
||||||
executeAllButton.transform.SetSiblingIndex(1);
|
|
||||||
|
|
||||||
additionalActionsOnFirst.Reverse();
|
|
||||||
foreach (var item in additionalActionsOnFirst)
|
|
||||||
{
|
|
||||||
var newButton = GameObject.Instantiate(clearButton);
|
|
||||||
newButton.name = item.Name;
|
|
||||||
newButton.onClick.RemoveAllListeners();
|
|
||||||
newButton.GetComponentInChildren<Text>().text = item.Name;
|
|
||||||
newButton.onClick.AddListener(item.Action);
|
|
||||||
newButton.transform.SetParent(list);
|
|
||||||
newButton.transform.SetSiblingIndex(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
clearButton.onClick.AddListener(() =>
|
|
||||||
{
|
|
||||||
logText.text = "";
|
|
||||||
foreach (var btn in list.GetComponentsInChildren<Button>())
|
|
||||||
{
|
|
||||||
btn.interactable = true;
|
|
||||||
btn.GetComponent<Image>().color = normalColor;
|
|
||||||
}
|
|
||||||
executeAllButton.gameObject.GetComponent<Image>().color = new Color(250 / 255f, 150 / 255f, 150 / 255f, 1);
|
|
||||||
});
|
|
||||||
|
|
||||||
listScrollBar.value = 1;
|
|
||||||
logScrollBar.value = 1;
|
|
||||||
|
|
||||||
if (Application.isBatchMode)
|
|
||||||
{
|
|
||||||
// run immediately in player
|
|
||||||
StartCoroutine(ExecuteAllInCoroutine(executeAll));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
if (Application.isBatchMode)
|
|
||||||
{
|
|
||||||
// when failed(can not start runner), quit immediately.
|
|
||||||
WriteToConsole(ex.ToString());
|
|
||||||
Application.Quit(1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Button Add(string title, UnityAction test)
|
|
||||||
{
|
|
||||||
var newButton = GameObject.Instantiate(clearButton);
|
|
||||||
newButton.name = title;
|
|
||||||
newButton.onClick.RemoveAllListeners();
|
|
||||||
newButton.GetComponentInChildren<Text>().text = title;
|
|
||||||
newButton.onClick.AddListener(test);
|
|
||||||
|
|
||||||
newButton.transform.SetParent(list);
|
|
||||||
return newButton;
|
|
||||||
}
|
|
||||||
|
|
||||||
static IEnumerable<Type> GetTestTargetTypes()
|
|
||||||
{
|
|
||||||
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
|
|
||||||
{
|
|
||||||
var n = assembly.FullName;
|
|
||||||
if (n.StartsWith("UnityEngine")) continue;
|
|
||||||
if (n.StartsWith("mscorlib")) continue;
|
|
||||||
if (n.StartsWith("System")) continue;
|
|
||||||
|
|
||||||
foreach (var item in assembly.GetTypes())
|
|
||||||
{
|
|
||||||
foreach (var method in item.GetMethods())
|
|
||||||
{
|
|
||||||
TestAttribute t1 = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
t1 = method.GetCustomAttribute<TestAttribute>(true);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Debug.Log("TestAttribute Load Fail, Assembly:" + assembly.FullName);
|
|
||||||
Debug.LogException(ex);
|
|
||||||
goto NEXT_ASSEMBLY;
|
|
||||||
}
|
|
||||||
if (t1 != null)
|
|
||||||
{
|
|
||||||
yield return item;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
UnityTestAttribute t2 = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
t2 = method.GetCustomAttribute<UnityTestAttribute>(true);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Debug.Log("UnityTestAttribute Load Fail, Assembly:" + assembly.FullName);
|
|
||||||
Debug.LogException(ex);
|
|
||||||
goto NEXT_ASSEMBLY;
|
|
||||||
}
|
|
||||||
if (t2 != null)
|
|
||||||
{
|
|
||||||
yield return item;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NEXT_ASSEMBLY:
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddTest(string group, string title, Action test, List<Action> setups, List<Action> teardowns)
|
|
||||||
{
|
|
||||||
List<TestKeyValuePair> list;
|
|
||||||
if (!tests.TryGetValue(group, out list))
|
|
||||||
{
|
|
||||||
list = new List<TestKeyValuePair>();
|
|
||||||
tests[group] = list;
|
|
||||||
}
|
|
||||||
|
|
||||||
list.Add(new TestKeyValuePair(title, test, setups, teardowns));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddAsyncTest(string group, string title, Func<IEnumerator> asyncTestCoroutine, List<Action> setups, List<Action> teardowns)
|
|
||||||
{
|
|
||||||
List<TestKeyValuePair> list;
|
|
||||||
if (!tests.TryGetValue(group, out list))
|
|
||||||
{
|
|
||||||
list = new List<TestKeyValuePair>();
|
|
||||||
tests[group] = list;
|
|
||||||
}
|
|
||||||
|
|
||||||
list.Add(new TestKeyValuePair(title, asyncTestCoroutine, setups, teardowns));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddCutomAction(string name, UnityAction action)
|
|
||||||
{
|
|
||||||
additionalActionsOnFirst.Add(new Pair { Name = name, Action = action });
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void RegisterAllMethods<T>()
|
|
||||||
where T : new()
|
|
||||||
{
|
|
||||||
RegisterAllMethods(typeof(T));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RegisterAllMethods(Type testType)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var test = Activator.CreateInstance(testType);
|
|
||||||
|
|
||||||
var methods = testType.GetMethods(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
|
|
||||||
List<Action> setups = new List<Action>();
|
|
||||||
List<Action> teardowns = new List<Action>();
|
|
||||||
foreach (var item in methods)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var setup = item.GetCustomAttribute<NUnit.Framework.SetUpAttribute>(true);
|
|
||||||
if (setup != null)
|
|
||||||
{
|
|
||||||
setups.Add((Action)Delegate.CreateDelegate(typeof(Action), test, item));
|
|
||||||
}
|
|
||||||
var teardown = item.GetCustomAttribute<NUnit.Framework.TearDownAttribute>(true);
|
|
||||||
if (teardown != null)
|
|
||||||
{
|
|
||||||
teardowns.Add((Action)Delegate.CreateDelegate(typeof(Action), test, item));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
UnityEngine.Debug.LogError(testType.Name + "." + item.Name + " failed to register setup/teardown method, exception: " + e.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var item in methods)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var iteratorTest = item.GetCustomAttribute<UnityEngine.TestTools.UnityTestAttribute>(true);
|
|
||||||
if (iteratorTest != null)
|
|
||||||
{
|
|
||||||
if (item.GetParameters().Length == 0 && item.ReturnType == typeof(IEnumerator))
|
|
||||||
{
|
|
||||||
var factory = (Func<IEnumerator>)Delegate.CreateDelegate(typeof(Func<IEnumerator>), test, item);
|
|
||||||
AddAsyncTest(factory.Target.GetType().Name, factory.Method.Name, factory, setups, teardowns);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var testData = GetTestData(item);
|
|
||||||
if (testData.Count != 0)
|
|
||||||
{
|
|
||||||
foreach (var item2 in testData)
|
|
||||||
{
|
|
||||||
Func<IEnumerator> factory;
|
|
||||||
if (item.IsGenericMethod)
|
|
||||||
{
|
|
||||||
var method2 = InferGenericType(item, item2);
|
|
||||||
factory = () => (IEnumerator)method2.Invoke(test, item2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
factory = () => (IEnumerator)item.Invoke(test, item2);
|
|
||||||
}
|
|
||||||
var name = item.Name + "(" + string.Join(", ", item2.Select(x => x?.ToString() ?? "null")) + ")";
|
|
||||||
name = name.Replace(Char.MinValue, ' ').Replace(Char.MaxValue, ' ').Replace("<", "[").Replace(">", "]");
|
|
||||||
AddAsyncTest(test.GetType().Name, name, factory, setups, teardowns);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UnityEngine.Debug.Log(testType.Name + "." + item.Name + " currently does not supported in RuntumeUnitTestToolkit(multiple parameter without TestCase or return type is invalid).");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var standardTest = item.GetCustomAttribute<NUnit.Framework.TestAttribute>(true);
|
|
||||||
if (standardTest != null)
|
|
||||||
{
|
|
||||||
if (item.GetParameters().Length == 0 && item.ReturnType == typeof(void))
|
|
||||||
{
|
|
||||||
var invoke = (Action)Delegate.CreateDelegate(typeof(Action), test, item);
|
|
||||||
AddTest(invoke.Target.GetType().Name, invoke.Method.Name, invoke, setups, teardowns);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var testData = GetTestData(item);
|
|
||||||
if (testData.Count != 0)
|
|
||||||
{
|
|
||||||
foreach (var item2 in testData)
|
|
||||||
{
|
|
||||||
Action invoke = null;
|
|
||||||
if (item.IsGenericMethod)
|
|
||||||
{
|
|
||||||
var method2 = InferGenericType(item, item2);
|
|
||||||
invoke = () => method2.Invoke(test, item2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
invoke = () => item.Invoke(test, item2);
|
|
||||||
}
|
|
||||||
var name = item.Name + "(" + string.Join(", ", item2.Select(x => x?.ToString() ?? "null")) + ")";
|
|
||||||
name = name.Replace(Char.MinValue, ' ').Replace(Char.MaxValue, ' ').Replace("<", "[").Replace(">", "]");
|
|
||||||
AddTest(test.GetType().Name, name, invoke, setups, teardowns);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UnityEngine.Debug.Log(testType.Name + "." + item.Name + " currently does not supported in RuntumeUnitTestToolkit(multiple parameter without TestCase or return type is invalid).");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
UnityEngine.Debug.LogError(testType.Name + "." + item.Name + " failed to register method, exception: " + e.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Debug.LogException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
List<object[]> GetTestData(MethodInfo methodInfo)
|
|
||||||
{
|
|
||||||
List<object[]> testCases = new List<object[]>();
|
|
||||||
|
|
||||||
var inlineData = methodInfo.GetCustomAttributes<NUnit.Framework.TestCaseAttribute>(true);
|
|
||||||
foreach (var item in inlineData)
|
|
||||||
{
|
|
||||||
testCases.Add(item.Arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
var sourceData = methodInfo.GetCustomAttributes<NUnit.Framework.TestCaseSourceAttribute>(true);
|
|
||||||
foreach (var item in sourceData)
|
|
||||||
{
|
|
||||||
var enumerator = GetTestCaseSource(methodInfo, item.SourceType, item.SourceName, item.MethodParams);
|
|
||||||
foreach (var item2 in enumerator)
|
|
||||||
{
|
|
||||||
var item3 = item2 as IEnumerable; // object[][]
|
|
||||||
if (item3 != null)
|
|
||||||
{
|
|
||||||
var l = new List<object>();
|
|
||||||
foreach (var item4 in item3)
|
|
||||||
{
|
|
||||||
l.Add(item4);
|
|
||||||
}
|
|
||||||
testCases.Add(l.ToArray());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return testCases;
|
|
||||||
}
|
|
||||||
|
|
||||||
IEnumerable GetTestCaseSource(MethodInfo method, Type sourceType, string sourceName, object[] methodParams)
|
|
||||||
{
|
|
||||||
Type type = sourceType ?? method.DeclaringType;
|
|
||||||
|
|
||||||
MemberInfo[] member = type.GetMember(sourceName, BindingFlags.FlattenHierarchy | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
|
|
||||||
if (member.Length == 1)
|
|
||||||
{
|
|
||||||
MemberInfo memberInfo = member[0];
|
|
||||||
FieldInfo fieldInfo = memberInfo as FieldInfo;
|
|
||||||
if ((object)fieldInfo != null)
|
|
||||||
{
|
|
||||||
return (!fieldInfo.IsStatic) ? ReturnErrorAsParameter("The sourceName specified on a TestCaseSourceAttribute must refer to a static field, property or method.") : ((methodParams == null) ? ((IEnumerable)fieldInfo.GetValue(null)) : ReturnErrorAsParameter("You have specified a data source field but also given a set of parameters. Fields cannot take parameters, please revise the 3rd parameter passed to the TestCaseSourceAttribute and either remove it or specify a method."));
|
|
||||||
}
|
|
||||||
PropertyInfo propertyInfo = memberInfo as PropertyInfo;
|
|
||||||
if ((object)propertyInfo != null)
|
|
||||||
{
|
|
||||||
return (!propertyInfo.GetGetMethod(nonPublic: true).IsStatic) ? ReturnErrorAsParameter("The sourceName specified on a TestCaseSourceAttribute must refer to a static field, property or method.") : ((methodParams == null) ? ((IEnumerable)propertyInfo.GetValue(null, null)) : ReturnErrorAsParameter("You have specified a data source property but also given a set of parameters. Properties cannot take parameters, please revise the 3rd parameter passed to the TestCaseSource attribute and either remove it or specify a method."));
|
|
||||||
}
|
|
||||||
MethodInfo methodInfo = memberInfo as MethodInfo;
|
|
||||||
if ((object)methodInfo != null)
|
|
||||||
{
|
|
||||||
return (!methodInfo.IsStatic) ? ReturnErrorAsParameter("The sourceName specified on a TestCaseSourceAttribute must refer to a static field, property or method.") : ((methodParams == null || methodInfo.GetParameters().Length == methodParams.Length) ? ((IEnumerable)methodInfo.Invoke(null, methodParams)) : ReturnErrorAsParameter("You have given the wrong number of arguments to the method in the TestCaseSourceAttribute, please check the number of parameters passed in the object is correct in the 3rd parameter for the TestCaseSourceAttribute and this matches the number of parameters in the target method and try again."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
MethodInfo InferGenericType(MethodInfo methodInfo, object[] parameters)
|
|
||||||
{
|
|
||||||
var set = new HashSet<Type>();
|
|
||||||
List<Type> genericParameters = new List<Type>();
|
|
||||||
foreach (var item in methodInfo.GetParameters()
|
|
||||||
.Select((x, i) => new { x.ParameterType, i })
|
|
||||||
.Where(x => x.ParameterType.IsGenericParameter)
|
|
||||||
.OrderBy(x => x.ParameterType.GenericParameterPosition))
|
|
||||||
{
|
|
||||||
if (set.Add(item.ParameterType)) // DistinctBy
|
|
||||||
{
|
|
||||||
genericParameters.Add(parameters[item.i].GetType());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return methodInfo.MakeGenericMethod(genericParameters.ToArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
IEnumerable ReturnErrorAsParameter(string name)
|
|
||||||
{
|
|
||||||
throw new Exception(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
System.Collections.IEnumerator ScrollLogToEndNextFrame()
|
|
||||||
{
|
|
||||||
yield return null;
|
|
||||||
yield return null;
|
|
||||||
logScrollBar.value = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
IEnumerator RunTestInCoroutine(KeyValuePair<string, List<TestKeyValuePair>> actionList)
|
|
||||||
{
|
|
||||||
Button self = null;
|
|
||||||
foreach (var btn in list.GetComponentsInChildren<Button>())
|
|
||||||
{
|
|
||||||
btn.interactable = false;
|
|
||||||
if (btn.name == actionList.Key) self = btn;
|
|
||||||
}
|
|
||||||
if (self != null)
|
|
||||||
{
|
|
||||||
self.GetComponent<Image>().color = normalColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
var allGreen = true;
|
|
||||||
|
|
||||||
AppendToGraphicText("<color=yellow>" + actionList.Key + "</color>\n");
|
|
||||||
WriteToConsole("Begin Test Class: " + actionList.Key);
|
|
||||||
yield return null;
|
|
||||||
|
|
||||||
var totalExecutionTime = new List<double>();
|
|
||||||
foreach (var item2 in actionList.Value)
|
|
||||||
{
|
|
||||||
// setup
|
|
||||||
try
|
|
||||||
{
|
|
||||||
foreach (var setup in item2.Setups)
|
|
||||||
{
|
|
||||||
setup();
|
|
||||||
}
|
|
||||||
|
|
||||||
// before start, cleanup
|
|
||||||
GC.Collect();
|
|
||||||
GC.WaitForPendingFinalizers();
|
|
||||||
GC.Collect();
|
|
||||||
|
|
||||||
AppendToGraphicText("<color=teal>" + item2.Key + "</color>\n");
|
|
||||||
yield return null;
|
|
||||||
|
|
||||||
var v = item2.Value;
|
|
||||||
|
|
||||||
var methodStopwatch = System.Diagnostics.Stopwatch.StartNew();
|
|
||||||
Exception exception = null;
|
|
||||||
if (v is Action)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
((Action)v).Invoke();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
exception = ex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var coroutineFactory = (Func<IEnumerator>)v;
|
|
||||||
IEnumerator coroutine = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
coroutine = coroutineFactory();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
exception = ex;
|
|
||||||
}
|
|
||||||
if (exception == null)
|
|
||||||
{
|
|
||||||
yield return StartCoroutine(UnwrapEnumerator(coroutine, ex =>
|
|
||||||
{
|
|
||||||
exception = ex;
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
methodStopwatch.Stop();
|
|
||||||
totalExecutionTime.Add(methodStopwatch.Elapsed.TotalMilliseconds);
|
|
||||||
if (exception == null)
|
|
||||||
{
|
|
||||||
AppendToGraphicText("OK, " + methodStopwatch.Elapsed.TotalMilliseconds.ToString("0.00") + "ms\n");
|
|
||||||
WriteToConsoleResult(item2.Key + ", " + methodStopwatch.Elapsed.TotalMilliseconds.ToString("0.00") + "ms", true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AppendToGraphicText("<color=red>" + exception.ToString() + "</color>\n");
|
|
||||||
WriteToConsoleResult(item2.Key + ", " + exception.ToString(), false);
|
|
||||||
allGreen = false;
|
|
||||||
allTestGreen = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
foreach (var teardown in item2.Teardowns)
|
|
||||||
{
|
|
||||||
teardown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AppendToGraphicText("[" + actionList.Key + "]" + totalExecutionTime.Sum().ToString("0.00") + "ms\n\n");
|
|
||||||
foreach (var btn in list.GetComponentsInChildren<Button>()) btn.interactable = true;
|
|
||||||
if (self != null)
|
|
||||||
{
|
|
||||||
self.GetComponent<Image>().color = allGreen ? passColor : failColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
yield return StartCoroutine(ScrollLogToEndNextFrame());
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
IEnumerator ExecuteAllInCoroutine(List<Func<Coroutine>> tests)
|
|
||||||
{
|
|
||||||
allTestGreen = true;
|
|
||||||
|
|
||||||
foreach (var item in tests)
|
|
||||||
{
|
|
||||||
yield return item();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Application.isBatchMode)
|
|
||||||
{
|
|
||||||
var scene = UnityEngine.SceneManagement.SceneManager.GetActiveScene();
|
|
||||||
bool disableAutoClose = (scene.name.Contains("DisableAutoClose"));
|
|
||||||
|
|
||||||
if (allTestGreen)
|
|
||||||
{
|
|
||||||
WriteToConsole("Test Complete Successfully");
|
|
||||||
if (!disableAutoClose)
|
|
||||||
{
|
|
||||||
Application.Quit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
WriteToConsole("Test Failed, please see [NG] log.");
|
|
||||||
if (!disableAutoClose)
|
|
||||||
{
|
|
||||||
Application.Quit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IEnumerator UnwrapEnumerator(IEnumerator enumerator, Action<Exception> exceptionCallback)
|
|
||||||
{
|
|
||||||
var hasNext = true;
|
|
||||||
while (hasNext)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
hasNext = enumerator.MoveNext();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
exceptionCallback(ex);
|
|
||||||
hasNext = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasNext)
|
|
||||||
{
|
|
||||||
// unwrap self for bug of Unity
|
|
||||||
// https://issuetracker.unity3d.com/issues/does-not-stop-coroutine-when-it-throws-exception-in-movenext-at-first-frame
|
|
||||||
var moreCoroutine = enumerator.Current as IEnumerator;
|
|
||||||
if (moreCoroutine != null)
|
|
||||||
{
|
|
||||||
yield return StartCoroutine(UnwrapEnumerator(moreCoroutine, ex =>
|
|
||||||
{
|
|
||||||
exceptionCallback(ex);
|
|
||||||
hasNext = false;
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
yield return enumerator.Current;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void WriteToConsole(string msg)
|
|
||||||
{
|
|
||||||
if (Application.isBatchMode)
|
|
||||||
{
|
|
||||||
Console.WriteLine(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppendToGraphicText(string msg)
|
|
||||||
{
|
|
||||||
if (!Application.isBatchMode)
|
|
||||||
{
|
|
||||||
if (logClear)
|
|
||||||
{
|
|
||||||
logText.text = "";
|
|
||||||
logClear = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
logText.text += msg;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
logClear = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void WriteToConsoleResult(string msg, bool green)
|
|
||||||
{
|
|
||||||
if (Application.isBatchMode)
|
|
||||||
{
|
|
||||||
if (!green)
|
|
||||||
{
|
|
||||||
var currentForeground = Console.ForegroundColor;
|
|
||||||
Console.ForegroundColor = ConsoleColor.Red;
|
|
||||||
Console.Write("[NG]");
|
|
||||||
Console.ForegroundColor = currentForeground;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var currentForeground = Console.ForegroundColor;
|
|
||||||
Console.ForegroundColor = ConsoleColor.Green;
|
|
||||||
Console.Write("[OK]");
|
|
||||||
Console.ForegroundColor = currentForeground;
|
|
||||||
}
|
|
||||||
|
|
||||||
System.Console.WriteLine(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Pair
|
|
||||||
{
|
|
||||||
public string Name;
|
|
||||||
public UnityAction Action;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class TestKeyValuePair
|
|
||||||
{
|
|
||||||
public string Key;
|
|
||||||
/// <summary>IEnumerator or Func[IEnumerator]</summary>
|
|
||||||
public object Value;
|
|
||||||
public List<Action> Setups;
|
|
||||||
public List<Action> Teardowns;
|
|
||||||
|
|
||||||
public TestKeyValuePair(string key, object value, List<Action> setups, List<Action> teardowns)
|
|
||||||
{
|
|
||||||
this.Key = key;
|
|
||||||
this.Value = value;
|
|
||||||
this.Setups = setups;
|
|
||||||
this.Teardowns = teardowns;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
{
|
|
||||||
"name": "com.cysharp.runtimeunittesttoolkit",
|
|
||||||
"displayName": "RuntimeUnitTestToolkit",
|
|
||||||
"version": "2.3.0",
|
|
||||||
"unity": "2018.3",
|
|
||||||
"description": "CLI/GUI Frontend of Unity Test Runner to test on any platform.",
|
|
||||||
"keywords": ["test"],
|
|
||||||
"category": "Tests",
|
|
||||||
"dependencies": {
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: b7883c7ac5d6ea4409a229aeab14e796
|
|
||||||
TextScriptImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
|
@ -216,7 +216,7 @@
|
||||||
// RETRY:
|
// RETRY:
|
||||||
// try
|
// try
|
||||||
// {
|
// {
|
||||||
// context.RequestHeaders["x-accesss-token"] = token;
|
// context.RequestHeaders["x-access-token"] = token;
|
||||||
// return await next(context, cancellationToken);
|
// return await next(context, cancellationToken);
|
||||||
// }
|
// }
|
||||||
// catch (UnityWebRequestException ex)
|
// catch (UnityWebRequestException ex)
|
||||||
|
|
|
@ -18,10 +18,14 @@ using UnityEngine.SceneManagement;
|
||||||
using UnityEngine.Rendering;
|
using UnityEngine.Rendering;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
|
using UnityEngine.Events;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// using DG.Tweening;
|
// using DG.Tweening;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public struct MyJob : IJob
|
public struct MyJob : IJob
|
||||||
{
|
{
|
||||||
public int loopCount;
|
public int loopCount;
|
||||||
|
@ -116,7 +120,28 @@ public class AsyncMessageBroker<T> : IDisposable
|
||||||
connection.Dispose();
|
connection.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public class WhenEachTest
|
||||||
|
{
|
||||||
|
public async UniTask Each()
|
||||||
|
{
|
||||||
|
var a = Delay(1, 3000);
|
||||||
|
var b = Delay(2, 1000);
|
||||||
|
var c = Delay(3, 2000);
|
||||||
|
|
||||||
|
var l = new List<int>();
|
||||||
|
await foreach (var item in UniTask.WhenEach(a, b, c))
|
||||||
|
{
|
||||||
|
Debug.Log(item.Result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async UniTask<int> Delay(int id, int sleep)
|
||||||
|
{
|
||||||
|
await UniTask.Delay(sleep);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public class SandboxMain : MonoBehaviour
|
public class SandboxMain : MonoBehaviour
|
||||||
{
|
{
|
||||||
|
@ -144,6 +169,19 @@ public class SandboxMain : MonoBehaviour
|
||||||
|
|
||||||
Debug.Log("Again");
|
Debug.Log("Again");
|
||||||
|
|
||||||
|
|
||||||
|
// var foo = InstantiateAsync<SandboxMain>(this).ToUniTask();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// var tako = await foo;
|
||||||
|
|
||||||
|
|
||||||
|
//UnityAction action;
|
||||||
|
|
||||||
|
|
||||||
return 10;
|
return 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -554,6 +592,7 @@ public class SandboxMain : MonoBehaviour
|
||||||
|
|
||||||
async UniTaskVoid Start()
|
async UniTaskVoid Start()
|
||||||
{
|
{
|
||||||
|
await new WhenEachTest().Each();
|
||||||
|
|
||||||
|
|
||||||
// UniTask.Delay(TimeSpan.FromSeconds(1)).TimeoutWithoutException
|
// UniTask.Delay(TimeSpan.FromSeconds(1)).TimeoutWithoutException
|
||||||
|
|
|
@ -13,7 +13,7 @@ OcclusionCullingSettings:
|
||||||
--- !u!104 &2
|
--- !u!104 &2
|
||||||
RenderSettings:
|
RenderSettings:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
serializedVersion: 9
|
serializedVersion: 10
|
||||||
m_Fog: 0
|
m_Fog: 0
|
||||||
m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
|
m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
|
||||||
m_FogMode: 3
|
m_FogMode: 3
|
||||||
|
@ -38,13 +38,11 @@ RenderSettings:
|
||||||
m_ReflectionIntensity: 1
|
m_ReflectionIntensity: 1
|
||||||
m_CustomReflection: {fileID: 0}
|
m_CustomReflection: {fileID: 0}
|
||||||
m_Sun: {fileID: 0}
|
m_Sun: {fileID: 0}
|
||||||
m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1}
|
|
||||||
m_UseRadianceAmbientProbe: 0
|
m_UseRadianceAmbientProbe: 0
|
||||||
--- !u!157 &3
|
--- !u!157 &3
|
||||||
LightmapSettings:
|
LightmapSettings:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
serializedVersion: 11
|
serializedVersion: 12
|
||||||
m_GIWorkflowMode: 1
|
|
||||||
m_GISettings:
|
m_GISettings:
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
m_BounceScale: 1
|
m_BounceScale: 1
|
||||||
|
@ -67,9 +65,6 @@ LightmapSettings:
|
||||||
m_LightmapParameters: {fileID: 0}
|
m_LightmapParameters: {fileID: 0}
|
||||||
m_LightmapsBakeMode: 1
|
m_LightmapsBakeMode: 1
|
||||||
m_TextureCompression: 1
|
m_TextureCompression: 1
|
||||||
m_FinalGather: 0
|
|
||||||
m_FinalGatherFiltering: 1
|
|
||||||
m_FinalGatherRayCount: 256
|
|
||||||
m_ReflectionCompression: 2
|
m_ReflectionCompression: 2
|
||||||
m_MixedBakeMode: 2
|
m_MixedBakeMode: 2
|
||||||
m_BakeBackend: 0
|
m_BakeBackend: 0
|
||||||
|
@ -98,13 +93,14 @@ LightmapSettings:
|
||||||
m_TrainingDataDestination: TrainingData
|
m_TrainingDataDestination: TrainingData
|
||||||
m_LightProbeSampleCountMultiplier: 4
|
m_LightProbeSampleCountMultiplier: 4
|
||||||
m_LightingDataAsset: {fileID: 0}
|
m_LightingDataAsset: {fileID: 0}
|
||||||
m_UseShadowmask: 1
|
m_LightingSettings: {fileID: 4890085278179872738, guid: 814185d368762ed45a2298d112780689,
|
||||||
|
type: 2}
|
||||||
--- !u!196 &4
|
--- !u!196 &4
|
||||||
NavMeshSettings:
|
NavMeshSettings:
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
m_BuildSettings:
|
m_BuildSettings:
|
||||||
serializedVersion: 2
|
serializedVersion: 3
|
||||||
agentTypeID: 0
|
agentTypeID: 0
|
||||||
agentRadius: 0.5
|
agentRadius: 0.5
|
||||||
agentHeight: 2
|
agentHeight: 2
|
||||||
|
@ -117,7 +113,9 @@ NavMeshSettings:
|
||||||
cellSize: 0.16666667
|
cellSize: 0.16666667
|
||||||
manualTileSize: 0
|
manualTileSize: 0
|
||||||
tileSize: 256
|
tileSize: 256
|
||||||
accuratePlacement: 0
|
buildHeightMesh: 0
|
||||||
|
maxJobWorkers: 0
|
||||||
|
preserveTilesOutsideBounds: 0
|
||||||
debug:
|
debug:
|
||||||
m_Flags: 0
|
m_Flags: 0
|
||||||
m_NavMeshData: {fileID: 0}
|
m_NavMeshData: {fileID: 0}
|
||||||
|
@ -150,10 +148,10 @@ RectTransform:
|
||||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children:
|
m_Children:
|
||||||
- {fileID: 1584557232}
|
- {fileID: 1584557232}
|
||||||
m_Father: {fileID: 1556045508}
|
m_Father: {fileID: 1556045508}
|
||||||
m_RootOrder: 0
|
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||||
|
@ -174,6 +172,7 @@ MonoBehaviour:
|
||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
m_Navigation:
|
m_Navigation:
|
||||||
m_Mode: 3
|
m_Mode: 3
|
||||||
|
m_WrapAround: 0
|
||||||
m_SelectOnUp: {fileID: 0}
|
m_SelectOnUp: {fileID: 0}
|
||||||
m_SelectOnDown: {fileID: 0}
|
m_SelectOnDown: {fileID: 0}
|
||||||
m_SelectOnLeft: {fileID: 0}
|
m_SelectOnLeft: {fileID: 0}
|
||||||
|
@ -218,6 +217,8 @@ MonoBehaviour:
|
||||||
m_Material: {fileID: 0}
|
m_Material: {fileID: 0}
|
||||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||||
m_RaycastTarget: 1
|
m_RaycastTarget: 1
|
||||||
|
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
m_Maskable: 1
|
||||||
m_OnCullStateChanged:
|
m_OnCullStateChanged:
|
||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
m_Calls: []
|
m_Calls: []
|
||||||
|
@ -270,9 +271,17 @@ Camera:
|
||||||
m_projectionMatrixMode: 1
|
m_projectionMatrixMode: 1
|
||||||
m_GateFitMode: 2
|
m_GateFitMode: 2
|
||||||
m_FOVAxisMode: 0
|
m_FOVAxisMode: 0
|
||||||
|
m_Iso: 200
|
||||||
|
m_ShutterSpeed: 0.005
|
||||||
|
m_Aperture: 16
|
||||||
|
m_FocusDistance: 10
|
||||||
|
m_FocalLength: 50
|
||||||
|
m_BladeCount: 5
|
||||||
|
m_Curvature: {x: 2, y: 11}
|
||||||
|
m_BarrelClipping: 0.25
|
||||||
|
m_Anamorphism: 0
|
||||||
m_SensorSize: {x: 36, y: 24}
|
m_SensorSize: {x: 36, y: 24}
|
||||||
m_LensShift: {x: 0, y: 0}
|
m_LensShift: {x: 0, y: 0}
|
||||||
m_FocalLength: 50
|
|
||||||
m_NormalizedViewPortRect:
|
m_NormalizedViewPortRect:
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
x: 0
|
x: 0
|
||||||
|
@ -306,12 +315,13 @@ Transform:
|
||||||
m_PrefabInstance: {fileID: 0}
|
m_PrefabInstance: {fileID: 0}
|
||||||
m_PrefabAsset: {fileID: 0}
|
m_PrefabAsset: {fileID: 0}
|
||||||
m_GameObject: {fileID: 518730348}
|
m_GameObject: {fileID: 518730348}
|
||||||
|
serializedVersion: 2
|
||||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
m_LocalPosition: {x: 488, y: 418, z: 0}
|
m_LocalPosition: {x: 488, y: 418, z: 0}
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children: []
|
m_Children: []
|
||||||
m_Father: {fileID: 0}
|
m_Father: {fileID: 0}
|
||||||
m_RootOrder: 1
|
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
--- !u!1 &519420028
|
--- !u!1 &519420028
|
||||||
GameObject:
|
GameObject:
|
||||||
|
@ -352,9 +362,11 @@ MonoBehaviour:
|
||||||
m_Script: {fileID: 11500000, guid: f0bc6c75abb2e0b47a25aa49bfd488ed, type: 3}
|
m_Script: {fileID: 11500000, guid: f0bc6c75abb2e0b47a25aa49bfd488ed, type: 3}
|
||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
camera: {fileID: 518730349}
|
mycamera: {fileID: 0}
|
||||||
okButton: {fileID: 16537672}
|
okButton: {fileID: 16537672}
|
||||||
cancelButton: {fileID: 628393011}
|
cancelButton: {fileID: 628393011}
|
||||||
|
RP1:
|
||||||
|
latestValue: 0
|
||||||
text: {fileID: 2101290655}
|
text: {fileID: 2101290655}
|
||||||
button: {fileID: 0}
|
button: {fileID: 0}
|
||||||
--- !u!20 &519420031
|
--- !u!20 &519420031
|
||||||
|
@ -371,9 +383,17 @@ Camera:
|
||||||
m_projectionMatrixMode: 1
|
m_projectionMatrixMode: 1
|
||||||
m_GateFitMode: 2
|
m_GateFitMode: 2
|
||||||
m_FOVAxisMode: 0
|
m_FOVAxisMode: 0
|
||||||
|
m_Iso: 200
|
||||||
|
m_ShutterSpeed: 0.005
|
||||||
|
m_Aperture: 16
|
||||||
|
m_FocusDistance: 10
|
||||||
|
m_FocalLength: 50
|
||||||
|
m_BladeCount: 5
|
||||||
|
m_Curvature: {x: 2, y: 11}
|
||||||
|
m_BarrelClipping: 0.25
|
||||||
|
m_Anamorphism: 0
|
||||||
m_SensorSize: {x: 36, y: 24}
|
m_SensorSize: {x: 36, y: 24}
|
||||||
m_LensShift: {x: 0, y: 0}
|
m_LensShift: {x: 0, y: 0}
|
||||||
m_FocalLength: 50
|
|
||||||
m_NormalizedViewPortRect:
|
m_NormalizedViewPortRect:
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
x: 0
|
x: 0
|
||||||
|
@ -407,12 +427,13 @@ Transform:
|
||||||
m_PrefabInstance: {fileID: 0}
|
m_PrefabInstance: {fileID: 0}
|
||||||
m_PrefabAsset: {fileID: 0}
|
m_PrefabAsset: {fileID: 0}
|
||||||
m_GameObject: {fileID: 519420028}
|
m_GameObject: {fileID: 519420028}
|
||||||
|
serializedVersion: 2
|
||||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
m_LocalPosition: {x: 0, y: 0, z: -10}
|
m_LocalPosition: {x: 0, y: 0, z: -10}
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children: []
|
m_Children: []
|
||||||
m_Father: {fileID: 0}
|
m_Father: {fileID: 0}
|
||||||
m_RootOrder: 0
|
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
--- !u!1 &628393009
|
--- !u!1 &628393009
|
||||||
GameObject:
|
GameObject:
|
||||||
|
@ -443,10 +464,10 @@ RectTransform:
|
||||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children:
|
m_Children:
|
||||||
- {fileID: 865871445}
|
- {fileID: 865871445}
|
||||||
m_Father: {fileID: 1556045508}
|
m_Father: {fileID: 1556045508}
|
||||||
m_RootOrder: 1
|
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||||
|
@ -467,6 +488,7 @@ MonoBehaviour:
|
||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
m_Navigation:
|
m_Navigation:
|
||||||
m_Mode: 3
|
m_Mode: 3
|
||||||
|
m_WrapAround: 0
|
||||||
m_SelectOnUp: {fileID: 0}
|
m_SelectOnUp: {fileID: 0}
|
||||||
m_SelectOnDown: {fileID: 0}
|
m_SelectOnDown: {fileID: 0}
|
||||||
m_SelectOnLeft: {fileID: 0}
|
m_SelectOnLeft: {fileID: 0}
|
||||||
|
@ -511,6 +533,8 @@ MonoBehaviour:
|
||||||
m_Material: {fileID: 0}
|
m_Material: {fileID: 0}
|
||||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||||
m_RaycastTarget: 1
|
m_RaycastTarget: 1
|
||||||
|
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
m_Maskable: 1
|
||||||
m_OnCullStateChanged:
|
m_OnCullStateChanged:
|
||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
m_Calls: []
|
m_Calls: []
|
||||||
|
@ -560,9 +584,9 @@ RectTransform:
|
||||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children: []
|
m_Children: []
|
||||||
m_Father: {fileID: 628393010}
|
m_Father: {fileID: 628393010}
|
||||||
m_RootOrder: 0
|
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0, y: 0}
|
m_AnchorMin: {x: 0, y: 0}
|
||||||
m_AnchorMax: {x: 1, y: 1}
|
m_AnchorMax: {x: 1, y: 1}
|
||||||
|
@ -584,6 +608,8 @@ MonoBehaviour:
|
||||||
m_Material: {fileID: 0}
|
m_Material: {fileID: 0}
|
||||||
m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1}
|
m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1}
|
||||||
m_RaycastTarget: 1
|
m_RaycastTarget: 1
|
||||||
|
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
m_Maskable: 1
|
||||||
m_OnCullStateChanged:
|
m_OnCullStateChanged:
|
||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
m_Calls: []
|
m_Calls: []
|
||||||
|
@ -639,6 +665,7 @@ MonoBehaviour:
|
||||||
m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48677, type: 3}
|
m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48677, type: 3}
|
||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
|
m_SendPointerHoverToParent: 1
|
||||||
m_HorizontalAxis: Horizontal
|
m_HorizontalAxis: Horizontal
|
||||||
m_VerticalAxis: Vertical
|
m_VerticalAxis: Vertical
|
||||||
m_SubmitButton: Submit
|
m_SubmitButton: Submit
|
||||||
|
@ -668,12 +695,13 @@ Transform:
|
||||||
m_PrefabInstance: {fileID: 0}
|
m_PrefabInstance: {fileID: 0}
|
||||||
m_PrefabAsset: {fileID: 0}
|
m_PrefabAsset: {fileID: 0}
|
||||||
m_GameObject: {fileID: 872009839}
|
m_GameObject: {fileID: 872009839}
|
||||||
|
serializedVersion: 2
|
||||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children: []
|
m_Children: []
|
||||||
m_Father: {fileID: 0}
|
m_Father: {fileID: 0}
|
||||||
m_RootOrder: 2
|
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
--- !u!1 &1556045504
|
--- !u!1 &1556045504
|
||||||
GameObject:
|
GameObject:
|
||||||
|
@ -733,6 +761,7 @@ MonoBehaviour:
|
||||||
m_FallbackScreenDPI: 96
|
m_FallbackScreenDPI: 96
|
||||||
m_DefaultSpriteDPI: 96
|
m_DefaultSpriteDPI: 96
|
||||||
m_DynamicPixelsPerUnit: 1
|
m_DynamicPixelsPerUnit: 1
|
||||||
|
m_PresetInfoIsWorld: 0
|
||||||
--- !u!223 &1556045507
|
--- !u!223 &1556045507
|
||||||
Canvas:
|
Canvas:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
@ -750,7 +779,9 @@ Canvas:
|
||||||
m_OverrideSorting: 0
|
m_OverrideSorting: 0
|
||||||
m_OverridePixelPerfect: 0
|
m_OverridePixelPerfect: 0
|
||||||
m_SortingBucketNormalizedSize: 0
|
m_SortingBucketNormalizedSize: 0
|
||||||
|
m_VertexColorAlwaysGammaSpace: 0
|
||||||
m_AdditionalShaderChannelsFlag: 0
|
m_AdditionalShaderChannelsFlag: 0
|
||||||
|
m_UpdateRectTransformForStandalone: 0
|
||||||
m_SortingLayerID: 0
|
m_SortingLayerID: 0
|
||||||
m_SortingOrder: 0
|
m_SortingOrder: 0
|
||||||
m_TargetDisplay: 0
|
m_TargetDisplay: 0
|
||||||
|
@ -764,12 +795,12 @@ RectTransform:
|
||||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||||
m_LocalScale: {x: 0, y: 0, z: 0}
|
m_LocalScale: {x: 0, y: 0, z: 0}
|
||||||
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children:
|
m_Children:
|
||||||
- {fileID: 16537671}
|
- {fileID: 16537671}
|
||||||
- {fileID: 628393010}
|
- {fileID: 628393010}
|
||||||
- {fileID: 2101290654}
|
- {fileID: 2101290654}
|
||||||
m_Father: {fileID: 0}
|
m_Father: {fileID: 0}
|
||||||
m_RootOrder: 3
|
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0, y: 0}
|
m_AnchorMin: {x: 0, y: 0}
|
||||||
m_AnchorMax: {x: 0, y: 0}
|
m_AnchorMax: {x: 0, y: 0}
|
||||||
|
@ -804,9 +835,9 @@ RectTransform:
|
||||||
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
|
||||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children: []
|
m_Children: []
|
||||||
m_Father: {fileID: 16537671}
|
m_Father: {fileID: 16537671}
|
||||||
m_RootOrder: 0
|
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0, y: 0}
|
m_AnchorMin: {x: 0, y: 0}
|
||||||
m_AnchorMax: {x: 1, y: 1}
|
m_AnchorMax: {x: 1, y: 1}
|
||||||
|
@ -828,6 +859,8 @@ MonoBehaviour:
|
||||||
m_Material: {fileID: 0}
|
m_Material: {fileID: 0}
|
||||||
m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1}
|
m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1}
|
||||||
m_RaycastTarget: 1
|
m_RaycastTarget: 1
|
||||||
|
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
m_Maskable: 1
|
||||||
m_OnCullStateChanged:
|
m_OnCullStateChanged:
|
||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
m_Calls: []
|
m_Calls: []
|
||||||
|
@ -883,9 +916,9 @@ RectTransform:
|
||||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
|
m_ConstrainProportionsScale: 0
|
||||||
m_Children: []
|
m_Children: []
|
||||||
m_Father: {fileID: 1556045508}
|
m_Father: {fileID: 1556045508}
|
||||||
m_RootOrder: 2
|
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||||
|
@ -907,6 +940,8 @@ MonoBehaviour:
|
||||||
m_Material: {fileID: 0}
|
m_Material: {fileID: 0}
|
||||||
m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1}
|
m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1}
|
||||||
m_RaycastTarget: 1
|
m_RaycastTarget: 1
|
||||||
|
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
m_Maskable: 1
|
||||||
m_OnCullStateChanged:
|
m_OnCullStateChanged:
|
||||||
m_PersistentCalls:
|
m_PersistentCalls:
|
||||||
m_Calls: []
|
m_Calls: []
|
||||||
|
@ -932,3 +967,11 @@ CanvasRenderer:
|
||||||
m_PrefabAsset: {fileID: 0}
|
m_PrefabAsset: {fileID: 0}
|
||||||
m_GameObject: {fileID: 2101290653}
|
m_GameObject: {fileID: 2101290653}
|
||||||
m_CullTransparentMesh: 0
|
m_CullTransparentMesh: 0
|
||||||
|
--- !u!1660057539 &9223372036854775807
|
||||||
|
SceneRoots:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_Roots:
|
||||||
|
- {fileID: 519420032}
|
||||||
|
- {fileID: 518730350}
|
||||||
|
- {fileID: 872009842}
|
||||||
|
- {fileID: 1556045508}
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
// https://github.com/Cysharp/UniTask/issues/617
|
||||||
|
|
||||||
|
public class WaitWhileTest : MonoBehaviour
|
||||||
|
{
|
||||||
|
private const float c_CallInterval = 0.3f;
|
||||||
|
private float m_JustBeforeCallTime;
|
||||||
|
|
||||||
|
private TaskObj m_TestObj;
|
||||||
|
|
||||||
|
// Start is called before the first frame update
|
||||||
|
void Start()
|
||||||
|
{
|
||||||
|
m_JustBeforeCallTime = Time.unscaledTime;
|
||||||
|
m_TestObj = new TaskObj();
|
||||||
|
// m_TestObj.Test(CancellationToken.None).Forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update is called once per frame
|
||||||
|
void Update()
|
||||||
|
{
|
||||||
|
if (Time.unscaledTime - m_JustBeforeCallTime > c_CallInterval)
|
||||||
|
{
|
||||||
|
m_JustBeforeCallTime = Time.unscaledTime;
|
||||||
|
m_TestObj.Test(CancellationToken.None).Forget();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class TaskObj
|
||||||
|
{
|
||||||
|
private CancellationTokenSource m_CancelTokenSource;
|
||||||
|
private const float c_FinishElapsedTime = 0.1f;
|
||||||
|
private float m_StartTime;
|
||||||
|
public async UniTask Test(CancellationToken token)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CancelAndDisposeTokenSource();
|
||||||
|
m_CancelTokenSource = CancellationTokenSource.CreateLinkedTokenSource(token);
|
||||||
|
m_StartTime = Time.unscaledTime;
|
||||||
|
await UniTask.WaitWhile(IsContinued, cancellationToken: m_CancelTokenSource.Token, cancelImmediately: true);
|
||||||
|
Debug.Log("Task Finished");
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException)
|
||||||
|
{
|
||||||
|
Debug.LogWarning("Task Canceled");
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
CancelAndDisposeTokenSource();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CancelAndDisposeTokenSource()
|
||||||
|
{
|
||||||
|
m_CancelTokenSource?.Cancel();
|
||||||
|
m_CancelTokenSource?.Dispose();
|
||||||
|
m_CancelTokenSource = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsContinued()
|
||||||
|
{
|
||||||
|
return Time.unscaledTime - m_StartTime > c_FinishElapsedTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 660baed073888b8438569f57e42679b2
|
guid: a478e5f6126dc184ca902adfb35401b4
|
||||||
timeCreated: 1476793308
|
|
||||||
licenseType: Pro
|
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
defaultReferences: []
|
defaultReferences: []
|
||||||
executionOrder: 0
|
executionOrder: 0
|
|
@ -0,0 +1,90 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System.Threading;
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
using FluentAssertions;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.Networking;
|
||||||
|
using UnityEngine.TestTools;
|
||||||
|
|
||||||
|
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
|
||||||
|
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||||
|
|
||||||
|
namespace Cysharp.Threading.TasksTests
|
||||||
|
{
|
||||||
|
public class AsyncOperationTest
|
||||||
|
{
|
||||||
|
[UnityTest]
|
||||||
|
public IEnumerator ResourcesLoad_Completed() => UniTask.ToCoroutine(async () =>
|
||||||
|
{
|
||||||
|
var asyncOperation = Resources.LoadAsync<Texture2D>("sample_texture");
|
||||||
|
await asyncOperation.ToUniTask();
|
||||||
|
asyncOperation.isDone.Should().BeTrue();
|
||||||
|
asyncOperation.asset.GetType().Should().Be(typeof(Texture2D));
|
||||||
|
});
|
||||||
|
|
||||||
|
[UnityTest]
|
||||||
|
public IEnumerator ResourcesLoad_CancelOnPlayerLoop() => UniTask.ToCoroutine(async () =>
|
||||||
|
{
|
||||||
|
var cts = new CancellationTokenSource();
|
||||||
|
var task = Resources.LoadAsync<Texture>("sample_texture").ToUniTask(cancellationToken: cts.Token, cancelImmediately: false);
|
||||||
|
|
||||||
|
cts.Cancel();
|
||||||
|
task.Status.Should().Be(UniTaskStatus.Pending);
|
||||||
|
|
||||||
|
await UniTask.NextFrame();
|
||||||
|
task.Status.Should().Be(UniTaskStatus.Canceled);
|
||||||
|
});
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ResourcesLoad_CancelImmediately()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
var cts = new CancellationTokenSource();
|
||||||
|
var task = Resources.LoadAsync<Texture>("sample_texture").ToUniTask(cancellationToken: cts.Token, cancelImmediately: true);
|
||||||
|
|
||||||
|
cts.Cancel();
|
||||||
|
task.Status.Should().Be(UniTaskStatus.Canceled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if ENABLE_UNITYWEBREQUEST && (!UNITY_2019_1_OR_NEWER || UNITASK_WEBREQUEST_SUPPORT)
|
||||||
|
[UnityTest]
|
||||||
|
public IEnumerator UnityWebRequest_Completed() => UniTask.ToCoroutine(async () =>
|
||||||
|
{
|
||||||
|
var filePath = System.IO.Path.Combine(Application.dataPath, "Tests", "Resources", "sample_texture.png");
|
||||||
|
var asyncOperation = UnityWebRequest.Get($"file://{filePath}").SendWebRequest();
|
||||||
|
await asyncOperation.ToUniTask();
|
||||||
|
|
||||||
|
asyncOperation.isDone.Should().BeTrue();
|
||||||
|
asyncOperation.webRequest.result.Should().Be(UnityWebRequest.Result.Success);
|
||||||
|
});
|
||||||
|
|
||||||
|
[UnityTest]
|
||||||
|
public IEnumerator UnityWebRequest_CancelOnPlayerLoop() => UniTask.ToCoroutine(async () =>
|
||||||
|
{
|
||||||
|
var cts = new CancellationTokenSource();
|
||||||
|
var filePath = System.IO.Path.Combine(Application.dataPath, "Tests", "Resources", "sample_texture.png");
|
||||||
|
var task = UnityWebRequest.Get($"file://{filePath}").SendWebRequest().ToUniTask(cancellationToken: cts.Token);
|
||||||
|
|
||||||
|
cts.Cancel();
|
||||||
|
task.Status.Should().Be(UniTaskStatus.Pending);
|
||||||
|
|
||||||
|
await UniTask.NextFrame();
|
||||||
|
task.Status.Should().Be(UniTaskStatus.Canceled);
|
||||||
|
});
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void UnityWebRequest_CancelImmediately()
|
||||||
|
{
|
||||||
|
var cts = new CancellationTokenSource();
|
||||||
|
cts.Cancel();
|
||||||
|
var filePath = System.IO.Path.Combine(Application.dataPath, "Tests", "Resources", "sample_texture.png");
|
||||||
|
var task = UnityWebRequest.Get($"file://{filePath}").SendWebRequest().ToUniTask(cancellationToken: cts.Token, cancelImmediately: true);
|
||||||
|
|
||||||
|
task.Status.Should().Be(UniTaskStatus.Canceled);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,3 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 295d574a16494d6aa4d02fcb32179e39
|
||||||
|
timeCreated: 1698887128
|
|
@ -145,6 +145,11 @@ namespace Cysharp.Threading.TasksTests
|
||||||
public int MyProperty { get; set; }
|
public int MyProperty { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class MyBooleanClass
|
||||||
|
{
|
||||||
|
public bool MyProperty { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
[UnityTest]
|
[UnityTest]
|
||||||
public IEnumerator WaitUntil() => UniTask.ToCoroutine(async () =>
|
public IEnumerator WaitUntil() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
{
|
||||||
|
@ -159,6 +164,20 @@ namespace Cysharp.Threading.TasksTests
|
||||||
diff.Should().Be(11);
|
diff.Should().Be(11);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
[UnityTest]
|
||||||
|
public IEnumerator WaitUntilWithState() => UniTask.ToCoroutine(async () =>
|
||||||
|
{
|
||||||
|
var v = new MyBooleanClass { MyProperty = false };
|
||||||
|
|
||||||
|
UniTask.DelayFrame(10, PlayerLoopTiming.PostLateUpdate).ContinueWith(() => v.MyProperty = true).Forget();
|
||||||
|
|
||||||
|
var startFrame = Time.frameCount;
|
||||||
|
await UniTask.WaitUntil(v, static v => v.MyProperty, PlayerLoopTiming.EarlyUpdate);
|
||||||
|
|
||||||
|
var diff = Time.frameCount - startFrame;
|
||||||
|
diff.Should().Be(11);
|
||||||
|
});
|
||||||
|
|
||||||
[UnityTest]
|
[UnityTest]
|
||||||
public IEnumerator WaitWhile() => UniTask.ToCoroutine(async () =>
|
public IEnumerator WaitWhile() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
{
|
||||||
|
@ -173,6 +192,20 @@ namespace Cysharp.Threading.TasksTests
|
||||||
diff.Should().Be(11);
|
diff.Should().Be(11);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
[UnityTest]
|
||||||
|
public IEnumerator WaitWhileWithState() => UniTask.ToCoroutine(async () =>
|
||||||
|
{
|
||||||
|
var v = new MyBooleanClass { MyProperty = true };
|
||||||
|
|
||||||
|
UniTask.DelayFrame(10, PlayerLoopTiming.PostLateUpdate).ContinueWith(() => v.MyProperty = false).Forget();
|
||||||
|
|
||||||
|
var startFrame = Time.frameCount;
|
||||||
|
await UniTask.WaitWhile(v, static v => v.MyProperty, PlayerLoopTiming.EarlyUpdate);
|
||||||
|
|
||||||
|
var diff = Time.frameCount - startFrame;
|
||||||
|
diff.Should().Be(11);
|
||||||
|
});
|
||||||
|
|
||||||
[UnityTest]
|
[UnityTest]
|
||||||
public IEnumerator WaitUntilValueChanged() => UniTask.ToCoroutine(async () =>
|
public IEnumerator WaitUntilValueChanged() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
using Cysharp.Threading.Tasks;
|
#pragma warning disable CS0618
|
||||||
|
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
using Cysharp.Threading.Tasks.Linq;
|
using Cysharp.Threading.Tasks.Linq;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 894f21dfce4e82343a91661e1ec1a455
|
guid: 8d82913edf6ac48aca30f66ae9ba42d6
|
||||||
folderAsset: yes
|
folderAsset: yes
|
||||||
DefaultImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
|
@ -0,0 +1,215 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 535006a83baed4ebda99d24a909a2efe
|
||||||
|
TextureImporter:
|
||||||
|
internalIDToNameTable:
|
||||||
|
- first:
|
||||||
|
213: -2664112245596591751
|
||||||
|
second: sample_texture_0
|
||||||
|
- first:
|
||||||
|
213: -4606777057269188692
|
||||||
|
second: sample_texture_1
|
||||||
|
- first:
|
||||||
|
213: 1950921086533113773
|
||||||
|
second: sample_texture_2
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 13
|
||||||
|
mipmaps:
|
||||||
|
mipMapMode: 0
|
||||||
|
enableMipMap: 0
|
||||||
|
sRGBTexture: 1
|
||||||
|
linearTexture: 0
|
||||||
|
fadeOut: 0
|
||||||
|
borderMipMap: 0
|
||||||
|
mipMapsPreserveCoverage: 0
|
||||||
|
alphaTestReferenceValue: 0.5
|
||||||
|
mipMapFadeDistanceStart: 1
|
||||||
|
mipMapFadeDistanceEnd: 3
|
||||||
|
bumpmap:
|
||||||
|
convertToNormalMap: 0
|
||||||
|
externalNormalMap: 0
|
||||||
|
heightScale: 0.25
|
||||||
|
normalMapFilter: 0
|
||||||
|
flipGreenChannel: 0
|
||||||
|
isReadable: 0
|
||||||
|
streamingMipmaps: 0
|
||||||
|
streamingMipmapsPriority: 0
|
||||||
|
vTOnly: 0
|
||||||
|
ignoreMipmapLimit: 0
|
||||||
|
grayScaleToAlpha: 0
|
||||||
|
generateCubemap: 6
|
||||||
|
cubemapConvolution: 0
|
||||||
|
seamlessCubemap: 0
|
||||||
|
textureFormat: 1
|
||||||
|
maxTextureSize: 2048
|
||||||
|
textureSettings:
|
||||||
|
serializedVersion: 2
|
||||||
|
filterMode: 1
|
||||||
|
aniso: 1
|
||||||
|
mipBias: 0
|
||||||
|
wrapU: 1
|
||||||
|
wrapV: 1
|
||||||
|
wrapW: 1
|
||||||
|
nPOTScale: 0
|
||||||
|
lightmap: 0
|
||||||
|
compressionQuality: 50
|
||||||
|
spriteMode: 2
|
||||||
|
spriteExtrude: 1
|
||||||
|
spriteMeshType: 1
|
||||||
|
alignment: 0
|
||||||
|
spritePivot: {x: 0.5, y: 0.5}
|
||||||
|
spritePixelsToUnits: 100
|
||||||
|
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
spriteGenerateFallbackPhysicsShape: 1
|
||||||
|
alphaUsage: 1
|
||||||
|
alphaIsTransparency: 1
|
||||||
|
spriteTessellationDetail: -1
|
||||||
|
textureType: 8
|
||||||
|
textureShape: 1
|
||||||
|
singleChannelComponent: 0
|
||||||
|
flipbookRows: 1
|
||||||
|
flipbookColumns: 1
|
||||||
|
maxTextureSizeSet: 0
|
||||||
|
compressionQualitySet: 0
|
||||||
|
textureFormatSet: 0
|
||||||
|
ignorePngGamma: 0
|
||||||
|
applyGammaDecoding: 0
|
||||||
|
swizzle: 50462976
|
||||||
|
cookieLightType: 0
|
||||||
|
platformSettings:
|
||||||
|
- serializedVersion: 3
|
||||||
|
buildTarget: DefaultTexturePlatform
|
||||||
|
maxTextureSize: 2048
|
||||||
|
resizeAlgorithm: 0
|
||||||
|
textureFormat: -1
|
||||||
|
textureCompression: 1
|
||||||
|
compressionQuality: 50
|
||||||
|
crunchedCompression: 0
|
||||||
|
allowsAlphaSplitting: 0
|
||||||
|
overridden: 0
|
||||||
|
ignorePlatformSupport: 0
|
||||||
|
androidETC2FallbackOverride: 0
|
||||||
|
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||||
|
- serializedVersion: 3
|
||||||
|
buildTarget: WebGL
|
||||||
|
maxTextureSize: 2048
|
||||||
|
resizeAlgorithm: 0
|
||||||
|
textureFormat: -1
|
||||||
|
textureCompression: 1
|
||||||
|
compressionQuality: 50
|
||||||
|
crunchedCompression: 0
|
||||||
|
allowsAlphaSplitting: 0
|
||||||
|
overridden: 0
|
||||||
|
ignorePlatformSupport: 0
|
||||||
|
androidETC2FallbackOverride: 0
|
||||||
|
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||||
|
- serializedVersion: 3
|
||||||
|
buildTarget: Standalone
|
||||||
|
maxTextureSize: 2048
|
||||||
|
resizeAlgorithm: 0
|
||||||
|
textureFormat: -1
|
||||||
|
textureCompression: 1
|
||||||
|
compressionQuality: 50
|
||||||
|
crunchedCompression: 0
|
||||||
|
allowsAlphaSplitting: 0
|
||||||
|
overridden: 0
|
||||||
|
ignorePlatformSupport: 0
|
||||||
|
androidETC2FallbackOverride: 0
|
||||||
|
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||||
|
- serializedVersion: 3
|
||||||
|
buildTarget: iPhone
|
||||||
|
maxTextureSize: 2048
|
||||||
|
resizeAlgorithm: 0
|
||||||
|
textureFormat: -1
|
||||||
|
textureCompression: 1
|
||||||
|
compressionQuality: 50
|
||||||
|
crunchedCompression: 0
|
||||||
|
allowsAlphaSplitting: 0
|
||||||
|
overridden: 0
|
||||||
|
ignorePlatformSupport: 0
|
||||||
|
androidETC2FallbackOverride: 0
|
||||||
|
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||||
|
spriteSheet:
|
||||||
|
serializedVersion: 2
|
||||||
|
sprites:
|
||||||
|
- serializedVersion: 2
|
||||||
|
name: sample_texture_0
|
||||||
|
rect:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 0
|
||||||
|
y: 76
|
||||||
|
width: 243
|
||||||
|
height: 251
|
||||||
|
alignment: 0
|
||||||
|
pivot: {x: 0, y: 0}
|
||||||
|
border: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
outline: []
|
||||||
|
physicsShape: []
|
||||||
|
tessellationDetail: -1
|
||||||
|
bones: []
|
||||||
|
spriteID: 9796277170c270bd0800000000000000
|
||||||
|
internalID: -2664112245596591751
|
||||||
|
vertices: []
|
||||||
|
indices:
|
||||||
|
edges: []
|
||||||
|
weights: []
|
||||||
|
- serializedVersion: 2
|
||||||
|
name: sample_texture_1
|
||||||
|
rect:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 227
|
||||||
|
y: 0
|
||||||
|
width: 190
|
||||||
|
height: 231
|
||||||
|
alignment: 0
|
||||||
|
pivot: {x: 0, y: 0}
|
||||||
|
border: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
outline: []
|
||||||
|
physicsShape: []
|
||||||
|
tessellationDetail: -1
|
||||||
|
bones: []
|
||||||
|
spriteID: ca7fc069ca07110c0800000000000000
|
||||||
|
internalID: -4606777057269188692
|
||||||
|
vertices: []
|
||||||
|
indices:
|
||||||
|
edges: []
|
||||||
|
weights: []
|
||||||
|
- serializedVersion: 2
|
||||||
|
name: sample_texture_2
|
||||||
|
rect:
|
||||||
|
serializedVersion: 2
|
||||||
|
x: 398
|
||||||
|
y: 87
|
||||||
|
width: 202
|
||||||
|
height: 188
|
||||||
|
alignment: 0
|
||||||
|
pivot: {x: 0, y: 0}
|
||||||
|
border: {x: 0, y: 0, z: 0, w: 0}
|
||||||
|
outline: []
|
||||||
|
physicsShape: []
|
||||||
|
tessellationDetail: -1
|
||||||
|
bones: []
|
||||||
|
spriteID: da710ab4460131b10800000000000000
|
||||||
|
internalID: 1950921086533113773
|
||||||
|
vertices: []
|
||||||
|
indices:
|
||||||
|
edges: []
|
||||||
|
weights: []
|
||||||
|
outline: []
|
||||||
|
physicsShape: []
|
||||||
|
bones: []
|
||||||
|
spriteID:
|
||||||
|
internalID: 0
|
||||||
|
vertices: []
|
||||||
|
indices:
|
||||||
|
edges: []
|
||||||
|
weights: []
|
||||||
|
secondaryTextures: []
|
||||||
|
nameFileIdTable:
|
||||||
|
sample_texture_0: -2664112245596591751
|
||||||
|
sample_texture_1: -4606777057269188692
|
||||||
|
sample_texture_2: 1950921086533113773
|
||||||
|
mipmapLimitGroupName:
|
||||||
|
pSDRemoveMatte: 0
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -1,4 +1,6 @@
|
||||||
#if !(UNITY_4_5 || UNITY_4_6 || UNITY_4_7 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2)
|
#pragma warning disable CS0618
|
||||||
|
|
||||||
|
#if !(UNITY_4_5 || UNITY_4_6 || UNITY_4_7 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2)
|
||||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||||
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"com.cysharp.runtimeunittesttoolkit": "https://github.com/Cysharp/RuntimeUnitTestToolkit.git?path=RuntimeUnitTestToolkit/Assets/RuntimeUnitTestToolkit#2.6.0",
|
||||||
|
"com.unity.collab-proxy": "2.4.3",
|
||||||
|
"com.unity.ide.rider": "3.0.31",
|
||||||
|
"com.unity.ide.visualstudio": "2.0.22",
|
||||||
|
"com.unity.ide.vscode": "1.2.5",
|
||||||
|
"com.unity.test-framework": "1.1.33",
|
||||||
|
"com.unity.textmeshpro": "3.0.6",
|
||||||
|
"com.unity.timeline": "1.7.6",
|
||||||
|
"com.unity.toolchain.win-x86_64-linux-x86_64": "2.0.9",
|
||||||
|
"com.unity.ugui": "1.0.0",
|
||||||
|
"com.unity.modules.ai": "1.0.0",
|
||||||
|
"com.unity.modules.androidjni": "1.0.0",
|
||||||
|
"com.unity.modules.animation": "1.0.0",
|
||||||
|
"com.unity.modules.assetbundle": "1.0.0",
|
||||||
|
"com.unity.modules.audio": "1.0.0",
|
||||||
|
"com.unity.modules.cloth": "1.0.0",
|
||||||
|
"com.unity.modules.director": "1.0.0",
|
||||||
|
"com.unity.modules.imageconversion": "1.0.0",
|
||||||
|
"com.unity.modules.imgui": "1.0.0",
|
||||||
|
"com.unity.modules.jsonserialize": "1.0.0",
|
||||||
|
"com.unity.modules.particlesystem": "1.0.0",
|
||||||
|
"com.unity.modules.physics": "1.0.0",
|
||||||
|
"com.unity.modules.physics2d": "1.0.0",
|
||||||
|
"com.unity.modules.screencapture": "1.0.0",
|
||||||
|
"com.unity.modules.terrain": "1.0.0",
|
||||||
|
"com.unity.modules.terrainphysics": "1.0.0",
|
||||||
|
"com.unity.modules.tilemap": "1.0.0",
|
||||||
|
"com.unity.modules.ui": "1.0.0",
|
||||||
|
"com.unity.modules.uielements": "1.0.0",
|
||||||
|
"com.unity.modules.umbra": "1.0.0",
|
||||||
|
"com.unity.modules.unityanalytics": "1.0.0",
|
||||||
|
"com.unity.modules.unitywebrequest": "1.0.0",
|
||||||
|
"com.unity.modules.unitywebrequestassetbundle": "1.0.0",
|
||||||
|
"com.unity.modules.unitywebrequestaudio": "1.0.0",
|
||||||
|
"com.unity.modules.unitywebrequesttexture": "1.0.0",
|
||||||
|
"com.unity.modules.unitywebrequestwww": "1.0.0",
|
||||||
|
"com.unity.modules.vehicles": "1.0.0",
|
||||||
|
"com.unity.modules.video": "1.0.0",
|
||||||
|
"com.unity.modules.vr": "1.0.0",
|
||||||
|
"com.unity.modules.wind": "1.0.0",
|
||||||
|
"com.unity.modules.xr": "1.0.0"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,360 @@
|
||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"com.cysharp.runtimeunittesttoolkit": {
|
||||||
|
"version": "https://github.com/Cysharp/RuntimeUnitTestToolkit.git?path=RuntimeUnitTestToolkit/Assets/RuntimeUnitTestToolkit#2.6.0",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "git",
|
||||||
|
"dependencies": {},
|
||||||
|
"hash": "4e3dbfaa9c40b5cfdcb71a1d4e8bca0d45ca1055"
|
||||||
|
},
|
||||||
|
"com.unity.collab-proxy": {
|
||||||
|
"version": "2.4.3",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "registry",
|
||||||
|
"dependencies": {},
|
||||||
|
"url": "https://packages.unity.com"
|
||||||
|
},
|
||||||
|
"com.unity.ext.nunit": {
|
||||||
|
"version": "1.0.6",
|
||||||
|
"depth": 1,
|
||||||
|
"source": "registry",
|
||||||
|
"dependencies": {},
|
||||||
|
"url": "https://packages.unity.com"
|
||||||
|
},
|
||||||
|
"com.unity.ide.rider": {
|
||||||
|
"version": "3.0.31",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "registry",
|
||||||
|
"dependencies": {
|
||||||
|
"com.unity.ext.nunit": "1.0.6"
|
||||||
|
},
|
||||||
|
"url": "https://packages.unity.com"
|
||||||
|
},
|
||||||
|
"com.unity.ide.visualstudio": {
|
||||||
|
"version": "2.0.22",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "registry",
|
||||||
|
"dependencies": {
|
||||||
|
"com.unity.test-framework": "1.1.9"
|
||||||
|
},
|
||||||
|
"url": "https://packages.unity.com"
|
||||||
|
},
|
||||||
|
"com.unity.ide.vscode": {
|
||||||
|
"version": "1.2.5",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "registry",
|
||||||
|
"dependencies": {},
|
||||||
|
"url": "https://packages.unity.com"
|
||||||
|
},
|
||||||
|
"com.unity.sysroot": {
|
||||||
|
"version": "2.0.10",
|
||||||
|
"depth": 1,
|
||||||
|
"source": "registry",
|
||||||
|
"dependencies": {},
|
||||||
|
"url": "https://packages.unity.com"
|
||||||
|
},
|
||||||
|
"com.unity.sysroot.linux-x86_64": {
|
||||||
|
"version": "2.0.9",
|
||||||
|
"depth": 1,
|
||||||
|
"source": "registry",
|
||||||
|
"dependencies": {
|
||||||
|
"com.unity.sysroot": "2.0.10"
|
||||||
|
},
|
||||||
|
"url": "https://packages.unity.com"
|
||||||
|
},
|
||||||
|
"com.unity.test-framework": {
|
||||||
|
"version": "1.1.33",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "registry",
|
||||||
|
"dependencies": {
|
||||||
|
"com.unity.ext.nunit": "1.0.6",
|
||||||
|
"com.unity.modules.imgui": "1.0.0",
|
||||||
|
"com.unity.modules.jsonserialize": "1.0.0"
|
||||||
|
},
|
||||||
|
"url": "https://packages.unity.com"
|
||||||
|
},
|
||||||
|
"com.unity.textmeshpro": {
|
||||||
|
"version": "3.0.6",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "registry",
|
||||||
|
"dependencies": {
|
||||||
|
"com.unity.ugui": "1.0.0"
|
||||||
|
},
|
||||||
|
"url": "https://packages.unity.com"
|
||||||
|
},
|
||||||
|
"com.unity.timeline": {
|
||||||
|
"version": "1.7.6",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "registry",
|
||||||
|
"dependencies": {
|
||||||
|
"com.unity.modules.director": "1.0.0",
|
||||||
|
"com.unity.modules.animation": "1.0.0",
|
||||||
|
"com.unity.modules.audio": "1.0.0",
|
||||||
|
"com.unity.modules.particlesystem": "1.0.0"
|
||||||
|
},
|
||||||
|
"url": "https://packages.unity.com"
|
||||||
|
},
|
||||||
|
"com.unity.toolchain.win-x86_64-linux-x86_64": {
|
||||||
|
"version": "2.0.9",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "registry",
|
||||||
|
"dependencies": {
|
||||||
|
"com.unity.sysroot": "2.0.10",
|
||||||
|
"com.unity.sysroot.linux-x86_64": "2.0.9"
|
||||||
|
},
|
||||||
|
"url": "https://packages.unity.com"
|
||||||
|
},
|
||||||
|
"com.unity.ugui": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "builtin",
|
||||||
|
"dependencies": {
|
||||||
|
"com.unity.modules.ui": "1.0.0",
|
||||||
|
"com.unity.modules.imgui": "1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"com.unity.modules.ai": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "builtin",
|
||||||
|
"dependencies": {}
|
||||||
|
},
|
||||||
|
"com.unity.modules.androidjni": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "builtin",
|
||||||
|
"dependencies": {}
|
||||||
|
},
|
||||||
|
"com.unity.modules.animation": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "builtin",
|
||||||
|
"dependencies": {}
|
||||||
|
},
|
||||||
|
"com.unity.modules.assetbundle": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "builtin",
|
||||||
|
"dependencies": {}
|
||||||
|
},
|
||||||
|
"com.unity.modules.audio": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "builtin",
|
||||||
|
"dependencies": {}
|
||||||
|
},
|
||||||
|
"com.unity.modules.cloth": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "builtin",
|
||||||
|
"dependencies": {
|
||||||
|
"com.unity.modules.physics": "1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"com.unity.modules.director": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "builtin",
|
||||||
|
"dependencies": {
|
||||||
|
"com.unity.modules.audio": "1.0.0",
|
||||||
|
"com.unity.modules.animation": "1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"com.unity.modules.imageconversion": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "builtin",
|
||||||
|
"dependencies": {}
|
||||||
|
},
|
||||||
|
"com.unity.modules.imgui": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "builtin",
|
||||||
|
"dependencies": {}
|
||||||
|
},
|
||||||
|
"com.unity.modules.jsonserialize": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "builtin",
|
||||||
|
"dependencies": {}
|
||||||
|
},
|
||||||
|
"com.unity.modules.particlesystem": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "builtin",
|
||||||
|
"dependencies": {}
|
||||||
|
},
|
||||||
|
"com.unity.modules.physics": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "builtin",
|
||||||
|
"dependencies": {}
|
||||||
|
},
|
||||||
|
"com.unity.modules.physics2d": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "builtin",
|
||||||
|
"dependencies": {}
|
||||||
|
},
|
||||||
|
"com.unity.modules.screencapture": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "builtin",
|
||||||
|
"dependencies": {
|
||||||
|
"com.unity.modules.imageconversion": "1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"com.unity.modules.subsystems": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"depth": 1,
|
||||||
|
"source": "builtin",
|
||||||
|
"dependencies": {
|
||||||
|
"com.unity.modules.jsonserialize": "1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"com.unity.modules.terrain": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "builtin",
|
||||||
|
"dependencies": {}
|
||||||
|
},
|
||||||
|
"com.unity.modules.terrainphysics": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "builtin",
|
||||||
|
"dependencies": {
|
||||||
|
"com.unity.modules.physics": "1.0.0",
|
||||||
|
"com.unity.modules.terrain": "1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"com.unity.modules.tilemap": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "builtin",
|
||||||
|
"dependencies": {
|
||||||
|
"com.unity.modules.physics2d": "1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"com.unity.modules.ui": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "builtin",
|
||||||
|
"dependencies": {}
|
||||||
|
},
|
||||||
|
"com.unity.modules.uielements": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "builtin",
|
||||||
|
"dependencies": {
|
||||||
|
"com.unity.modules.ui": "1.0.0",
|
||||||
|
"com.unity.modules.imgui": "1.0.0",
|
||||||
|
"com.unity.modules.jsonserialize": "1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"com.unity.modules.umbra": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "builtin",
|
||||||
|
"dependencies": {}
|
||||||
|
},
|
||||||
|
"com.unity.modules.unityanalytics": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "builtin",
|
||||||
|
"dependencies": {
|
||||||
|
"com.unity.modules.unitywebrequest": "1.0.0",
|
||||||
|
"com.unity.modules.jsonserialize": "1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"com.unity.modules.unitywebrequest": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "builtin",
|
||||||
|
"dependencies": {}
|
||||||
|
},
|
||||||
|
"com.unity.modules.unitywebrequestassetbundle": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "builtin",
|
||||||
|
"dependencies": {
|
||||||
|
"com.unity.modules.assetbundle": "1.0.0",
|
||||||
|
"com.unity.modules.unitywebrequest": "1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"com.unity.modules.unitywebrequestaudio": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "builtin",
|
||||||
|
"dependencies": {
|
||||||
|
"com.unity.modules.unitywebrequest": "1.0.0",
|
||||||
|
"com.unity.modules.audio": "1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"com.unity.modules.unitywebrequesttexture": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "builtin",
|
||||||
|
"dependencies": {
|
||||||
|
"com.unity.modules.unitywebrequest": "1.0.0",
|
||||||
|
"com.unity.modules.imageconversion": "1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"com.unity.modules.unitywebrequestwww": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "builtin",
|
||||||
|
"dependencies": {
|
||||||
|
"com.unity.modules.unitywebrequest": "1.0.0",
|
||||||
|
"com.unity.modules.unitywebrequestassetbundle": "1.0.0",
|
||||||
|
"com.unity.modules.unitywebrequestaudio": "1.0.0",
|
||||||
|
"com.unity.modules.audio": "1.0.0",
|
||||||
|
"com.unity.modules.assetbundle": "1.0.0",
|
||||||
|
"com.unity.modules.imageconversion": "1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"com.unity.modules.vehicles": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "builtin",
|
||||||
|
"dependencies": {
|
||||||
|
"com.unity.modules.physics": "1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"com.unity.modules.video": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "builtin",
|
||||||
|
"dependencies": {
|
||||||
|
"com.unity.modules.audio": "1.0.0",
|
||||||
|
"com.unity.modules.ui": "1.0.0",
|
||||||
|
"com.unity.modules.unitywebrequest": "1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"com.unity.modules.vr": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "builtin",
|
||||||
|
"dependencies": {
|
||||||
|
"com.unity.modules.jsonserialize": "1.0.0",
|
||||||
|
"com.unity.modules.physics": "1.0.0",
|
||||||
|
"com.unity.modules.xr": "1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"com.unity.modules.wind": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "builtin",
|
||||||
|
"dependencies": {}
|
||||||
|
},
|
||||||
|
"com.unity.modules.xr": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"depth": 0,
|
||||||
|
"source": "builtin",
|
||||||
|
"dependencies": {
|
||||||
|
"com.unity.modules.physics": "1.0.0",
|
||||||
|
"com.unity.modules.jsonserialize": "1.0.0",
|
||||||
|
"com.unity.modules.subsystems": "1.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!387306366 &1
|
||||||
|
MemorySettings:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_EditorMemorySettings:
|
||||||
|
m_MainAllocatorBlockSize: -1
|
||||||
|
m_ThreadAllocatorBlockSize: -1
|
||||||
|
m_MainGfxBlockSize: -1
|
||||||
|
m_ThreadGfxBlockSize: -1
|
||||||
|
m_CacheBlockSize: -1
|
||||||
|
m_TypetreeBlockSize: -1
|
||||||
|
m_ProfilerBlockSize: -1
|
||||||
|
m_ProfilerEditorBlockSize: -1
|
||||||
|
m_BucketAllocatorGranularity: -1
|
||||||
|
m_BucketAllocatorBucketsCount: -1
|
||||||
|
m_BucketAllocatorBlockSize: -1
|
||||||
|
m_BucketAllocatorBlockCount: -1
|
||||||
|
m_ProfilerBucketAllocatorGranularity: -1
|
||||||
|
m_ProfilerBucketAllocatorBucketsCount: -1
|
||||||
|
m_ProfilerBucketAllocatorBlockSize: -1
|
||||||
|
m_ProfilerBucketAllocatorBlockCount: -1
|
||||||
|
m_TempAllocatorSizeMain: -1
|
||||||
|
m_JobTempAllocatorBlockSize: -1
|
||||||
|
m_BackgroundJobTempAllocatorBlockSize: -1
|
||||||
|
m_JobTempAllocatorReducedBlockSize: -1
|
||||||
|
m_TempAllocatorSizeGIBakingWorker: -1
|
||||||
|
m_TempAllocatorSizeNavMeshWorker: -1
|
||||||
|
m_TempAllocatorSizeAudioWorker: -1
|
||||||
|
m_TempAllocatorSizeCloudWorker: -1
|
||||||
|
m_TempAllocatorSizeGfx: -1
|
||||||
|
m_TempAllocatorSizeJobWorker: -1
|
||||||
|
m_TempAllocatorSizeBackgroundWorker: -1
|
||||||
|
m_TempAllocatorSizePreloadManager: -1
|
||||||
|
m_PlatformMemorySettings: {}
|
|
@ -3,7 +3,7 @@
|
||||||
--- !u!129 &1
|
--- !u!129 &1
|
||||||
PlayerSettings:
|
PlayerSettings:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
serializedVersion: 20
|
serializedVersion: 26
|
||||||
productGUID: 904cd7a3163037f42a9204c0e2f2b7bd
|
productGUID: 904cd7a3163037f42a9204c0e2f2b7bd
|
||||||
AndroidProfiler: 0
|
AndroidProfiler: 0
|
||||||
AndroidFilterTouchesWhenObscured: 0
|
AndroidFilterTouchesWhenObscured: 0
|
||||||
|
@ -48,12 +48,16 @@ PlayerSettings:
|
||||||
defaultScreenHeightWeb: 600
|
defaultScreenHeightWeb: 600
|
||||||
m_StereoRenderingPath: 0
|
m_StereoRenderingPath: 0
|
||||||
m_ActiveColorSpace: 0
|
m_ActiveColorSpace: 0
|
||||||
|
unsupportedMSAAFallback: 0
|
||||||
|
m_SpriteBatchVertexThreshold: 300
|
||||||
m_MTRendering: 1
|
m_MTRendering: 1
|
||||||
|
mipStripping: 0
|
||||||
|
numberOfMipsStripped: 0
|
||||||
|
numberOfMipsStrippedPerMipmapLimitGroup: {}
|
||||||
m_StackTraceTypes: 010000000100000001000000010000000100000001000000
|
m_StackTraceTypes: 010000000100000001000000010000000100000001000000
|
||||||
iosShowActivityIndicatorOnLoading: -1
|
iosShowActivityIndicatorOnLoading: -1
|
||||||
androidShowActivityIndicatorOnLoading: -1
|
androidShowActivityIndicatorOnLoading: -1
|
||||||
iosUseCustomAppBackgroundBehavior: 0
|
iosUseCustomAppBackgroundBehavior: 0
|
||||||
iosAllowHTTPDownload: 1
|
|
||||||
allowedAutorotateToPortrait: 1
|
allowedAutorotateToPortrait: 1
|
||||||
allowedAutorotateToPortraitUpsideDown: 1
|
allowedAutorotateToPortraitUpsideDown: 1
|
||||||
allowedAutorotateToLandscapeRight: 1
|
allowedAutorotateToLandscapeRight: 1
|
||||||
|
@ -66,6 +70,13 @@ PlayerSettings:
|
||||||
androidRenderOutsideSafeArea: 1
|
androidRenderOutsideSafeArea: 1
|
||||||
androidUseSwappy: 0
|
androidUseSwappy: 0
|
||||||
androidBlitType: 0
|
androidBlitType: 0
|
||||||
|
androidResizableWindow: 0
|
||||||
|
androidDefaultWindowWidth: 1920
|
||||||
|
androidDefaultWindowHeight: 1080
|
||||||
|
androidMinimumWindowWidth: 400
|
||||||
|
androidMinimumWindowHeight: 300
|
||||||
|
androidFullscreenMode: 1
|
||||||
|
androidAutoRotationBehavior: 1
|
||||||
defaultIsNativeResolution: 1
|
defaultIsNativeResolution: 1
|
||||||
macRetinaSupport: 1
|
macRetinaSupport: 1
|
||||||
runInBackground: 1
|
runInBackground: 1
|
||||||
|
@ -77,6 +88,7 @@ PlayerSettings:
|
||||||
hideHomeButton: 0
|
hideHomeButton: 0
|
||||||
submitAnalytics: 1
|
submitAnalytics: 1
|
||||||
usePlayerLog: 1
|
usePlayerLog: 1
|
||||||
|
dedicatedServerOptimizations: 0
|
||||||
bakeCollisionMeshes: 0
|
bakeCollisionMeshes: 0
|
||||||
forceSingleInstance: 0
|
forceSingleInstance: 0
|
||||||
useFlipModelSwapchain: 1
|
useFlipModelSwapchain: 1
|
||||||
|
@ -111,16 +123,22 @@ PlayerSettings:
|
||||||
switchNVNShaderPoolsGranularity: 33554432
|
switchNVNShaderPoolsGranularity: 33554432
|
||||||
switchNVNDefaultPoolsGranularity: 16777216
|
switchNVNDefaultPoolsGranularity: 16777216
|
||||||
switchNVNOtherPoolsGranularity: 16777216
|
switchNVNOtherPoolsGranularity: 16777216
|
||||||
|
switchGpuScratchPoolGranularity: 2097152
|
||||||
|
switchAllowGpuScratchShrinking: 0
|
||||||
|
switchNVNMaxPublicTextureIDCount: 0
|
||||||
|
switchNVNMaxPublicSamplerIDCount: 0
|
||||||
|
switchNVNGraphicsFirmwareMemory: 32
|
||||||
|
switchMaxWorkerMultiple: 8
|
||||||
stadiaPresentMode: 0
|
stadiaPresentMode: 0
|
||||||
stadiaTargetFramerate: 0
|
stadiaTargetFramerate: 0
|
||||||
vulkanNumSwapchainBuffers: 3
|
vulkanNumSwapchainBuffers: 3
|
||||||
vulkanEnableSetSRGBWrite: 0
|
vulkanEnableSetSRGBWrite: 0
|
||||||
m_SupportedAspectRatios:
|
vulkanEnablePreTransform: 0
|
||||||
4:3: 1
|
vulkanEnableLateAcquireNextImage: 0
|
||||||
5:4: 1
|
vulkanEnableCommandBufferRecycling: 1
|
||||||
16:10: 1
|
loadStoreDebugModeEnabled: 0
|
||||||
16:9: 1
|
visionOSBundleVersion: 1.0
|
||||||
Others: 1
|
tvOSBundleVersion: 1.0
|
||||||
bundleVersion: 0.1
|
bundleVersion: 0.1
|
||||||
preloadedAssets: []
|
preloadedAssets: []
|
||||||
metroInputSource: 0
|
metroInputSource: 0
|
||||||
|
@ -129,46 +147,29 @@ PlayerSettings:
|
||||||
xboxOneDisableKinectGpuReservation: 1
|
xboxOneDisableKinectGpuReservation: 1
|
||||||
xboxOneEnable7thCore: 1
|
xboxOneEnable7thCore: 1
|
||||||
vrSettings:
|
vrSettings:
|
||||||
cardboard:
|
|
||||||
depthFormat: 0
|
|
||||||
enableTransitionView: 0
|
|
||||||
daydream:
|
|
||||||
depthFormat: 0
|
|
||||||
useSustainedPerformanceMode: 0
|
|
||||||
enableVideoLayer: 0
|
|
||||||
useProtectedVideoMemory: 0
|
|
||||||
minimumSupportedHeadTracking: 0
|
|
||||||
maximumSupportedHeadTracking: 1
|
|
||||||
hololens:
|
|
||||||
depthFormat: 1
|
|
||||||
depthBufferSharingEnabled: 1
|
|
||||||
lumin:
|
|
||||||
depthFormat: 0
|
|
||||||
frameTiming: 2
|
|
||||||
enableGLCache: 0
|
|
||||||
glCacheMaxBlobSize: 524288
|
|
||||||
glCacheMaxFileSize: 8388608
|
|
||||||
oculus:
|
|
||||||
sharedDepthBuffer: 1
|
|
||||||
dashSupport: 1
|
|
||||||
lowOverheadMode: 0
|
|
||||||
protectedContext: 0
|
|
||||||
v2Signing: 1
|
|
||||||
enable360StereoCapture: 0
|
enable360StereoCapture: 0
|
||||||
isWsaHolographicRemotingEnabled: 0
|
isWsaHolographicRemotingEnabled: 0
|
||||||
enableFrameTimingStats: 0
|
enableFrameTimingStats: 0
|
||||||
|
enableOpenGLProfilerGPURecorders: 1
|
||||||
|
allowHDRDisplaySupport: 0
|
||||||
useHDRDisplay: 0
|
useHDRDisplay: 0
|
||||||
D3DHDRBitDepth: 0
|
hdrBitDepth: 0
|
||||||
m_ColorGamuts: 00000000
|
m_ColorGamuts: 00000000
|
||||||
targetPixelDensity: 30
|
targetPixelDensity: 30
|
||||||
resolutionScalingMode: 0
|
resolutionScalingMode: 0
|
||||||
|
resetResolutionOnWindowResize: 0
|
||||||
androidSupportedAspectRatio: 1
|
androidSupportedAspectRatio: 1
|
||||||
androidMaxAspectRatio: 2.1
|
androidMaxAspectRatio: 2.1
|
||||||
applicationIdentifier:
|
applicationIdentifier:
|
||||||
Standalone: com.Company.ProductName
|
Standalone: com.DefaultCompany.UniTask
|
||||||
buildNumber: {}
|
buildNumber:
|
||||||
|
Standalone: 0
|
||||||
|
VisionOS: 0
|
||||||
|
iPhone: 0
|
||||||
|
tvOS: 0
|
||||||
|
overrideDefaultApplicationIdentifier: 0
|
||||||
AndroidBundleVersionCode: 1
|
AndroidBundleVersionCode: 1
|
||||||
AndroidMinSdkVersion: 19
|
AndroidMinSdkVersion: 22
|
||||||
AndroidTargetSdkVersion: 0
|
AndroidTargetSdkVersion: 0
|
||||||
AndroidPreferredInstallLocation: 1
|
AndroidPreferredInstallLocation: 1
|
||||||
aotOptions:
|
aotOptions:
|
||||||
|
@ -181,12 +182,15 @@ PlayerSettings:
|
||||||
APKExpansionFiles: 0
|
APKExpansionFiles: 0
|
||||||
keepLoadedShadersAlive: 0
|
keepLoadedShadersAlive: 0
|
||||||
StripUnusedMeshComponents: 1
|
StripUnusedMeshComponents: 1
|
||||||
|
strictShaderVariantMatching: 0
|
||||||
VertexChannelCompressionMask: 4054
|
VertexChannelCompressionMask: 4054
|
||||||
iPhoneSdkVersion: 988
|
iPhoneSdkVersion: 988
|
||||||
iOSTargetOSVersionString: 10.0
|
iOSTargetOSVersionString: 12.0
|
||||||
tvOSSdkVersion: 0
|
tvOSSdkVersion: 0
|
||||||
tvOSRequireExtendedGameController: 0
|
tvOSRequireExtendedGameController: 0
|
||||||
tvOSTargetOSVersionString: 10.0
|
tvOSTargetOSVersionString: 12.0
|
||||||
|
VisionOSSdkVersion: 0
|
||||||
|
VisionOSTargetOSVersionString: 1.0
|
||||||
uIPrerenderedIcon: 0
|
uIPrerenderedIcon: 0
|
||||||
uIRequiresPersistentWiFi: 0
|
uIRequiresPersistentWiFi: 0
|
||||||
uIRequiresFullScreen: 1
|
uIRequiresFullScreen: 1
|
||||||
|
@ -220,32 +224,48 @@ PlayerSettings:
|
||||||
iOSLaunchScreeniPadFillPct: 100
|
iOSLaunchScreeniPadFillPct: 100
|
||||||
iOSLaunchScreeniPadSize: 100
|
iOSLaunchScreeniPadSize: 100
|
||||||
iOSLaunchScreeniPadCustomXibPath:
|
iOSLaunchScreeniPadCustomXibPath:
|
||||||
iOSUseLaunchScreenStoryboard: 0
|
|
||||||
iOSLaunchScreenCustomStoryboardPath:
|
iOSLaunchScreenCustomStoryboardPath:
|
||||||
|
iOSLaunchScreeniPadCustomStoryboardPath:
|
||||||
iOSDeviceRequirements: []
|
iOSDeviceRequirements: []
|
||||||
iOSURLSchemes: []
|
iOSURLSchemes: []
|
||||||
|
macOSURLSchemes: []
|
||||||
iOSBackgroundModes: 0
|
iOSBackgroundModes: 0
|
||||||
iOSMetalForceHardShadows: 0
|
iOSMetalForceHardShadows: 0
|
||||||
metalEditorSupport: 1
|
metalEditorSupport: 1
|
||||||
metalAPIValidation: 1
|
metalAPIValidation: 1
|
||||||
|
metalCompileShaderBinary: 0
|
||||||
iOSRenderExtraFrameOnPause: 0
|
iOSRenderExtraFrameOnPause: 0
|
||||||
|
iosCopyPluginsCodeInsteadOfSymlink: 0
|
||||||
appleDeveloperTeamID:
|
appleDeveloperTeamID:
|
||||||
iOSManualSigningProvisioningProfileID:
|
iOSManualSigningProvisioningProfileID:
|
||||||
tvOSManualSigningProvisioningProfileID:
|
tvOSManualSigningProvisioningProfileID:
|
||||||
|
VisionOSManualSigningProvisioningProfileID:
|
||||||
iOSManualSigningProvisioningProfileType: 0
|
iOSManualSigningProvisioningProfileType: 0
|
||||||
tvOSManualSigningProvisioningProfileType: 0
|
tvOSManualSigningProvisioningProfileType: 0
|
||||||
|
VisionOSManualSigningProvisioningProfileType: 0
|
||||||
appleEnableAutomaticSigning: 0
|
appleEnableAutomaticSigning: 0
|
||||||
iOSRequireARKit: 0
|
iOSRequireARKit: 0
|
||||||
iOSAutomaticallyDetectAndAddCapabilities: 1
|
iOSAutomaticallyDetectAndAddCapabilities: 1
|
||||||
appleEnableProMotion: 0
|
appleEnableProMotion: 0
|
||||||
|
shaderPrecisionModel: 0
|
||||||
clonedFromGUID: 5f34be1353de5cf4398729fda238591b
|
clonedFromGUID: 5f34be1353de5cf4398729fda238591b
|
||||||
templatePackageId: com.unity.template.2d@3.1.0
|
templatePackageId: com.unity.template.2d@3.1.0
|
||||||
templateDefaultScene: Assets/Scenes/SampleScene.unity
|
templateDefaultScene: Assets/Scenes/SampleScene.unity
|
||||||
|
useCustomMainManifest: 0
|
||||||
|
useCustomLauncherManifest: 0
|
||||||
|
useCustomMainGradleTemplate: 0
|
||||||
|
useCustomLauncherGradleManifest: 0
|
||||||
|
useCustomBaseGradleTemplate: 0
|
||||||
|
useCustomGradlePropertiesTemplate: 0
|
||||||
|
useCustomGradleSettingsTemplate: 0
|
||||||
|
useCustomProguardFile: 0
|
||||||
AndroidTargetArchitectures: 1
|
AndroidTargetArchitectures: 1
|
||||||
|
AndroidTargetDevices: 0
|
||||||
AndroidSplashScreenScale: 0
|
AndroidSplashScreenScale: 0
|
||||||
androidSplashScreen: {fileID: 0}
|
androidSplashScreen: {fileID: 0}
|
||||||
AndroidKeystoreName: '{inproject}: '
|
AndroidKeystoreName: '{inproject}: '
|
||||||
AndroidKeyaliasName:
|
AndroidKeyaliasName:
|
||||||
|
AndroidEnableArmv9SecurityFeatures: 0
|
||||||
AndroidBuildApkPerCpuArchitecture: 0
|
AndroidBuildApkPerCpuArchitecture: 0
|
||||||
AndroidTVCompatibility: 0
|
AndroidTVCompatibility: 0
|
||||||
AndroidIsGame: 1
|
AndroidIsGame: 1
|
||||||
|
@ -258,11 +278,15 @@ PlayerSettings:
|
||||||
height: 180
|
height: 180
|
||||||
banner: {fileID: 0}
|
banner: {fileID: 0}
|
||||||
androidGamepadSupportLevel: 0
|
androidGamepadSupportLevel: 0
|
||||||
|
chromeosInputEmulation: 1
|
||||||
|
AndroidMinifyRelease: 0
|
||||||
|
AndroidMinifyDebug: 0
|
||||||
AndroidValidateAppBundleSize: 1
|
AndroidValidateAppBundleSize: 1
|
||||||
AndroidAppBundleSizeToValidate: 100
|
AndroidAppBundleSizeToValidate: 100
|
||||||
m_BuildTargetIcons: []
|
m_BuildTargetIcons: []
|
||||||
m_BuildTargetPlatformIcons: []
|
m_BuildTargetPlatformIcons: []
|
||||||
m_BuildTargetBatching: []
|
m_BuildTargetBatching: []
|
||||||
|
m_BuildTargetShaderSettings: []
|
||||||
m_BuildTargetGraphicsJobs:
|
m_BuildTargetGraphicsJobs:
|
||||||
- m_BuildTarget: MacStandaloneSupport
|
- m_BuildTarget: MacStandaloneSupport
|
||||||
m_GraphicsJobs: 0
|
m_GraphicsJobs: 0
|
||||||
|
@ -298,8 +322,13 @@ PlayerSettings:
|
||||||
m_BuildTargetGraphicsAPIs:
|
m_BuildTargetGraphicsAPIs:
|
||||||
- m_BuildTarget: AndroidPlayer
|
- m_BuildTarget: AndroidPlayer
|
||||||
m_APIs: 150000000b000000
|
m_APIs: 150000000b000000
|
||||||
m_Automatic: 0
|
m_Automatic: 1
|
||||||
|
- m_BuildTarget: iOSSupport
|
||||||
|
m_APIs: 10000000
|
||||||
|
m_Automatic: 1
|
||||||
m_BuildTargetVRSettings: []
|
m_BuildTargetVRSettings: []
|
||||||
|
m_DefaultShaderChunkSizeInMB: 16
|
||||||
|
m_DefaultShaderChunkCount: 0
|
||||||
openGLRequireES31: 0
|
openGLRequireES31: 0
|
||||||
openGLRequireES31AEP: 0
|
openGLRequireES31AEP: 0
|
||||||
openGLRequireES32: 0
|
openGLRequireES32: 0
|
||||||
|
@ -309,7 +338,11 @@ PlayerSettings:
|
||||||
iPhone: 1
|
iPhone: 1
|
||||||
tvOS: 1
|
tvOS: 1
|
||||||
m_BuildTargetGroupLightmapEncodingQuality: []
|
m_BuildTargetGroupLightmapEncodingQuality: []
|
||||||
|
m_BuildTargetGroupHDRCubemapEncodingQuality: []
|
||||||
m_BuildTargetGroupLightmapSettings: []
|
m_BuildTargetGroupLightmapSettings: []
|
||||||
|
m_BuildTargetGroupLoadStoreDebugModeSettings: []
|
||||||
|
m_BuildTargetNormalMapEncoding: []
|
||||||
|
m_BuildTargetDefaultTextureCompressionFormat: []
|
||||||
playModeTestRunnerEnabled: 0
|
playModeTestRunnerEnabled: 0
|
||||||
runPlayModeTestAsEditModeTest: 0
|
runPlayModeTestAsEditModeTest: 0
|
||||||
actionOnDotNetUnhandledException: 1
|
actionOnDotNetUnhandledException: 1
|
||||||
|
@ -319,14 +352,20 @@ PlayerSettings:
|
||||||
cameraUsageDescription:
|
cameraUsageDescription:
|
||||||
locationUsageDescription:
|
locationUsageDescription:
|
||||||
microphoneUsageDescription:
|
microphoneUsageDescription:
|
||||||
|
bluetoothUsageDescription:
|
||||||
|
macOSTargetOSVersion: 10.13.0
|
||||||
|
switchNMETAOverride:
|
||||||
switchNetLibKey:
|
switchNetLibKey:
|
||||||
switchSocketMemoryPoolSize: 6144
|
switchSocketMemoryPoolSize: 6144
|
||||||
switchSocketAllocatorPoolSize: 128
|
switchSocketAllocatorPoolSize: 128
|
||||||
switchSocketConcurrencyLimit: 14
|
switchSocketConcurrencyLimit: 14
|
||||||
switchScreenResolutionBehavior: 2
|
switchScreenResolutionBehavior: 2
|
||||||
switchUseCPUProfiler: 0
|
switchUseCPUProfiler: 0
|
||||||
|
switchEnableFileSystemTrace: 0
|
||||||
|
switchLTOSetting: 0
|
||||||
switchApplicationID: 0x01004b9000490000
|
switchApplicationID: 0x01004b9000490000
|
||||||
switchNSODependencies:
|
switchNSODependencies:
|
||||||
|
switchCompilerFlags:
|
||||||
switchTitleNames_0:
|
switchTitleNames_0:
|
||||||
switchTitleNames_1:
|
switchTitleNames_1:
|
||||||
switchTitleNames_2:
|
switchTitleNames_2:
|
||||||
|
@ -342,6 +381,7 @@ PlayerSettings:
|
||||||
switchTitleNames_12:
|
switchTitleNames_12:
|
||||||
switchTitleNames_13:
|
switchTitleNames_13:
|
||||||
switchTitleNames_14:
|
switchTitleNames_14:
|
||||||
|
switchTitleNames_15:
|
||||||
switchPublisherNames_0:
|
switchPublisherNames_0:
|
||||||
switchPublisherNames_1:
|
switchPublisherNames_1:
|
||||||
switchPublisherNames_2:
|
switchPublisherNames_2:
|
||||||
|
@ -357,6 +397,7 @@ PlayerSettings:
|
||||||
switchPublisherNames_12:
|
switchPublisherNames_12:
|
||||||
switchPublisherNames_13:
|
switchPublisherNames_13:
|
||||||
switchPublisherNames_14:
|
switchPublisherNames_14:
|
||||||
|
switchPublisherNames_15:
|
||||||
switchIcons_0: {fileID: 0}
|
switchIcons_0: {fileID: 0}
|
||||||
switchIcons_1: {fileID: 0}
|
switchIcons_1: {fileID: 0}
|
||||||
switchIcons_2: {fileID: 0}
|
switchIcons_2: {fileID: 0}
|
||||||
|
@ -372,6 +413,7 @@ PlayerSettings:
|
||||||
switchIcons_12: {fileID: 0}
|
switchIcons_12: {fileID: 0}
|
||||||
switchIcons_13: {fileID: 0}
|
switchIcons_13: {fileID: 0}
|
||||||
switchIcons_14: {fileID: 0}
|
switchIcons_14: {fileID: 0}
|
||||||
|
switchIcons_15: {fileID: 0}
|
||||||
switchSmallIcons_0: {fileID: 0}
|
switchSmallIcons_0: {fileID: 0}
|
||||||
switchSmallIcons_1: {fileID: 0}
|
switchSmallIcons_1: {fileID: 0}
|
||||||
switchSmallIcons_2: {fileID: 0}
|
switchSmallIcons_2: {fileID: 0}
|
||||||
|
@ -387,6 +429,7 @@ PlayerSettings:
|
||||||
switchSmallIcons_12: {fileID: 0}
|
switchSmallIcons_12: {fileID: 0}
|
||||||
switchSmallIcons_13: {fileID: 0}
|
switchSmallIcons_13: {fileID: 0}
|
||||||
switchSmallIcons_14: {fileID: 0}
|
switchSmallIcons_14: {fileID: 0}
|
||||||
|
switchSmallIcons_15: {fileID: 0}
|
||||||
switchManualHTML:
|
switchManualHTML:
|
||||||
switchAccessibleURLs:
|
switchAccessibleURLs:
|
||||||
switchLegalInformation:
|
switchLegalInformation:
|
||||||
|
@ -396,7 +439,6 @@ PlayerSettings:
|
||||||
switchReleaseVersion: 0
|
switchReleaseVersion: 0
|
||||||
switchDisplayVersion: 1.0.0
|
switchDisplayVersion: 1.0.0
|
||||||
switchStartupUserAccount: 0
|
switchStartupUserAccount: 0
|
||||||
switchTouchScreenUsage: 0
|
|
||||||
switchSupportedLanguagesMask: 0
|
switchSupportedLanguagesMask: 0
|
||||||
switchLogoType: 0
|
switchLogoType: 0
|
||||||
switchApplicationErrorCodeCategory:
|
switchApplicationErrorCodeCategory:
|
||||||
|
@ -438,6 +480,7 @@ PlayerSettings:
|
||||||
switchNativeFsCacheSize: 32
|
switchNativeFsCacheSize: 32
|
||||||
switchIsHoldTypeHorizontal: 0
|
switchIsHoldTypeHorizontal: 0
|
||||||
switchSupportedNpadCount: 8
|
switchSupportedNpadCount: 8
|
||||||
|
switchEnableTouchScreen: 1
|
||||||
switchSocketConfigEnabled: 0
|
switchSocketConfigEnabled: 0
|
||||||
switchTcpInitialSendBufferSize: 32
|
switchTcpInitialSendBufferSize: 32
|
||||||
switchTcpInitialReceiveBufferSize: 64
|
switchTcpInitialReceiveBufferSize: 64
|
||||||
|
@ -448,7 +491,12 @@ PlayerSettings:
|
||||||
switchSocketBufferEfficiency: 4
|
switchSocketBufferEfficiency: 4
|
||||||
switchSocketInitializeEnabled: 1
|
switchSocketInitializeEnabled: 1
|
||||||
switchNetworkInterfaceManagerInitializeEnabled: 1
|
switchNetworkInterfaceManagerInitializeEnabled: 1
|
||||||
switchPlayerConnectionEnabled: 1
|
switchUseNewStyleFilepaths: 0
|
||||||
|
switchUseLegacyFmodPriorities: 0
|
||||||
|
switchUseMicroSleepForYield: 1
|
||||||
|
switchEnableRamDiskSupport: 0
|
||||||
|
switchMicroSleepForYieldTime: 25
|
||||||
|
switchRamDiskSpaceSize: 12
|
||||||
ps4NPAgeRating: 12
|
ps4NPAgeRating: 12
|
||||||
ps4NPTitleSecret:
|
ps4NPTitleSecret:
|
||||||
ps4NPTrophyPackPath:
|
ps4NPTrophyPackPath:
|
||||||
|
@ -475,6 +523,7 @@ PlayerSettings:
|
||||||
ps4ShareFilePath:
|
ps4ShareFilePath:
|
||||||
ps4ShareOverlayImagePath:
|
ps4ShareOverlayImagePath:
|
||||||
ps4PrivacyGuardImagePath:
|
ps4PrivacyGuardImagePath:
|
||||||
|
ps4ExtraSceSysFile:
|
||||||
ps4NPtitleDatPath:
|
ps4NPtitleDatPath:
|
||||||
ps4RemotePlayKeyAssignment: -1
|
ps4RemotePlayKeyAssignment: -1
|
||||||
ps4RemotePlayKeyMappingDir:
|
ps4RemotePlayKeyMappingDir:
|
||||||
|
@ -517,6 +566,9 @@ PlayerSettings:
|
||||||
ps4disableAutoHideSplash: 0
|
ps4disableAutoHideSplash: 0
|
||||||
ps4videoRecordingFeaturesUsed: 0
|
ps4videoRecordingFeaturesUsed: 0
|
||||||
ps4contentSearchFeaturesUsed: 0
|
ps4contentSearchFeaturesUsed: 0
|
||||||
|
ps4CompatibilityPS5: 0
|
||||||
|
ps4AllowPS5Detection: 0
|
||||||
|
ps4GPU800MHz: 1
|
||||||
ps4attribEyeToEyeDistanceSettingVR: 0
|
ps4attribEyeToEyeDistanceSettingVR: 0
|
||||||
ps4IncludedModules: []
|
ps4IncludedModules: []
|
||||||
ps4attribVROutputEnabled: 0
|
ps4attribVROutputEnabled: 0
|
||||||
|
@ -528,6 +580,7 @@ PlayerSettings:
|
||||||
webGLMemorySize: 16
|
webGLMemorySize: 16
|
||||||
webGLExceptionSupport: 1
|
webGLExceptionSupport: 1
|
||||||
webGLNameFilesAsHashes: 0
|
webGLNameFilesAsHashes: 0
|
||||||
|
webGLShowDiagnostics: 0
|
||||||
webGLDataCaching: 1
|
webGLDataCaching: 1
|
||||||
webGLDebugSymbols: 0
|
webGLDebugSymbols: 0
|
||||||
webGLEmscriptenArgs:
|
webGLEmscriptenArgs:
|
||||||
|
@ -536,18 +589,47 @@ PlayerSettings:
|
||||||
webGLAnalyzeBuildSize: 0
|
webGLAnalyzeBuildSize: 0
|
||||||
webGLUseEmbeddedResources: 0
|
webGLUseEmbeddedResources: 0
|
||||||
webGLCompressionFormat: 1
|
webGLCompressionFormat: 1
|
||||||
|
webGLWasmArithmeticExceptions: 0
|
||||||
webGLLinkerTarget: 1
|
webGLLinkerTarget: 1
|
||||||
webGLThreadsSupport: 0
|
webGLThreadsSupport: 0
|
||||||
webGLWasmStreaming: 0
|
webGLDecompressionFallback: 0
|
||||||
|
webGLInitialMemorySize: 32
|
||||||
|
webGLMaximumMemorySize: 2048
|
||||||
|
webGLMemoryGrowthMode: 2
|
||||||
|
webGLMemoryLinearGrowthStep: 16
|
||||||
|
webGLMemoryGeometricGrowthStep: 0.2
|
||||||
|
webGLMemoryGeometricGrowthCap: 96
|
||||||
|
webGLPowerPreference: 2
|
||||||
scriptingDefineSymbols: {}
|
scriptingDefineSymbols: {}
|
||||||
|
additionalCompilerArguments: {}
|
||||||
platformArchitecture: {}
|
platformArchitecture: {}
|
||||||
scriptingBackend:
|
scriptingBackend:
|
||||||
Android: 1
|
Android: 1
|
||||||
|
Server: 1
|
||||||
Standalone: 1
|
Standalone: 1
|
||||||
il2cppCompilerConfiguration: {}
|
il2cppCompilerConfiguration: {}
|
||||||
managedStrippingLevel: {}
|
il2cppCodeGeneration: {}
|
||||||
|
managedStrippingLevel:
|
||||||
|
Android: 1
|
||||||
|
EmbeddedLinux: 1
|
||||||
|
GameCoreScarlett: 1
|
||||||
|
GameCoreXboxOne: 1
|
||||||
|
Nintendo Switch: 1
|
||||||
|
PS4: 1
|
||||||
|
PS5: 1
|
||||||
|
QNX: 1
|
||||||
|
Stadia: 1
|
||||||
|
Standalone: 1
|
||||||
|
VisionOS: 1
|
||||||
|
WebGL: 1
|
||||||
|
Windows Store Apps: 1
|
||||||
|
XboxOne: 1
|
||||||
|
iPhone: 1
|
||||||
|
tvOS: 1
|
||||||
incrementalIl2cppBuild: {}
|
incrementalIl2cppBuild: {}
|
||||||
|
suppressCommonWarnings: 1
|
||||||
allowUnsafeCode: 0
|
allowUnsafeCode: 0
|
||||||
|
useDeterministicCompilation: 1
|
||||||
additionalIl2CppArgs:
|
additionalIl2CppArgs:
|
||||||
scriptingRuntimeVersion: 1
|
scriptingRuntimeVersion: 1
|
||||||
gcIncremental: 0
|
gcIncremental: 0
|
||||||
|
@ -578,11 +660,13 @@ PlayerSettings:
|
||||||
metroSplashScreenBackgroundColor: {r: 0.12941177, g: 0.17254902, b: 0.21568628,
|
metroSplashScreenBackgroundColor: {r: 0.12941177, g: 0.17254902, b: 0.21568628,
|
||||||
a: 1}
|
a: 1}
|
||||||
metroSplashScreenUseBackgroundColor: 0
|
metroSplashScreenUseBackgroundColor: 0
|
||||||
|
syncCapabilities: 0
|
||||||
platformCapabilities: {}
|
platformCapabilities: {}
|
||||||
metroTargetDeviceFamilies: {}
|
metroTargetDeviceFamilies: {}
|
||||||
metroFTAName:
|
metroFTAName:
|
||||||
metroFTAFileTypes: []
|
metroFTAFileTypes: []
|
||||||
metroProtocolName:
|
metroProtocolName:
|
||||||
|
vcxProjDefaultLanguage:
|
||||||
XboxOneProductId:
|
XboxOneProductId:
|
||||||
XboxOneUpdateKey:
|
XboxOneUpdateKey:
|
||||||
XboxOneSandboxId:
|
XboxOneSandboxId:
|
||||||
|
@ -601,6 +685,7 @@ PlayerSettings:
|
||||||
XboxOneCapability: []
|
XboxOneCapability: []
|
||||||
XboxOneGameRating: {}
|
XboxOneGameRating: {}
|
||||||
XboxOneIsContentPackage: 0
|
XboxOneIsContentPackage: 0
|
||||||
|
XboxOneEnhancedXboxCompatibilityMode: 0
|
||||||
XboxOneEnableGPUVariability: 1
|
XboxOneEnableGPUVariability: 1
|
||||||
XboxOneSockets: {}
|
XboxOneSockets: {}
|
||||||
XboxOneSplashScreen: {fileID: 0}
|
XboxOneSplashScreen: {fileID: 0}
|
||||||
|
@ -609,10 +694,7 @@ PlayerSettings:
|
||||||
XboxOneXTitleMemory: 8
|
XboxOneXTitleMemory: 8
|
||||||
XboxOneOverrideIdentityName:
|
XboxOneOverrideIdentityName:
|
||||||
XboxOneOverrideIdentityPublisher:
|
XboxOneOverrideIdentityPublisher:
|
||||||
vrEditorSettings:
|
vrEditorSettings: {}
|
||||||
daydream:
|
|
||||||
daydreamIconForeground: {fileID: 0}
|
|
||||||
daydreamIconBackground: {fileID: 0}
|
|
||||||
cloudServicesEnabled:
|
cloudServicesEnabled:
|
||||||
UNet: 1
|
UNet: 1
|
||||||
luminIcon:
|
luminIcon:
|
||||||
|
@ -626,12 +708,22 @@ PlayerSettings:
|
||||||
luminVersion:
|
luminVersion:
|
||||||
m_VersionCode: 1
|
m_VersionCode: 1
|
||||||
m_VersionName:
|
m_VersionName:
|
||||||
|
hmiPlayerDataPath:
|
||||||
|
hmiForceSRGBBlit: 1
|
||||||
|
embeddedLinuxEnableGamepadInput: 1
|
||||||
|
hmiLogStartupTiming: 0
|
||||||
|
hmiCpuConfiguration:
|
||||||
apiCompatibilityLevel: 6
|
apiCompatibilityLevel: 6
|
||||||
|
activeInputHandler: 0
|
||||||
|
windowsGamepadBackendHint: 0
|
||||||
cloudProjectId:
|
cloudProjectId:
|
||||||
framebufferDepthMemorylessMode: 0
|
framebufferDepthMemorylessMode: 0
|
||||||
|
qualitySettingsNames: []
|
||||||
projectName:
|
projectName:
|
||||||
organizationId:
|
organizationId:
|
||||||
cloudEnabled: 0
|
cloudEnabled: 0
|
||||||
enableNativePlatformBackendsForNewInputSystem: 0
|
|
||||||
disableOldInputManagerSupport: 0
|
|
||||||
legacyClampBlendShapeWeights: 1
|
legacyClampBlendShapeWeights: 1
|
||||||
|
hmiLoadingImage: {fileID: 0}
|
||||||
|
platformRequiresReadableAssets: 0
|
||||||
|
virtualTexturingSupportEnabled: 0
|
||||||
|
insecureHttpOption: 0
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
m_EditorVersion: 2020.2.1f1
|
m_EditorVersion: 2022.3.39f1
|
||||||
m_EditorVersionWithRevision: 2020.2.1f1 (270dd8c3da1c)
|
m_EditorVersionWithRevision: 2022.3.39f1 (4e1b0f82c39a)
|
||||||
|
|
|
@ -0,0 +1,121 @@
|
||||||
|
{
|
||||||
|
"templatePinStates": [],
|
||||||
|
"dependencyTypeInfos": [
|
||||||
|
{
|
||||||
|
"userAdded": false,
|
||||||
|
"type": "UnityEngine.AnimationClip",
|
||||||
|
"defaultInstantiationMode": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"userAdded": false,
|
||||||
|
"type": "UnityEditor.Animations.AnimatorController",
|
||||||
|
"defaultInstantiationMode": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"userAdded": false,
|
||||||
|
"type": "UnityEngine.AnimatorOverrideController",
|
||||||
|
"defaultInstantiationMode": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"userAdded": false,
|
||||||
|
"type": "UnityEditor.Audio.AudioMixerController",
|
||||||
|
"defaultInstantiationMode": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"userAdded": false,
|
||||||
|
"type": "UnityEngine.ComputeShader",
|
||||||
|
"defaultInstantiationMode": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"userAdded": false,
|
||||||
|
"type": "UnityEngine.Cubemap",
|
||||||
|
"defaultInstantiationMode": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"userAdded": false,
|
||||||
|
"type": "UnityEngine.GameObject",
|
||||||
|
"defaultInstantiationMode": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"userAdded": false,
|
||||||
|
"type": "UnityEditor.LightingDataAsset",
|
||||||
|
"defaultInstantiationMode": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"userAdded": false,
|
||||||
|
"type": "UnityEngine.LightingSettings",
|
||||||
|
"defaultInstantiationMode": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"userAdded": false,
|
||||||
|
"type": "UnityEngine.Material",
|
||||||
|
"defaultInstantiationMode": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"userAdded": false,
|
||||||
|
"type": "UnityEditor.MonoScript",
|
||||||
|
"defaultInstantiationMode": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"userAdded": false,
|
||||||
|
"type": "UnityEngine.PhysicMaterial",
|
||||||
|
"defaultInstantiationMode": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"userAdded": false,
|
||||||
|
"type": "UnityEngine.PhysicsMaterial2D",
|
||||||
|
"defaultInstantiationMode": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"userAdded": false,
|
||||||
|
"type": "UnityEngine.Rendering.PostProcessing.PostProcessProfile",
|
||||||
|
"defaultInstantiationMode": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"userAdded": false,
|
||||||
|
"type": "UnityEngine.Rendering.PostProcessing.PostProcessResources",
|
||||||
|
"defaultInstantiationMode": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"userAdded": false,
|
||||||
|
"type": "UnityEngine.Rendering.VolumeProfile",
|
||||||
|
"defaultInstantiationMode": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"userAdded": false,
|
||||||
|
"type": "UnityEditor.SceneAsset",
|
||||||
|
"defaultInstantiationMode": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"userAdded": false,
|
||||||
|
"type": "UnityEngine.Shader",
|
||||||
|
"defaultInstantiationMode": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"userAdded": false,
|
||||||
|
"type": "UnityEngine.ShaderVariantCollection",
|
||||||
|
"defaultInstantiationMode": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"userAdded": false,
|
||||||
|
"type": "UnityEngine.Texture",
|
||||||
|
"defaultInstantiationMode": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"userAdded": false,
|
||||||
|
"type": "UnityEngine.Texture2D",
|
||||||
|
"defaultInstantiationMode": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"userAdded": false,
|
||||||
|
"type": "UnityEngine.Timeline.TimelineAsset",
|
||||||
|
"defaultInstantiationMode": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"defaultDependencyTypeInfo": {
|
||||||
|
"userAdded": false,
|
||||||
|
"type": "<default_scene_template_dependencies>",
|
||||||
|
"defaultInstantiationMode": 1
|
||||||
|
},
|
||||||
|
"newSceneOverride": 0
|
||||||
|
}
|
|
@ -9,6 +9,7 @@ UnityConnectSettings:
|
||||||
m_EventOldUrl: https://api.uca.cloud.unity3d.com/v1/events
|
m_EventOldUrl: https://api.uca.cloud.unity3d.com/v1/events
|
||||||
m_EventUrl: https://cdp.cloud.unity3d.com/v1/events
|
m_EventUrl: https://cdp.cloud.unity3d.com/v1/events
|
||||||
m_ConfigUrl: https://config.uca.cloud.unity3d.com
|
m_ConfigUrl: https://config.uca.cloud.unity3d.com
|
||||||
|
m_DashboardUrl: https://dashboard.unity3d.com
|
||||||
m_TestInitMode: 0
|
m_TestInitMode: 0
|
||||||
CrashReportingSettings:
|
CrashReportingSettings:
|
||||||
m_EventUrl: https://perf-events.cloud.unity3d.com
|
m_EventUrl: https://perf-events.cloud.unity3d.com
|
||||||
|
@ -22,6 +23,7 @@ UnityConnectSettings:
|
||||||
m_Enabled: 0
|
m_Enabled: 0
|
||||||
m_TestMode: 0
|
m_TestMode: 0
|
||||||
m_InitializeOnStartup: 1
|
m_InitializeOnStartup: 1
|
||||||
|
m_PackageRequiringCoreStatsPresent: 0
|
||||||
UnityAdsSettings:
|
UnityAdsSettings:
|
||||||
m_Enabled: 0
|
m_Enabled: 0
|
||||||
m_InitializeOnStartup: 1
|
m_InitializeOnStartup: 1
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
%YAML 1.1
|
|
||||||
%TAG !u! tag:unity3d.com,2011:
|
|
||||||
--- !u!162 &1
|
|
||||||
EditorUserSettings:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
serializedVersion: 4
|
|
||||||
m_ConfigSettings:
|
|
||||||
RecentlyUsedScenePath-0:
|
|
||||||
value: 22424703114646680e0b0227036c6c1118131a25340527392367083debf42d
|
|
||||||
flags: 0
|
|
||||||
vcSharedLogLevel:
|
|
||||||
value: 0d5e400f0650
|
|
||||||
flags: 0
|
|
||||||
m_VCAutomaticAdd: 1
|
|
||||||
m_VCDebugCom: 0
|
|
||||||
m_VCDebugCmd: 0
|
|
||||||
m_VCDebugOut: 0
|
|
||||||
m_SemanticMergeMode: 2
|
|
||||||
m_VCShowFailedCheckout: 1
|
|
||||||
m_VCOverwriteFailedCheckoutAssets: 1
|
|
||||||
m_VCProjectOverlayIcons: 1
|
|
||||||
m_VCHierarchyOverlayIcons: 1
|
|
||||||
m_VCOtherOverlayIcons: 1
|
|
||||||
m_VCAllowAsyncUpdate: 0
|
|
Loading…
Reference in New Issue