mirror of
https://github.com/Cysharp/UniTask.git
synced 2026-05-15 19:40:09 +00:00
Compare commits
84 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3cc0c80b1e | ||
|
|
cdda33a98e | ||
|
|
e57a4332ec | ||
|
|
e88e553cc9 | ||
|
|
a1a38d0d7c | ||
|
|
c9bebd6550 | ||
|
|
42047070dd | ||
|
|
316f3bd963 | ||
|
|
5f96e646d4 | ||
|
|
186114996c | ||
|
|
841b6e85ae | ||
|
|
7ac9853cf6 | ||
|
|
0ec45b9da6 | ||
|
|
dfd0fe9fe4 | ||
|
|
4710268e0a | ||
|
|
cae512e4de | ||
|
|
6351d4c5a4 | ||
|
|
1173bb4f34 | ||
|
|
e4272b5337 | ||
|
|
b660506e31 | ||
|
|
2c101aef08 | ||
|
|
498b2a4f81 | ||
|
|
a8c2fd420a | ||
|
|
dade7fdc76 | ||
|
|
1c8b16f798 | ||
|
|
89649d8777 | ||
|
|
9894bf875b | ||
|
|
45a800330b | ||
|
|
a35e5f929d | ||
|
|
9a3f10d4bf | ||
|
|
19b5f921a1 | ||
|
|
8cd577904e | ||
|
|
309d661bcc | ||
|
|
8736024d9b | ||
|
|
97680e57a8 | ||
|
|
638522600a | ||
|
|
081113a62c | ||
|
|
7535c84581 | ||
|
|
690f3a2ead | ||
|
|
88371d08b9 | ||
|
|
6d382450cf | ||
|
|
19f2a6f282 | ||
|
|
7ed0b016ea | ||
|
|
f72a51e13d | ||
|
|
0e2dbbe754 | ||
|
|
cff51a0425 | ||
|
|
7cac4bbbab | ||
|
|
3f4a46bca6 | ||
|
|
7d21a75ea8 | ||
|
|
88817b7093 | ||
|
|
52cdadc035 | ||
|
|
5401b9b227 | ||
|
|
38de930f81 | ||
|
|
9be6ef7ba6 | ||
|
|
739bc6e26c | ||
|
|
71879266ac | ||
|
|
5ced0a1d4b | ||
|
|
908e361985 | ||
|
|
797affae4d | ||
|
|
ae3b825e29 | ||
|
|
143d97a73b | ||
|
|
90631c54b1 | ||
|
|
478e2998a8 | ||
|
|
9406305b2e | ||
|
|
1c26c81b20 | ||
|
|
a455de88b0 | ||
|
|
fba6942d5f | ||
|
|
3115efb672 | ||
|
|
fd70c031cb | ||
|
|
a2eb75df68 | ||
|
|
4a62d7eba6 | ||
|
|
40d2d2fe06 | ||
|
|
d5d2cb5937 | ||
|
|
854100c075 | ||
|
|
5837b26208 | ||
|
|
da0e654e7d | ||
|
|
a3e9932be7 | ||
|
|
e82353b4d9 | ||
|
|
944b61f28c | ||
|
|
457c574865 | ||
|
|
089a509663 | ||
|
|
3bebaef969 | ||
|
|
37e8b4500e | ||
|
|
8537ddf8a6 |
67
.github/workflows/build-debug.yml
vendored
67
.github/workflows/build-debug.yml
vendored
@@ -3,16 +3,16 @@ name: Build-Debug
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- "**"
|
- "master"
|
||||||
tags:
|
tags:
|
||||||
- "!*" # not a tag push
|
- "!*" # not a tag push
|
||||||
pull_request:
|
pull_request:
|
||||||
types:
|
branches:
|
||||||
- opened
|
- "master"
|
||||||
- synchronize
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-dotnet:
|
build-dotnet:
|
||||||
|
if: "!(contains(github.event.head_commit.message, '[skip ci]') || contains(github.event.head_commit.message, '[ci skip]'))"
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
env:
|
env:
|
||||||
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
||||||
@@ -22,46 +22,65 @@ jobs:
|
|||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-dotnet@v1
|
- uses: actions/setup-dotnet@v1
|
||||||
with:
|
with:
|
||||||
dotnet-version: 3.1.101
|
dotnet-version: 3.1.x
|
||||||
- run: dotnet test -c Debug ./src/UniTask.NetCoreTests/UniTask.NetCoreTests.csproj
|
- run: dotnet test -c Debug ./src/UniTask.NetCoreTests/UniTask.NetCoreTests.csproj
|
||||||
|
|
||||||
build-unity:
|
build-unity:
|
||||||
if: "(github.event == 'push' && github.repository_owner == 'Cysharp') || startsWith(github.event.pull_request.head.label, 'Cysharp:')"
|
if: "!(contains(github.event.head_commit.message, '[skip ci]') || contains(github.event.head_commit.message, '[ci skip]')) && ((github.event_name == 'push' && github.repository_owner == 'Cysharp') || startsWith(github.event.pull_request.head.label, 'Cysharp:'))"
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
unity: ["2019.3.9f1", "2020.1.0b5"]
|
unity: ["2019.3.9f1", "2019.4.13f1", "2020.1.12f1"]
|
||||||
include:
|
include:
|
||||||
- unity: 2019.3.9f1
|
- unity: 2019.3.9f1
|
||||||
license: UNITY_2019_3
|
license: UNITY_LICENSE_2019
|
||||||
- unity: 2020.1.0b5
|
- unity: 2019.4.13f1
|
||||||
license: UNITY_2020_1
|
license: UNITY_LICENSE_2019
|
||||||
|
- unity: 2020.1.12f1
|
||||||
|
license: UNITY_LICENSE_2020
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
|
||||||
# with linux-il2cpp. image from https://hub.docker.com/r/gableroux/unity3d/tags
|
|
||||||
image: gableroux/unity3d:${{ matrix.unity }}-linux-il2cpp
|
|
||||||
steps:
|
steps:
|
||||||
- run: apt update && apt install git -y
|
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- run: echo -n "$UNITY_LICENSE" >> .Unity.ulf
|
# Execute scripts: RuntimeUnitTestToolkit
|
||||||
|
# /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -projectPath . -executeMethod UnitTestBuilder.BuildUnitTest /headless /ScriptBackend mono /BuildTarget StandaloneLinux64
|
||||||
|
- name: Build UnitTest(Linux64, mono)
|
||||||
|
uses: game-ci/unity-builder@v2.0-alpha-6
|
||||||
env:
|
env:
|
||||||
UNITY_LICENSE: ${{ secrets[matrix.license] }}
|
UNITY_LICENSE: ${{ secrets[matrix.license] }}
|
||||||
- name: Activate Unity, always returns a success. But if a subsequent run fails, the activation may have failed(if succeeded, shows `Next license update check is after` and not shows other message(like GUID != GUID). If fails not). In that case, upload the artifact's .alf file to https://license.unity3d.com/manual to get the .ulf file and set it to secrets.
|
with:
|
||||||
run: /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -manualLicenseFile .Unity.ulf || exit 0
|
projectPath: src/UniTask
|
||||||
|
unityVersion: ${{ matrix.unity }}
|
||||||
# Execute scripts: RuntimeUnitTestToolkit
|
targetPlatform: StandaloneLinux64
|
||||||
- name: Build UnitTest(Linux64, mono)
|
buildMethod: UnitTestBuilder.BuildUnitTest
|
||||||
run: /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -projectPath . -executeMethod UnitTestBuilder.BuildUnitTest /headless /ScriptBackend mono /BuildTarget StandaloneLinux64
|
customParameters: /headless /ScriptBackend mono
|
||||||
working-directory: src/UniTask
|
versioning: None
|
||||||
- name: Execute UnitTest
|
- name: Execute UnitTest
|
||||||
run: ./src/UniTask/bin/UnitTest/StandaloneLinux64_Mono2x/test
|
run: ./src/UniTask/bin/UnitTest/StandaloneLinux64_Mono2x/test
|
||||||
|
|
||||||
# Execute scripts: Export Package
|
# Execute scripts: Export Package
|
||||||
|
# /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -projectPath . -executeMethod PackageExporter.Export
|
||||||
- name: Export unitypackage
|
- name: Export unitypackage
|
||||||
run: /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -projectPath . -executeMethod PackageExporter.Export
|
uses: game-ci/unity-builder@v2.0-alpha-6
|
||||||
|
env:
|
||||||
|
UNITY_LICENSE: ${{ secrets[matrix.license] }}
|
||||||
|
with:
|
||||||
|
projectPath: src/UniTask
|
||||||
|
unityVersion: ${{ matrix.unity }}
|
||||||
|
targetPlatform: StandaloneLinux64
|
||||||
|
buildMethod: PackageExporter.Export
|
||||||
|
versioning: None
|
||||||
|
|
||||||
|
- name: check all .meta is commited
|
||||||
|
run: |
|
||||||
|
if git ls-files --others --exclude-standard -t | grep --regexp='[.]meta$'; then
|
||||||
|
echo "Detected .meta file generated. Do you forgot commit a .meta file?"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo "Great, all .meta files are commited."
|
||||||
|
fi
|
||||||
working-directory: src/UniTask
|
working-directory: src/UniTask
|
||||||
|
|
||||||
# Store artifacts.
|
# Store artifacts.
|
||||||
- uses: actions/upload-artifact@v2
|
- uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: UniTask.unitypackage.zip
|
name: UniTask.unitypackage-${{ matrix.unity }}.zip
|
||||||
path: ./src/UniTask/*.unitypackage
|
path: ./src/UniTask/*.unitypackage
|
||||||
|
|||||||
192
.github/workflows/build-release.yml
vendored
192
.github/workflows/build-release.yml
vendored
@@ -1,105 +1,181 @@
|
|||||||
name: Build-Release
|
name: build-release
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
workflow_dispatch:
|
||||||
tags:
|
inputs:
|
||||||
- "[0-9]+.[0-9]+.[0-9]+*"
|
tag:
|
||||||
|
description: "tag: git tag you want create. (sample 1.0.0)"
|
||||||
|
required: true
|
||||||
|
dry_run:
|
||||||
|
description: "dry_run: true will never create relase/nuget."
|
||||||
|
required: true
|
||||||
|
default: "false"
|
||||||
|
|
||||||
|
env:
|
||||||
|
GIT_TAG: ${{ github.event.inputs.tag }}
|
||||||
|
DRY_RUN: ${{ github.event.inputs.dry_run }}
|
||||||
|
DRY_RUN_BRANCH_PREFIX: "test_release"
|
||||||
|
DOTNET_SDK_VERISON_3: 3.1.x
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-dotnet:
|
update-packagejson:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
TARGET_FILE: ./src/UniTask/Assets/Plugins/UniTask/package.json
|
||||||
|
outputs:
|
||||||
|
sha: ${{ steps.commit.outputs.sha }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: before
|
||||||
|
run: cat ${{ env.TARGET_FILE}}
|
||||||
|
- name: update package.json to version ${{ env.GIT_TAG }}
|
||||||
|
run: sed -i -e "s/\(\"version\":\) \"\(.*\)\",/\1 \"${{ env.GIT_TAG }}\",/" ${{ env.TARGET_FILE }}
|
||||||
|
- name: after
|
||||||
|
run: cat ${{ env.TARGET_FILE}}
|
||||||
|
- name: Commit files
|
||||||
|
id: commit
|
||||||
|
run: |
|
||||||
|
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||||
|
git config --local user.name "github-actions[bot]"
|
||||||
|
git commit -m "feat: Update package.json to ${{ env.GIT_TAG }}" -a
|
||||||
|
echo "::set-output name=sha::$(git rev-parse HEAD)"
|
||||||
|
- name: check sha
|
||||||
|
run: echo "SHA ${SHA}"
|
||||||
|
env:
|
||||||
|
SHA: ${{ steps.commit.outputs.sha }}
|
||||||
|
- name: tag
|
||||||
|
run: git tag ${{ env.GIT_TAG }}
|
||||||
|
if: env.DRY_RUN == 'false'
|
||||||
|
- name: Push changes
|
||||||
|
uses: ad-m/github-push-action@master
|
||||||
|
with:
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
branch: ${{ github.ref }}
|
||||||
|
tags: true
|
||||||
|
if: env.DRY_RUN == 'false'
|
||||||
|
- name: Push changes (dry_run)
|
||||||
|
uses: ad-m/github-push-action@master
|
||||||
|
with:
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
branch: ${{ env.DRY_RUN_BRANCH_PREFIX }}-${{ env.GIT_TAG }}
|
||||||
|
tags: false
|
||||||
|
if: env.DRY_RUN == 'true'
|
||||||
|
|
||||||
|
build-dotnet:
|
||||||
|
needs: [update-packagejson]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 10
|
||||||
env:
|
env:
|
||||||
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
||||||
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1
|
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1
|
||||||
NUGET_XMLDOC_MODE: skip
|
NUGET_XMLDOC_MODE: skip
|
||||||
steps:
|
steps:
|
||||||
|
- run: echo ${{ needs.update-packagejson.outputs.sha }}
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
ref: ${{ needs.update-packagejson.outputs.sha }}
|
||||||
- uses: actions/setup-dotnet@v1
|
- uses: actions/setup-dotnet@v1
|
||||||
with:
|
with:
|
||||||
dotnet-version: 3.1.101
|
dotnet-version: "${{ env.DOTNET_SDK_VERSION_3 }}"
|
||||||
# set release tag(*.*.*) to env.GIT_TAG
|
|
||||||
- run: echo ::set-env name=GIT_TAG::${GITHUB_REF#refs/tags/}
|
|
||||||
|
|
||||||
# build and pack
|
# build and pack
|
||||||
- run: dotnet build -c Release -p:Version=${{ env.GIT_TAG }}
|
- run: dotnet build -c Release -p:Version=${{ env.GIT_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 }}
|
- run: dotnet pack ./src/UniTask.NetCore/UniTask.NetCore.csproj -c Release --no-build -p:Version=${{ env.GIT_TAG }} -o ./publish
|
||||||
|
|
||||||
# Store artifacts.
|
# Store artifacts.
|
||||||
- uses: actions/upload-artifact@v1
|
- uses: actions/upload-artifact@v1
|
||||||
with:
|
with:
|
||||||
name: nuget
|
name: nuget
|
||||||
path: ./src/UniTask.NetCore/bin/Release/UniTask.${{ env.GIT_TAG }}.nupkg
|
path: ./publish/
|
||||||
|
|
||||||
build-unity:
|
build-unity:
|
||||||
|
needs: [update-packagejson]
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
unity: ['2019.3.9f1']
|
unity: ["2019.3.9f1"]
|
||||||
include:
|
include:
|
||||||
- unity: 2019.3.9f1
|
- unity: 2019.3.9f1
|
||||||
license: UNITY_2019_3
|
license: UNITY_LICENSE_2019
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
timeout-minutes: 15
|
||||||
# with linux-il2cpp. image from https://hub.docker.com/r/gableroux/unity3d/tags
|
|
||||||
image: gableroux/unity3d:${{ matrix.unity }}-linux-il2cpp
|
|
||||||
steps:
|
steps:
|
||||||
- run: apt update && apt install git -y
|
- run: echo ${{ needs.update-packagejson.outputs.sha }}
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- run: echo -n "$UNITY_LICENSE" >> .Unity.ulf
|
with:
|
||||||
|
ref: ${{ needs.update-packagejson.outputs.sha }}
|
||||||
|
# Execute scripts: Export Package
|
||||||
|
# /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -projectPath . -executeMethod PackageExporter.Export
|
||||||
|
- name: Export unitypackage
|
||||||
|
uses: game-ci/unity-builder@v2.0-alpha-6
|
||||||
env:
|
env:
|
||||||
UNITY_LICENSE: ${{ secrets[matrix.license] }}
|
UNITY_LICENSE: ${{ secrets[matrix.license] }}
|
||||||
- run: /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -manualLicenseFile .Unity.ulf || exit 0
|
with:
|
||||||
|
projectPath: src/UniTask
|
||||||
|
unityVersion: ${{ matrix.unity }}
|
||||||
|
targetPlatform: StandaloneLinux64
|
||||||
|
buildMethod: PackageExporter.Export
|
||||||
|
versioning: None
|
||||||
|
|
||||||
# set release tag(*.*.*) to env.GIT_TAG
|
- name: check all .meta is commited
|
||||||
- run: echo ::set-env name=GIT_TAG::${GITHUB_REF#refs/tags/}
|
run: |
|
||||||
|
if git ls-files --others --exclude-standard -t | grep --regexp='[.]meta$'; then
|
||||||
# Execute scripts: Export Package
|
echo "Detected .meta file generated. Do you forgot commit a .meta file?"
|
||||||
- name: Export unitypackage
|
exit 1
|
||||||
run: /opt/Unity/Editor/Unity -quit -batchmode -nographics -silent-crashes -logFile -projectPath . -executeMethod PackageExporter.Export
|
else
|
||||||
|
echo "Great, all .meta files are commited."
|
||||||
|
fi
|
||||||
working-directory: src/UniTask
|
working-directory: src/UniTask
|
||||||
|
|
||||||
# Store artifacts.
|
# Store artifacts.
|
||||||
- uses: actions/upload-artifact@v2
|
- uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: UniTask.${{ env.GIT_TAG }}.unitypackage
|
name: UniTask.${{ env.GIT_TAG }}.unitypackage
|
||||||
path: ./src/UniTask/UniTask.${{ env.GIT_TAG }}.unitypackage
|
path: ./src/UniTask/UniTask.${{ env.GIT_TAG }}.unitypackage
|
||||||
|
|
||||||
create-release:
|
create-release:
|
||||||
needs: [build-dotnet, build-unity]
|
if: github.event.inputs.dry_run == 'false'
|
||||||
|
needs: [update-packagejson, build-dotnet, build-unity]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
env:
|
env:
|
||||||
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
||||||
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1
|
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1
|
||||||
NUGET_XMLDOC_MODE: skip
|
NUGET_XMLDOC_MODE: skip
|
||||||
steps:
|
steps:
|
||||||
# setup dotnet for nuget push
|
# setup dotnet for nuget push
|
||||||
- uses: actions/setup-dotnet@v1
|
- uses: actions/setup-dotnet@v1
|
||||||
with:
|
with:
|
||||||
dotnet-version: 3.1.101
|
dotnet-version: "${{ env.DOTNET_SDK_VERSION_3 }}"
|
||||||
# set release tag(*.*.*) to env.GIT_TAG
|
# Create Releases
|
||||||
- run: echo ::set-env name=GIT_TAG::${GITHUB_REF#refs/tags/}
|
- uses: actions/create-release@v1
|
||||||
|
id: create_release
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
tag_name: ${{ env.GIT_TAG }}
|
||||||
|
release_name: Ver.${{ env.GIT_TAG }}
|
||||||
|
commitish: ${{ needs.update-packagejson.outputs.sha }}
|
||||||
|
draft: true
|
||||||
|
prerelease: false
|
||||||
|
# Download(All) Artifacts to current directory
|
||||||
|
- uses: actions/download-artifact@v2
|
||||||
|
# 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
|
||||||
|
|
||||||
# Create Releases
|
cleanup:
|
||||||
- uses: actions/create-release@v1
|
if: github.event.inputs.dry_run == 'true'
|
||||||
id: create_release
|
needs: [build-dotnet, build-unity]
|
||||||
env:
|
runs-on: ubuntu-latest
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
steps:
|
||||||
with:
|
- name: Delete branch
|
||||||
tag_name: ${{ github.ref }}
|
uses: dawidd6/action-delete-branch@v3
|
||||||
release_name: Ver.${{ github.ref }}
|
with:
|
||||||
|
github_token: ${{ github.token }}
|
||||||
# Download(All) Artifacts to current directory
|
branches: ${{ env.DRY_RUN_BRANCH_PREFIX }}-${{ env.GIT_TAG }}
|
||||||
- uses: actions/download-artifact@v2-preview
|
|
||||||
|
|
||||||
# Upload to NuGet
|
|
||||||
- run: dotnet nuget push "./nuget/*.nupkg" -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
|
|
||||||
|
|||||||
24
.github/workflows/stale.yml
vendored
Normal file
24
.github/workflows/stale.yml
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
name: "Close stale issues"
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: "0 0 * * *"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
stale:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/stale@v3
|
||||||
|
with:
|
||||||
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
# enable issue
|
||||||
|
stale-issue-message: "This issue is stale because it has been open 90 days with no activity. Remove stale label or comment or this will be closed in 7 days."
|
||||||
|
stale-issue-label: "stale"
|
||||||
|
# enable pr
|
||||||
|
stale-pr-message: "This PR is stale because it has been open 90 days with no activity. Remove stale label or comment or this will be closed in 7 days."
|
||||||
|
stale-pr-label: "stale"
|
||||||
|
days-before-stale: 90
|
||||||
|
days-before-close: 7
|
||||||
|
exempt-issue-labels: "wip"
|
||||||
|
exempt-pr-labels: "wip"
|
||||||
|
remove-stale-when-updated: true
|
||||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -255,3 +255,9 @@ src/UniTask/DOTween.Modules.Player.csproj
|
|||||||
src/UniTask/Assembly-CSharp.Player.csproj
|
src/UniTask/Assembly-CSharp.Player.csproj
|
||||||
|
|
||||||
src/UniTask/Unity.EditorCoroutines.Editor.csproj
|
src/UniTask/Unity.EditorCoroutines.Editor.csproj
|
||||||
|
|
||||||
|
src/UniTask/.vsconfig
|
||||||
|
|
||||||
|
src/UniTask/Logs/ApiUpdaterCheck.txt
|
||||||
|
|
||||||
|
src/UniTask/Assembly-CSharp-firstpass.csproj
|
||||||
|
|||||||
323
README.md
323
README.md
@@ -2,20 +2,20 @@ 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)
|
||||||
|
|
||||||
Provides an efficient allocation free async/await integration to Unity.
|
Provides an efficient allocation free async/await integration for Unity.
|
||||||
|
|
||||||
* Struct based `UniTask<T>` and custom AsyncMethodBuilder to achive zero allocation
|
* Struct based `UniTask<T>` and custom AsyncMethodBuilder to achieve zero allocation
|
||||||
* All Unity AsyncOperations and Coroutine to awaitable
|
* Makes all Unity AsyncOperations and Coroutines awaitable
|
||||||
* PlayerLoop based task(`UniTask.Yield`, `UniTask.Delay`, `UniTask.DelayFrame`, etc..) that enable to replace all coroutine operation
|
* PlayerLoop based task(`UniTask.Yield`, `UniTask.Delay`, `UniTask.DelayFrame`, etc..) that enable replacing all coroutine operations
|
||||||
* MonoBehaviour Message Events and uGUI Events as awaitable/async-enumerable
|
* MonoBehaviour Message Events and uGUI Events as awaitable/async-enumerable
|
||||||
* Completely run on Unity's PlayerLoop so don't use thread and run on WebGL, wasm, etc.
|
* Runs completely on Unity's PlayerLoop so doesn't use threads and runs on WebGL, wasm, etc.
|
||||||
* Asynchronous LINQ, with Channel and AsyncReactiveProperty
|
* Asynchronous LINQ, with Channel and AsyncReactiveProperty
|
||||||
* TaskTracker window to prevent memory leak
|
* TaskTracker window to prevent memory leaks
|
||||||
* Highly compatible behaviour with Task/ValueTask/IValueTaskSource
|
* Highly compatible behaviour with Task/ValueTask/IValueTaskSource
|
||||||
|
|
||||||
Techinical details, see blog post: [UniTask v2 — Zero Allocation async/await for Unity, with Asynchronous LINQ
|
For technical details, see blog post: [UniTask v2 — Zero Allocation async/await for Unity, with Asynchronous LINQ
|
||||||
](https://medium.com/@neuecc/unitask-v2-zero-allocation-async-await-for-unity-with-asynchronous-linq-1aa9c96aa7dd)
|
](https://medium.com/@neuecc/unitask-v2-zero-allocation-async-await-for-unity-with-asynchronous-linq-1aa9c96aa7dd)
|
||||||
Advanced tips, see blog post: [Extends UnityWebRequest via async decorator pattern — Advanced Techniques of UniTask](https://medium.com/@neuecc/extends-unitywebrequest-via-async-decorator-pattern-advanced-techniques-of-unitask-ceff9c5ee846)
|
For advanced tips, see blog post: [Extends UnityWebRequest via async decorator pattern — Advanced Techniques of UniTask](https://medium.com/@neuecc/extends-unitywebrequest-via-async-decorator-pattern-advanced-techniques-of-unitask-ceff9c5ee846)
|
||||||
|
|
||||||
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
||||||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
||||||
@@ -24,6 +24,7 @@ Advanced tips, see blog post: [Extends UnityWebRequest via async decorator patte
|
|||||||
- [Getting started](#getting-started)
|
- [Getting started](#getting-started)
|
||||||
- [Basics of UniTask and AsyncOperation](#basics-of-unitask-and-asyncoperation)
|
- [Basics of UniTask and AsyncOperation](#basics-of-unitask-and-asyncoperation)
|
||||||
- [Cancellation and Exception handling](#cancellation-and-exception-handling)
|
- [Cancellation and Exception handling](#cancellation-and-exception-handling)
|
||||||
|
- [Timeout handling](#timeout-handling)
|
||||||
- [Progress](#progress)
|
- [Progress](#progress)
|
||||||
- [PlayerLoop](#playerloop)
|
- [PlayerLoop](#playerloop)
|
||||||
- [async void vs async UniTaskVoid](#async-void-vs-async-unitaskvoid)
|
- [async void vs async UniTaskVoid](#async-void-vs-async-unitaskvoid)
|
||||||
@@ -72,7 +73,7 @@ async UniTask<string> DemoAsync()
|
|||||||
// .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>
|
||||||
var asset3 = await Resources.LoadAsync<TextAsset>("baz").ToUniTask(Progress.Create<float>(x => Debug.Log(x)));
|
var asset3 = await Resources.LoadAsync<TextAsset>("baz").ToUniTask(Progress.Create<float>(x => Debug.Log(x)));
|
||||||
|
|
||||||
// await frame-based operation like coroutine
|
// await frame-based operation like a coroutine
|
||||||
await UniTask.DelayFrame(100);
|
await UniTask.DelayFrame(100);
|
||||||
|
|
||||||
// replacement of yield return new WaitForSeconds/WaitForSecondsRealtime
|
// replacement of yield return new WaitForSeconds/WaitForSecondsRealtime
|
||||||
@@ -97,10 +98,10 @@ async UniTask<string> DemoAsync()
|
|||||||
// special helper of WaitUntil
|
// special helper of WaitUntil
|
||||||
await UniTask.WaitUntilValueChanged(this, x => x.isActive);
|
await UniTask.WaitUntilValueChanged(this, x => x.isActive);
|
||||||
|
|
||||||
// You can await IEnumerator coroutine
|
// You can await IEnumerator coroutines
|
||||||
await FooCoroutineEnumerator();
|
await FooCoroutineEnumerator();
|
||||||
|
|
||||||
// You can await standard task
|
// You can await a standard task
|
||||||
await Task.Run(() => 100);
|
await Task.Run(() => 100);
|
||||||
|
|
||||||
// Multithreading, run on ThreadPool under this code
|
// Multithreading, run on ThreadPool under this code
|
||||||
@@ -122,14 +123,11 @@ async UniTask<string> DemoAsync()
|
|||||||
var task2 = GetTextAsync(UnityWebRequest.Get("http://bing.com"));
|
var task2 = GetTextAsync(UnityWebRequest.Get("http://bing.com"));
|
||||||
var task3 = GetTextAsync(UnityWebRequest.Get("http://yahoo.com"));
|
var task3 = GetTextAsync(UnityWebRequest.Get("http://yahoo.com"));
|
||||||
|
|
||||||
// concurrent async-wait and get result easily by tuple syntax
|
// concurrent async-wait and get results easily by tuple syntax
|
||||||
var (google, bing, yahoo) = await UniTask.WhenAll(task1, task2, task3);
|
var (google, bing, yahoo) = await UniTask.WhenAll(task1, task2, task3);
|
||||||
|
|
||||||
// shorthand of WhenAll, tuple can await directly
|
// shorthand of WhenAll, tuple can await directly
|
||||||
var (google2, bing2, yahoo2) = await (task1, task2, task3);
|
var (google2, bing2, yahoo2) = await (task1, task2, task3);
|
||||||
|
|
||||||
// You can handle timeout easily
|
|
||||||
await GetTextAsync(UnityWebRequest.Get("http://unity.com")).Timeout(TimeSpan.FromMilliseconds(300));
|
|
||||||
|
|
||||||
// return async-value.(or you can use `UniTask`(no result), `UniTaskVoid`(fire and forget)).
|
// return async-value.(or you can use `UniTask`(no result), `UniTaskVoid`(fire and forget)).
|
||||||
return (asset as TextAsset)?.text ?? throw new InvalidOperationException("Asset not found");
|
return (asset as TextAsset)?.text ?? throw new InvalidOperationException("Asset not found");
|
||||||
@@ -138,9 +136,9 @@ async UniTask<string> DemoAsync()
|
|||||||
|
|
||||||
Basics of UniTask and AsyncOperation
|
Basics of UniTask and AsyncOperation
|
||||||
---
|
---
|
||||||
UniTask feature rely on C# 7.0([task-like custom async method builder feature](https://github.com/dotnet/roslyn/blob/master/docs/features/task-types.md)) so required Unity version is after `Unity 2018.3`, officialy lower support version is `Unity 2018.4.13f1`.
|
UniTask features rely on C# 7.0([task-like custom async method builder feature](https://github.com/dotnet/roslyn/blob/master/docs/features/task-types.md)) so the required Unity version is after `Unity 2018.3`, the official lowest version supported is `Unity 2018.4.13f1`.
|
||||||
|
|
||||||
Why UniTask(custom task-like object) is required? Because Task is too heavy, not matched to Unity threading(single-thread). UniTask does not use thread and SynchronizationContext/ExecutionContext because almost Unity's asynchronous object is automaticaly dispatched by Unity's engine layer. It acquires more fast and more less allocation, completely integrated with Unity.
|
Why is UniTask(custom task-like object) required? Because Task is too heavy and not matched to Unity threading (single-thread). UniTask does not use threads and SynchronizationContext/ExecutionContext because Unity's asynchronous object is automaticaly dispatched by Unity's engine layer. It achieves faster and lower allocation, and is completely integrated with Unity.
|
||||||
|
|
||||||
You can await `AsyncOperation`, `ResourceRequest`, `AssetBundleRequest`, `AssetBundleCreateRequest`, `UnityWebRequestAsyncOperation`, `AsyncGPUReadbackRequest`, `IEnumerator` and others when `using Cysharp.Threading.Tasks;`.
|
You can await `AsyncOperation`, `ResourceRequest`, `AssetBundleRequest`, `AssetBundleCreateRequest`, `UnityWebRequestAsyncOperation`, `AsyncGPUReadbackRequest`, `IEnumerator` and others when `using Cysharp.Threading.Tasks;`.
|
||||||
|
|
||||||
@@ -152,13 +150,13 @@ UniTask provides three pattern of extension methods.
|
|||||||
* .ToUniTask(IProgress, PlayerLoopTiming, CancellationToken);
|
* .ToUniTask(IProgress, PlayerLoopTiming, CancellationToken);
|
||||||
```
|
```
|
||||||
|
|
||||||
`WithCancellation` is a simple version of `ToUniTask`, both returns `UniTask`. Details of cancellation, see: [Cancellation and Exception handling](#cancellation-and-exception-handling) section.
|
`WithCancellation` is a simple version of `ToUniTask`, both return `UniTask`. For details of cancellation, see: [Cancellation and Exception handling](#cancellation-and-exception-handling) section.
|
||||||
|
|
||||||
> Note: WithCancellation is returned from native timing of PlayerLoop but ToUniTask is returned from specified PlayerLoopTiming. Details of timing, see: [PlayerLoop](#playerloop) section.
|
> Note: await directly is returned from native timing of PlayerLoop but WithCancellation and ToUniTask are returned from specified PlayerLoopTiming. For details of timing, see: [PlayerLoop](#playerloop) section.
|
||||||
|
|
||||||
> Note: AssetBundleRequest has `asset` and `allAssets`, in 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 utility like `UniTask.WhenAll`, `UniTask.WhenAny`. It is like Task.WhenAll/WhenAny but return type is more useful, returns value tuple so can deconsrtuct each result and pass multiple type.
|
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.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
public async UniTaskVoid LoadManyAsync()
|
public async UniTaskVoid LoadManyAsync()
|
||||||
@@ -177,7 +175,7 @@ async UniTask<Sprite> LoadAsSprite(string path)
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
If you want to convert callback to UniTask, you can use `UniTaskCompletionSource<T>` that is the lightweight edition of `TaskCompletionSource<T>`.
|
If you want to convert a callback to UniTask, you can use `UniTaskCompletionSource<T>` which is a lightweight edition of `TaskCompletionSource<T>`.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
public UniTask<int> WrapByUniTaskCompletionSource()
|
public UniTask<int> WrapByUniTaskCompletionSource()
|
||||||
@@ -194,7 +192,7 @@ public UniTask<int> WrapByUniTaskCompletionSource()
|
|||||||
|
|
||||||
You can convert Task -> UniTask: `AsUniTask`, `UniTask` -> `UniTask<AsyncUnit>`: `AsAsyncUnitUniTask`, `UniTask<T>` -> `UniTask`: `AsUniTask`. `UniTask<T>` -> `UniTask`'s conversion cost is free.
|
You can convert Task -> UniTask: `AsUniTask`, `UniTask` -> `UniTask<AsyncUnit>`: `AsAsyncUnitUniTask`, `UniTask<T>` -> `UniTask`: `AsUniTask`. `UniTask<T>` -> `UniTask`'s conversion cost is free.
|
||||||
|
|
||||||
If you want to convert async to coroutine, you can use `.ToCoroutine()`, this is useful to use only allow coroutine system.
|
If you want to convert async to coroutine, you can use `.ToCoroutine()`, this is useful if you want to only allow using the coroutine system.
|
||||||
|
|
||||||
UniTask can not await twice. This is a similar constraint to the [ValueTask/IValueTaskSource](https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.valuetask-1?view=netcore-3.1) introduced in .NET Standard 2.1.
|
UniTask can not await twice. This is a similar constraint to the [ValueTask/IValueTaskSource](https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.valuetask-1?view=netcore-3.1) introduced in .NET Standard 2.1.
|
||||||
|
|
||||||
@@ -213,11 +211,13 @@ await task;
|
|||||||
await task; // NG, throws Exception
|
await task; // NG, throws Exception
|
||||||
```
|
```
|
||||||
|
|
||||||
Store to the class field, you can use `UniTask.Lazy` that gurantee call multipletimes. `.Preserve()` allows for multiple calls (internally cached results). This is useful when multiple calls in a function scope.
|
Store to the class field, you can use `UniTask.Lazy` that supports calling multiple times. `.Preserve()` allows for multiple calls (internally cached results). This is useful when there are multiple calls in a function scope.
|
||||||
|
|
||||||
|
Also `UniTaskCompletionSource` can await multiple times and await from many callers.
|
||||||
|
|
||||||
Cancellation and Exception handling
|
Cancellation and Exception handling
|
||||||
---
|
---
|
||||||
Some UniTask factory methods have `CancellationToken cancellationToken = default` parameter. Andalso some async operation for unity have `WithCancellation(CancellationToken)` and `ToUniTask(..., CancellationToken cancellation = default)` extension methods.
|
Some UniTask factory methods have a `CancellationToken cancellationToken = default` parameter. Also some async operations for Unity have `WithCancellation(CancellationToken)` and `ToUniTask(..., CancellationToken cancellation = default)` extension methods.
|
||||||
|
|
||||||
You can pass `CancellationToken` to parameter by standard [`CancellationTokenSource`](https://docs.microsoft.com/en-us/dotnet/api/system.threading.cancellationtokensource).
|
You can pass `CancellationToken` to parameter by standard [`CancellationTokenSource`](https://docs.microsoft.com/en-us/dotnet/api/system.threading.cancellationtokensource).
|
||||||
|
|
||||||
@@ -234,18 +234,18 @@ await UnityWebRequest.Get("http://google.co.jp").SendWebRequest().WithCancellati
|
|||||||
await UniTask.DelayFrame(1000, cancellationToken: cts.Token);
|
await UniTask.DelayFrame(1000, cancellationToken: cts.Token);
|
||||||
```
|
```
|
||||||
|
|
||||||
CancellationToken can create by `CancellationTokenSource` or MonoBehaviour's extension method `GetCancellationTokenOnDestroy`.
|
CancellationToken can be created by `CancellationTokenSource` or MonoBehaviour's extension method `GetCancellationTokenOnDestroy`.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// this CancellationToken lifecycle is same as GameObject.
|
// this CancellationToken lifecycle is same as GameObject.
|
||||||
await UniTask.DelayFrame(1000, cancellationToken: this.GetCancellationTokenOnDestroy());
|
await UniTask.DelayFrame(1000, cancellationToken: this.GetCancellationTokenOnDestroy());
|
||||||
```
|
```
|
||||||
|
|
||||||
When detect cancellation, all methods throws `OperationCanceledException` and propagate to upstream. `OperationCanceledException` is special exception, if not handled this exception, finally it is propagated to `UniTaskScheduler.UnobservedTaskException`.
|
When cancellation is detected, all methods throw `OperationCanceledException` and propagate upstream. `OperationCanceledException` is a special exception, if this exception is not handled, it is propagated finally to `UniTaskScheduler.UnobservedTaskException`.
|
||||||
|
|
||||||
Default behaviour of received unhandled exception is write log as exception. Log level can change by `UniTaskScheduler.UnobservedExceptionWriteLogType`. If you want to change custom beavhiour, set action 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.`
|
||||||
|
|
||||||
If you want to cancel behaviour in async UniTask method, throws `OperationCanceledException` manually.
|
If you want to cancel behaviour in an async UniTask method, throw `OperationCanceledException` manually.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
public async UniTask<int> FooAsync()
|
public async UniTask<int> FooAsync()
|
||||||
@@ -255,7 +255,7 @@ public async UniTask<int> FooAsync()
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
If you handle exception but want to ignore(propagete to global cancellation handling), use exception filter.
|
If you handle an exception but want to ignore(propagate to global cancellation handling), use an exception filter.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
public async UniTask<int> BarAsync()
|
public async UniTask<int> BarAsync()
|
||||||
@@ -272,7 +272,7 @@ public async UniTask<int> BarAsync()
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
throws/catch `OperationCanceledException` is slightly heavy, if you want to care performance, use `UniTask.SuppressCancellationThrow` to avoid OperationCanceledException throw. It returns `(bool IsCanceled, T Result)` instead of throw.
|
throws/catch `OperationCanceledException` is slightly heavy, so if performance is a concern, use `UniTask.SuppressCancellationThrow` to avoid OperationCanceledException throw. It returns `(bool IsCanceled, T Result)` instead of throwing.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
var (isCanceled, _) = await UniTask.DelayFrame(10, cancellationToken: cts.Token).SuppressCancellationThrow();
|
var (isCanceled, _) = await UniTask.DelayFrame(10, cancellationToken: cts.Token).SuppressCancellationThrow();
|
||||||
@@ -282,11 +282,105 @@ if (isCanceled)
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Note: Only suppress throws if you call it directly into the most source method. Otherwise, the return value will be converted, but the entire pipeline will not be suppressed 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.
|
||||||
|
|
||||||
|
Timeout handling
|
||||||
|
---
|
||||||
|
Timeout is a variation of cancellation. You can set timeout by `CancellationTokenSouce.CancelAfterSlim(TimeSpan)` and pass CancellationToken to async methods.
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
var cts = new CancellationTokenSource();
|
||||||
|
cts.CancelAfterSlim(TimeSpan.FromSeconds(5)); // 5sec timeout.
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await UnityWebRequest.Get("http://foo").SendWebRequest().WithCancellation(cts.Token);
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException ex)
|
||||||
|
{
|
||||||
|
if (ex.CancellationToken == cts.Token)
|
||||||
|
{
|
||||||
|
UnityEngine.Debug.Log("Timeout");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
> `CancellationTokenSouce.CancelAfter` is a standard api. However in Unity you should not use it because it depends threading timer. `CancelAfterSlim` is UniTask's extension methods, it uses PlayerLoop instead.
|
||||||
|
|
||||||
|
If you want to use timeout with other source of cancellation, use `CancellationTokenSource.CreateLinkedTokenSource`.
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
var cancelToken = new CancellationTokenSource();
|
||||||
|
cancelButton.onClick.AddListener(()=>
|
||||||
|
{
|
||||||
|
cancelToken.Cancel(); // cancel from button click.
|
||||||
|
});
|
||||||
|
|
||||||
|
var timeoutToken = new CancellationTokenSource();
|
||||||
|
timeoutToken.CancelAfterSlim(TimeSpan.FromSeconds(5)); // 5sec timeout.
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// combine token
|
||||||
|
var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancelToken.Token, timeoutToken.Token);
|
||||||
|
|
||||||
|
await UnityWebRequest.Get("http://foo").SendWebRequest().WithCancellation(linkedTokenSource.Token);
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException ex)
|
||||||
|
{
|
||||||
|
if (timeoutToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
UnityEngine.Debug.Log("Timeout.");
|
||||||
|
}
|
||||||
|
else if (cancelToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
UnityEngine.Debug.Log("Cancel clicked.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Optimize for reduce allocation of CancellationTokenSource for timeout per call async method, you can use UniTask's `TimeoutController`.
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
TimeoutController timeoutController = new TimeoutController(); // setup to field for reuse.
|
||||||
|
|
||||||
|
async UniTask FooAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// you can pass timeoutController.Timeout(TimeSpan) to cancellationToken.
|
||||||
|
await UnityWebRequest.Get("http://foo").SendWebRequest()
|
||||||
|
.WithCancellation(timeoutController.Timeout(TimeSpan.FromSeconds(5)));
|
||||||
|
timeoutController.Reset(); // call Reset(Stop timeout timer and ready for reuse) when succeed.
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException ex)
|
||||||
|
{
|
||||||
|
if (timeoutController.IsTimeout())
|
||||||
|
{
|
||||||
|
UnityEngine.Debug.Log("timeout");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If you want to use timeout with other source of cancellation, use `new TimeoutController(CancellationToken)`.
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
TimeoutController timeoutController;
|
||||||
|
CancellationTokenSource clickCancelSource;
|
||||||
|
|
||||||
|
void Start()
|
||||||
|
{
|
||||||
|
this.clickCancelSource = new CancellationTokenSource();
|
||||||
|
this.timeoutController = new TimeoutController(clickCancelSource);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Note: UniTask has `.Timeout`, `.TimeoutWithoutException` methods however, if possible, do not use these, please pass `CancellationToken`. Because `.Timeout` work from external of task, can not stop timeoutted task. `.Timeout` means ignore result when timeout. If you pass a `CancellationToken` to the method, it will act from inside of the task, so it is possible to stop a running task.
|
||||||
|
|
||||||
Progress
|
Progress
|
||||||
---
|
---
|
||||||
Some async operation for unity have `ToUniTask(IProgress<float> progress = null, ...)` extension methods.
|
Some async operations for unity have `ToUniTask(IProgress<float> progress = null, ...)` extension methods.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
var progress = Progress.Create<float>(x => Debug.Log(x));
|
var progress = Progress.Create<float>(x => Debug.Log(x));
|
||||||
@@ -296,9 +390,9 @@ var request = await UnityWebRequest.Get("http://google.co.jp")
|
|||||||
.ToUniTask(progress: progress);
|
.ToUniTask(progress: progress);
|
||||||
```
|
```
|
||||||
|
|
||||||
You should not use standard `new System.Progress<T>`, because it causes allocation every times. Use `Cysharp.Threading.Tasks.Progress` instead. This progress factory has two methods, `Create` and `CreateOnlyValueChanged`. `CreateOnlyValueChanged` calls only when progress value changed.
|
You should not use standard `new System.Progress<T>`, because it causes allocation every time. Use `Cysharp.Threading.Tasks.Progress` instead. This progress factory has two methods, `Create` and `CreateOnlyValueChanged`. `CreateOnlyValueChanged` calls only when the progress value has changed.
|
||||||
|
|
||||||
Implements IProgress interface to caller is more better, there is no allocation of lambda.
|
Implementing IProgress interface to caller is better as there is no lambda allocation.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
public class Foo : MonoBehaviour, IProgress<float>
|
public class Foo : MonoBehaviour, IProgress<float>
|
||||||
@@ -319,7 +413,7 @@ public class Foo : MonoBehaviour, IProgress<float>
|
|||||||
|
|
||||||
PlayerLoop
|
PlayerLoop
|
||||||
---
|
---
|
||||||
UniTask is run on custom [PlayerLoop](https://docs.unity3d.com/ScriptReference/LowLevel.PlayerLoop.html). UniTask's playerloop based method(such as `Delay`, `DelayFrame`, `asyncOperation.ToUniTask`, etc...) accepts this `PlayerLoopTiming`.
|
UniTask is run on a custom [PlayerLoop](https://docs.unity3d.com/ScriptReference/LowLevel.PlayerLoop.html). UniTask's playerloop based methods (such as `Delay`, `DelayFrame`, `asyncOperation.ToUniTask`, etc...) accept this `PlayerLoopTiming`.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
public enum PlayerLoopTiming
|
public enum PlayerLoopTiming
|
||||||
@@ -344,30 +438,35 @@ public enum PlayerLoopTiming
|
|||||||
|
|
||||||
PostLateUpdate = 12,
|
PostLateUpdate = 12,
|
||||||
LastPostLateUpdate = 13
|
LastPostLateUpdate = 13
|
||||||
|
|
||||||
|
#if UNITY_2020_2_OR_NEWER
|
||||||
|
TimeUpdate = 14,
|
||||||
|
LastTimeUpdate = 15,
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
It indicates when to run, you can check [PlayerLoopList.md](https://gist.github.com/neuecc/bc3a1cfd4d74501ad057e49efcd7bdae) to Unity's default playerloop and injected UniTask's custom loop.
|
It indicates when to run, you can check [PlayerLoopList.md](https://gist.github.com/neuecc/bc3a1cfd4d74501ad057e49efcd7bdae) to Unity's default playerloop and injected UniTask's custom loop.
|
||||||
|
|
||||||
`PlayerLoopTiming.Update` is similar as `yield return null` in coroutine, but it is called before Update(Update and uGUI events(button.onClick, etc...) are called on `ScriptRunBehaviourUpdate`, yield return null is called on `ScriptRunDelayedDynamicFrameRate`). `PlayerLoopTiming.FixedUpdate` is similar as `WaitForFixedUpdate`, `PlayerLoopTiming.LastPostLateUpdate` is similar as `WaitForEndOfFrame` in coroutine.
|
`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 similar to `WaitForEndOfFrame` in coroutine.
|
||||||
|
|
||||||
> `await UniTask.WaitForEndOfFrame()` is not equilavelnt 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(`ScreenCapture.CaptureScreenshotAsTexture`, `CommandBuffer`, etc) does not work correctly when replace to async/await. In that case, use a coroutine.
|
> `await UniTask.WaitForEndOfFrame()` 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(`ScreenCapture.CaptureScreenshotAsTexture`, `CommandBuffer`, etc) do not work correctly when replaced with async/await. In these cases, use a coroutine instead.
|
||||||
|
|
||||||
`yield return null` and `UniTask.Yield` is similar but different. `yield return null` always return next frame but `UniTask.Yield` return next called, that is, call `UniTask.Yield(PlayerLoopTiming.Update)` on `PreUpdate`, it returns same frame. `UniTask.NextFrame()` gurantees return next frame, this would be expected to behave exactly the same as `yield return null`.
|
`yield return null` and `UniTask.Yield` 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`.
|
||||||
|
|
||||||
> UniTask.Yield(without CancellationToken) is a special type, returns `YieldAwaitable` and run on YieldRunner. It is most lightweight and faster.
|
> UniTask.Yield(without CancellationToken) is a special type, returns `YieldAwaitable` and run on YieldRunner. It is most lightweight and fastest.
|
||||||
|
|
||||||
AsyncOperation is returned from native timing. For example, await `SceneManager.LoadSceneAsync` is returned from `EarlyUpdate.UpdatePreloading` and after called, loaded scene's `Start` called from `EarlyUpdate.ScriptRunDelayedStartupFrame`. Also `await UnityWebRequest` is returned from `EarlyUpdate.ExecuteMainThreadJobs`.
|
`AsyncOperation` is returned from native timing. For example, await `SceneManager.LoadSceneAsync` is returned from `EarlyUpdate.UpdatePreloading` and after being called, the loaded scene's `Start` is called from `EarlyUpdate.ScriptRunDelayedStartupFrame`. Also `await UnityWebRequest` is returned from `EarlyUpdate.ExecuteMainThreadJobs`.
|
||||||
|
|
||||||
In UniTask, await directly and `WithCancellation` use native timing, `ToUniTask` use specified timing. This is usually not a particular problem, but with `LoadSceneAsync`, causes different order of Start and continuation after await. so recommend not to use `LoadSceneAsync.ToUniTask`.
|
In UniTask, await directly uses native timing, `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 stacktrace, you can check where is running in playerloop.
|
In the stacktrace, you can check where it is running in playerloop.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
In default, UniTask's PlayerLoop is initialized at `[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]`.
|
By default, UniTask's PlayerLoop is initialized at `[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]`.
|
||||||
|
|
||||||
The order in which methods are called in BeforeSceneLoad is indeterminate, so if you want to use UniTask in other BeforeSceneLoad methods, you should try to initialize it before this.
|
The order in which methods are called in BeforeSceneLoad is nondeterministic, so if you want to use UniTask in other BeforeSceneLoad methods, you should try to initialize it before this.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// AfterAssembliesLoaded is called before BeforeSceneLoad
|
// AfterAssembliesLoaded is called before BeforeSceneLoad
|
||||||
@@ -379,9 +478,9 @@ public static void InitUniTaskLoop()
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
If you import Unity's `Entities` package, that reset custom player loop to default at `BeforeSceneLoad` and inject ECS's loop. When Unity call ECS's inject method after UniTask's initialize method, UniTask will no longer work.
|
If you import Unity's `Entities` package, that resets the custom player loop to default at `BeforeSceneLoad` and injects ECS's loop. When Unity calls ECS's inject method after UniTask's initialize method, UniTask will no longer work.
|
||||||
|
|
||||||
To solve this issue, you can re-initialize UniTask PlayerLoop after ECS initialized.
|
To solve this issue, you can re-initialize the UniTask PlayerLoop after ECS is initialized.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// Get ECS Loop.
|
// Get ECS Loop.
|
||||||
@@ -391,7 +490,7 @@ var playerLoop = ScriptBehaviourUpdateOrder.CurrentPlayerLoop;
|
|||||||
PlayerLoopHelper.Initialize(ref playerLoop);
|
PlayerLoopHelper.Initialize(ref playerLoop);
|
||||||
```
|
```
|
||||||
|
|
||||||
You can diagnostic UniTask's player loop is ready by `PlayerLoopHelper.IsInjectedUniTaskPlayerLoop()`. And also `PlayerLoopHelper.DumpCurrentPlayerLoop` shows current all playerloop to console.
|
You can diagnose whether UniTask's player loop is ready by calling `PlayerLoopHelper.IsInjectedUniTaskPlayerLoop()`. And also `PlayerLoopHelper.DumpCurrentPlayerLoop` logs all current playerloops to console.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
void Start()
|
void Start()
|
||||||
@@ -401,9 +500,40 @@ void Start()
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
You can optimize loop cost slightly by remove unuse PlayerLoopTiming injection. You can call `PlayerLoopHelper.Initialize(InjectPlayerLoopTimings)` on initialize.
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
var loop = PlayerLoop.GetCurrentPlayerLoop();
|
||||||
|
PlayerLoopHelper.Initialize(ref loop, InjectPlayerLoopTimings.Minimum); // minimum is Update | FixedUpdate | LastPostLateUpdate
|
||||||
|
```
|
||||||
|
|
||||||
|
`InjectPlayerLoopTimings` has three preset, `All` and `Standard`(All without last except LastPostLateUpdate), `Minimum`(`Update | FixedUpdate | LastPostLateUpdate`). Default is All and you can combine custom inject timings like `InjectPlayerLoopTimings.Update | InjectPlayerLoopTimings.FixedUpdate | InjectPlayerLoopTimings.PreLateUpdate`.
|
||||||
|
|
||||||
|
You can make error to use uninjected `PlayerLoopTiming` by [Microsoft.CodeAnalysis.BannedApiAnalyzers](https://github.com/dotnet/roslyn-analyzers/blob/master/src/Microsoft.CodeAnalysis.BannedApiAnalyzers/BannedApiAnalyzers.Help.md). For example, you can setup `BannedSymbols.txt` like this for `InjectPlayerLoopTimings.Minimum`.
|
||||||
|
|
||||||
|
```txt
|
||||||
|
F:Cysharp.Threading.Tasks.PlayerLoopTiming.Initialization; Isn't injected this PlayerLoop in this project.
|
||||||
|
F:Cysharp.Threading.Tasks.PlayerLoopTiming.LastInitialization; Isn't injected this PlayerLoop in this project.
|
||||||
|
F:Cysharp.Threading.Tasks.PlayerLoopTiming.EarlyUpdate; Isn't injected this PlayerLoop in this project.
|
||||||
|
F:Cysharp.Threading.Tasks.PlayerLoopTiming.LastEarlyUpdate; Isn't injected this PlayerLoop in this project.d
|
||||||
|
F:Cysharp.Threading.Tasks.PlayerLoopTiming.LastFixedUpdate; Isn't injected this PlayerLoop in this project.
|
||||||
|
F:Cysharp.Threading.Tasks.PlayerLoopTiming.PreUpdate; Isn't injected this PlayerLoop in this project.
|
||||||
|
F:Cysharp.Threading.Tasks.PlayerLoopTiming.LastPreUpdate; Isn't injected this PlayerLoop in this project.
|
||||||
|
F:Cysharp.Threading.Tasks.PlayerLoopTiming.LastUpdate; Isn't injected this PlayerLoop in this project.
|
||||||
|
F:Cysharp.Threading.Tasks.PlayerLoopTiming.PreLateUpdate; Isn't injected this PlayerLoop in this project.
|
||||||
|
F:Cysharp.Threading.Tasks.PlayerLoopTiming.LastPreLateUpdate; Isn't injected this PlayerLoop in this project.
|
||||||
|
F:Cysharp.Threading.Tasks.PlayerLoopTiming.PostLateUpdate; Isn't injected this PlayerLoop in this project.
|
||||||
|
F:Cysharp.Threading.Tasks.PlayerLoopTiming.TimeUpdate; Isn't injected this PlayerLoop in this project.
|
||||||
|
F:Cysharp.Threading.Tasks.PlayerLoopTiming.LastTimeUpdate; Isn't injected this PlayerLoop in this project.
|
||||||
|
```
|
||||||
|
|
||||||
|
You can configure `RS0030` severity to error.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
async void vs async UniTaskVoid
|
async void vs async UniTaskVoid
|
||||||
---
|
---
|
||||||
`async void` is a standard C# task system so does not run on UniTask systems. It is better not to use. `async UniTaskVoid` is a lightweight version of `async UniTask` because it does not have awaitable completion and report error immediately to `UniTaskScheduler.UnobservedTaskException`. If you don't require to await it(fire and forget), use `UniTaskVoid` is better. Unfortunately to dismiss warning, require to using with `Forget()`.
|
`async void` is a standard C# task system so it does not run on UniTask systems. It is better not to use it. `async UniTaskVoid` is a lightweight version of `async UniTask` because it does not have awaitable completion and reports errors immediately to `UniTaskScheduler.UnobservedTaskException`. If you don't require awaiting (fire and forget), using `UniTaskVoid` is better. Unfortunately to dismiss warning, you're required to call `Forget()`.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
public async UniTaskVoid FireAndForgetMethod()
|
public async UniTaskVoid FireAndForgetMethod()
|
||||||
@@ -418,7 +548,7 @@ public void Caller()
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Also UniTask have `Forget` method, it is similar with UniTaskVoid and same effects with it. However still UniTaskVoid is more efficient if completely do not use await。
|
Also UniTask has the `Forget` method, it is similar to `UniTaskVoid` and has the same effects. However `UniTaskVoid` is more efficient if you completely don't use `await`。
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
public async UniTask DoAsync()
|
public async UniTask DoAsync()
|
||||||
@@ -433,7 +563,7 @@ public void Caller()
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Using async lambda in register event, it is used `async void`. To avoid it, you can use `UniTask.Action` or `UniTask.UnityAction` that creates delegate via `async UniTaskVoid` lambda.
|
To use an async lambda registered to an event, don't use `async void`. Instead you can use `UniTask.Action` or `UniTask.UnityAction`, both of which create a delegate via `async UniTaskVoid` lambda.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
Action actEvent;
|
Action actEvent;
|
||||||
@@ -448,7 +578,7 @@ actEvent += UniTask.Action(async () => { await UniTask.Yield(); });
|
|||||||
unityEvent += UniTask.UnityAction(async () => { await UniTask.Yield(); });
|
unityEvent += UniTask.UnityAction(async () => { await UniTask.Yield(); });
|
||||||
```
|
```
|
||||||
|
|
||||||
`UniTaskVoid` can also use in MonoBehaviour's `Start` method.
|
`UniTaskVoid` can also be used in MonoBehaviour's `Start` method.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
class Sample : MonoBehaviour
|
class Sample : MonoBehaviour
|
||||||
@@ -462,7 +592,7 @@ class Sample : MonoBehaviour
|
|||||||
|
|
||||||
UniTaskTracker
|
UniTaskTracker
|
||||||
---
|
---
|
||||||
useful for check(leak) UniTasks. You can open tracker window in `Window -> UniTask Tracker`.
|
useful for checking (leaked) UniTasks. You can open tracker window in `Window -> UniTask Tracker`.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -472,15 +602,15 @@ useful for check(leak) UniTasks. You can open tracker window in `Window -> UniTa
|
|||||||
* Enable Tracking(Toggle) - Start to track async/await UniTask. Performance impact: low.
|
* Enable Tracking(Toggle) - Start to track async/await UniTask. Performance impact: low.
|
||||||
* Enable StackTrace(Toggle) - Capture StackTrace when task is started. Performance impact: high.
|
* Enable StackTrace(Toggle) - Capture StackTrace when task is started. Performance impact: high.
|
||||||
|
|
||||||
For debug use, enable tracking and capture stacktrace is useful but it it decline performance. Recommended usage is enable both to find task leak, and when done, finally disable both.
|
UniTaskTracker is intended for debugging use only as enabling tracking and capturing stacktraces is useful but has a heavy performance impact. Recommended usage is to enable both tracking and stacktraces to find task leaks and to disable them both when done.
|
||||||
|
|
||||||
External Assets
|
External Assets
|
||||||
---
|
---
|
||||||
In default, UniTask supports TextMeshPro(`BindTo(TMP_Text)` and `TMP_InputField` event extensions like standard uGUI `InputField`), DOTween(`Tween` as awaitable) and Addressables(`AsyncOperationHandle` and `AsyncOpereationHandle<T>` as awaitable).
|
By default, UniTask supports TextMeshPro(`BindTo(TMP_Text)` and `TMP_InputField` event extensions like standard uGUI `InputField`), DOTween(`Tween` as awaitable) and Addressables(`AsyncOperationHandle` and `AsyncOperationHandle<T>` as awaitable).
|
||||||
|
|
||||||
There are defined in separated asmdef 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 import there package from package manager. However DOTween support, require to `com.demigiant.dotween` import from [OpenUPM](https://openupm.com/packages/com.demigiant.dotween/) or 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, 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.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// sequential
|
// sequential
|
||||||
@@ -495,14 +625,14 @@ await UniTask.WhenAll(
|
|||||||
transform.DOScale(10, 3).WithCancellation(ct));
|
transform.DOScale(10, 3).WithCancellation(ct));
|
||||||
```
|
```
|
||||||
|
|
||||||
DOTween support's default behaviour(`await`, `WithCancellation`, `ToUniTask`) awaits tween is killed. It works both Complete(true/false) and Kill(true/false). But if you want to tween reuse(`SetAutoKill(false)`), it does not work you expected. Or, if you want to await for another timing, the following extension methods exist in Tween, `AwaitForComplete`, `AwaitForPause`, `AwaitForPlay`, `AwaitForRewind`, `AwaitForStepComplete`.
|
DOTween support's default behaviour(`await`, `WithCancellation`, `ToUniTask`) awaits tween is killed. It works on both Complete(true/false) and Kill(true/false). But if you want to reuse tweens (`SetAutoKill(false)`), it does not work as expected. If you want to await for another timing, the following extension methods exist in Tween, `AwaitForComplete`, `AwaitForPause`, `AwaitForPlay`, `AwaitForRewind`, `AwaitForStepComplete`.
|
||||||
|
|
||||||
AsyncEnumerable and Async LINQ
|
AsyncEnumerable and Async LINQ
|
||||||
---
|
---
|
||||||
Unity 2020.2.0a12 supports C# 8.0 so you can use `await foreach`. This is the new Update notation in async era.
|
Unity 2020.2 supports C# 8.0 so you can use `await foreach`. This is the new Update notation in the async era.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// Unity 2020.2.0a12, C# 8.0
|
// Unity 2020.2, C# 8.0
|
||||||
await foreach (var _ in UniTaskAsyncEnumerable.EveryUpdate(token))
|
await foreach (var _ in UniTaskAsyncEnumerable.EveryUpdate(token))
|
||||||
{
|
{
|
||||||
Debug.Log("Update() " + Time.frameCount);
|
Debug.Log("Update() " + Time.frameCount);
|
||||||
@@ -527,7 +657,7 @@ await okButton.OnClickAsAsyncEnumerable().Where((x, i) => i % 2 == 0).ForEachAsy
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
Fire and Forget style(for example, event handling), also you can use `Subscribe`.
|
Fire and Forget style(for example, event handling), you can also use `Subscribe`.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
okButton.OnClickAsAsyncEnumerable().Where((x, i) => i % 2 == 0).Subscribe(_ =>
|
okButton.OnClickAsAsyncEnumerable().Where((x, i) => i % 2 == 0).Subscribe(_ =>
|
||||||
@@ -551,7 +681,7 @@ SelectAwaitWithCancellation(Func<T, CancellationToken, UniTask<TR>> selector)
|
|||||||
|
|
||||||
If you want to use the `async` method inside the func, use the `***Await` or `***AwaitWithCancellation`.
|
If you want to use the `async` method inside the func, use the `***Await` or `***AwaitWithCancellation`.
|
||||||
|
|
||||||
How to create async iterator, C# 8.0 supports async iterator(`async yield return`) but it only allows `IAsyncEnumerable<T>` and of course requires C# 8.0. UniTask supports `UniTaskAsyncEnumerable.Create` method to create custom async iterator.
|
How to create an async iterator: C# 8.0 supports async iterator(`async yield return`) but it only allows `IAsyncEnumerable<T>` and of course requires C# 8.0. UniTask supports `UniTaskAsyncEnumerable.Create` method to create custom async iterator.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// IAsyncEnumerable, C# 8.0 version of async iterator. ( do not use this style, IAsyncEnumerable is not controled in UniTask).
|
// IAsyncEnumerable, C# 8.0 version of async iterator. ( do not use this style, IAsyncEnumerable is not controled in UniTask).
|
||||||
@@ -627,7 +757,7 @@ async UniTask TripleClick(CancellationToken token)
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
All MonoBehaviour message events can convert async-streams by `AsyncTriggers` that can enable by `using Cysharp.Threading.Tasks.Triggers;`.
|
All MonoBehaviour message events can convert async-streams by `AsyncTriggers` that can be enabled by `using Cysharp.Threading.Tasks.Triggers;`.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
using Cysharp.Threading.Tasks.Triggers;
|
using Cysharp.Threading.Tasks.Triggers;
|
||||||
@@ -643,7 +773,7 @@ async UniTaskVoid MonitorCollision()
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Similar as uGUI event, AsyncTrigger can get by `GetAsync***Trigger` and trigger it self is UniTaskAsyncEnumerable.
|
Similar to uGUI event, AsyncTrigger can be created using `GetAsync***Trigger` and triggers itself as UniTaskAsyncEnumerable.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// use await multiple times, get AsyncTriggerHandler is more efficient.
|
// use await multiple times, get AsyncTriggerHandler is more efficient.
|
||||||
@@ -660,7 +790,7 @@ await this.GetAsyncMoveTrigger().ForEachAsync(axisEventData =>
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
`AsyncReactiveProperty`, `AsyncReadOnlyReactiveProperty` is UniTask version of UniTask's ReactiveProperty. `BindTo` extension method of `IUniTaskAsyncEnumerable<T>` for binding asynchronous stream values to Unity components(Text/Selectable/TMP/Text).
|
`AsyncReactiveProperty`, `AsyncReadOnlyReactiveProperty` is UniTask's version of ReactiveProperty. `BindTo` extension method of `IUniTaskAsyncEnumerable<T>` for binding asynchronous stream values to Unity components(Text/Selectable/TMP/Text).
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
var rp = new AsyncReactiveProperty<int>(99);
|
var rp = new AsyncReactiveProperty<int>(99);
|
||||||
@@ -695,9 +825,9 @@ await button.OnClickAsAsyncEnumerable().ForEachAwaitAsync(async x =>
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
It is useful(prevent double-click) but not useful in sometimes.
|
It is useful (prevent double-click) but not useful sometimes.
|
||||||
|
|
||||||
Using `Queue()` method, which will also queue events during asynchronous processing.
|
Using the `Queue()` method will also queue events during asynchronous processing.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// queued message in asynchronous processing
|
// queued message in asynchronous processing
|
||||||
@@ -718,13 +848,13 @@ button.OnClickAsAsyncEnumerable().Subscribe(async x =>
|
|||||||
|
|
||||||
Channel
|
Channel
|
||||||
---
|
---
|
||||||
`Channel` is same as [System.Threading.Tasks.Channels](https://docs.microsoft.com/ja-jp/dotnet/api/system.threading.channels?view=netcore-3.1) that is similar as GoLang Channel.
|
`Channel` is the same as [System.Threading.Tasks.Channels](https://docs.microsoft.com/ja-jp/dotnet/api/system.threading.channels?view=netcore-3.1) which is similar to a GoLang Channel.
|
||||||
|
|
||||||
Currently only supports multiple-producer, single-consumer unbounded channel. It can create by `Channel.CreateSingleConsumerUnbounded<T>()`.
|
Currently it only supports multiple-producer, single-consumer unbounded channels. It can create by `Channel.CreateSingleConsumerUnbounded<T>()`.
|
||||||
|
|
||||||
For producer(`.Writer`), `TryWrite` to push value and `TryComplete` to complete channel. For consumer(`.Reader`), `TryRead`, `WaitToReadAsync`, `ReadAsync`, `Completion` and `ReadAllAsync` to read queued messages.
|
For producer(`.Writer`), use `TryWrite` to push value and `TryComplete` to complete channel. For consumer(`.Reader`), use `TryRead`, `WaitToReadAsync`, `ReadAsync`, `Completion` and `ReadAllAsync` to read queued messages.
|
||||||
|
|
||||||
`ReadAllAsync` returns `IUniTaskAsyncEnumerable<T>` so query LINQ operators. Reader only allows single-consumer but use `.Publish()` query operator to enable multicast message. For example, make pub/sub utility.
|
`ReadAllAsync` returns `IUniTaskAsyncEnumerable<T>` so query LINQ operators. Reader only allows single-consumer but uses `.Publish()` query operator to enable multicast message. For example, make pub/sub utility.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
public class AsyncMessageBroker<T> : IDisposable
|
public class AsyncMessageBroker<T> : IDisposable
|
||||||
@@ -761,7 +891,7 @@ public class AsyncMessageBroker<T> : IDisposable
|
|||||||
|
|
||||||
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 method.
|
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.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
[UnityTest]
|
[UnityTest]
|
||||||
@@ -784,31 +914,34 @@ public IEnumerator DelayIgnore() => UniTask.ToCoroutine(async () =>
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
UniTask itself's unit test is written by Unity Test Runner and [Cysharp/RuntimeUnitTestToolkit](https://github.com/Cysharp/RuntimeUnitTestToolkit) to check on CI and IL2CPP working.
|
UniTask's own unit tests are written using Unity Test Runner and [Cysharp/RuntimeUnitTestToolkit](https://github.com/Cysharp/RuntimeUnitTestToolkit) to integrate with CI and check if IL2CPP is working.
|
||||||
|
|
||||||
ThreadPool limitation
|
ThreadPool limitation
|
||||||
---
|
---
|
||||||
Most UniTask methods run in a single thread (PlayerLoop), but only `UniTask.Run` and `UniTask.SwitchToThreadPool` run on a thread pool. If you use a thread pool, it won't work with WebGL and so on.
|
Most UniTask methods run on a single thread (PlayerLoop), with only `UniTask.Run` and `UniTask.SwitchToThreadPool` running on a thread pool. If you use a thread pool, it won't work with WebGL and so on.
|
||||||
|
|
||||||
`UniTask.Run` will be deprecated in the future (marked with an Obsolete) and only `RunOnThreadPool` will be used. Also, if you use `UniTask.Run`, consider whether you can use `UniTask.Create` or `UniTask.Void`.
|
`UniTask.Run` will be deprecated in the future (marked with an Obsolete) and only `RunOnThreadPool` will be used. If you use `UniTask.Run`, consider whether you can use `UniTask.Create` or `UniTask.Void`.
|
||||||
|
|
||||||
IEnumerator.ToUniTask limitation
|
IEnumerator.ToUniTask limitation
|
||||||
---
|
---
|
||||||
You can convert coroutine(IEnumerator) to UniTask(or await directly) but has some limitations.
|
You can convert coroutine(IEnumerator) to UniTask(or await directly) but it has some limitations.
|
||||||
|
|
||||||
* `WaitForEndOfFrame`/`WaitForFixedUpdate` is not supported, used `yield return null` instead.
|
* `WaitForEndOfFrame`/`WaitForFixedUpdate`/`Coroutine` is not supported.
|
||||||
* Consuming loop timing is not same as StartCoroutine, it is used specified PlayerLoopTiming, and default's `PlayerLoopTiming.Update` is run before MonoBehaviour's Update and StartCoroutine's loop.
|
* Consuming loop timing is not the same as `StartCoroutine`, it uses the specified `PlayerLoopTiming` and the default `PlayerLoopTiming.Update` is run before MonoBehaviour's `Update` and `StartCoroutine`'s loop.
|
||||||
|
|
||||||
|
If you want fully compatible conversion from coroutine to async, use the `IEnumerator.ToUniTask(MonoBehaviour coroutineRunner)` overload. It executes StartCoroutine on an instance of the argument MonoBehaviour and waits for it to complete in UniTask.
|
||||||
|
|
||||||
For UnityEditor
|
For UnityEditor
|
||||||
---
|
---
|
||||||
UniTask can run on Unity Edtitor like Editor Coroutine. However, there are some limitations.
|
UniTask can run on Unity Editor like an Editor Coroutine. However, there are some limitations.
|
||||||
|
|
||||||
* Delay, DelayFrame is not work correctly because can not get deltaTime in editor. Return the result of the await immediately; you can use `DelayType.Realtime` to wait for the right time.
|
* UniTask.Delay's DelayType.DeltaTime, UnscaledDeltaTime do not work correctly because they can not get deltaTime in editor. Therefore run on EditMode, automatically change DelayType to `DelayType.Realtime` that wait for the right time.
|
||||||
* All PlayerLoopTiming run on timing, `EditorApplication.update`.
|
* All PlayerLoopTiming run on the timing `EditorApplication.update`.
|
||||||
|
* `-batchmode` with `-quit` does not work because does not run `EditorApplication.update`(quit on single frame) so should not use `-quit` and quit manually with `Environment.Exit(0)`.
|
||||||
|
|
||||||
Compare with Standard Task API
|
Compare with Standard Task API
|
||||||
---
|
---
|
||||||
UniTask has many standard Task-like APIs. This table shows what is the alternative apis.
|
UniTask has many standard Task-like APIs. This table shows what the alternative apis are.
|
||||||
|
|
||||||
Use standard type.
|
Use standard type.
|
||||||
|
|
||||||
@@ -854,7 +987,7 @@ Use UniTask type.
|
|||||||
|
|
||||||
Pooling Configuration
|
Pooling Configuration
|
||||||
---
|
---
|
||||||
UniTask is aggressively caching async promise object to achive zero allocation. In default, cache all promises but you can configure `TaskPool.SetMaxPoolSize` to your value, the value indicates cache size per type. `TaskPool.GetCacheSizeInfo` returns current cached object in pool.
|
UniTask aggressively caches async promise objects to achieve zero allocation (for technical details, see blog post [UniTask v2 — Zero Allocation async/await for Unity, with Asynchronous LINQ](https://medium.com/@neuecc/unitask-v2-zero-allocation-async-await-for-unity-with-asynchronous-linq-1aa9c96aa7dd)). By default, it caches all promises but you can configure `TaskPool.SetMaxPoolSize` to your value, the value indicates cache size per type. `TaskPool.GetCacheSizeInfo` returns currently cached objects in pool.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
foreach (var (type, size) in TaskPool.GetCacheSizeInfo())
|
foreach (var (type, size) in TaskPool.GetCacheSizeInfo())
|
||||||
@@ -865,17 +998,17 @@ foreach (var (type, size) in TaskPool.GetCacheSizeInfo())
|
|||||||
|
|
||||||
Allocation on Profiler
|
Allocation on Profiler
|
||||||
---
|
---
|
||||||
In UnityEditor profiler shows allocation of compiler generated AsyncStateMachine but it only occurs in debug(development) build. C# Compiler generate AsyncStateMachine as class on Debug build and as struct on Release build.
|
In UnityEditor the profiler shows allocation of compiler generated AsyncStateMachine but it only occurs in debug(development) build. C# Compiler generates AsyncStateMachine as class on Debug build and as struct on Release build.
|
||||||
|
|
||||||
After Unity 2020.1 supports Code Optimization option on UnityEditor(right, footer).
|
Unity supports Code Optimization option starting in 2020.1 (right, footer).
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
You can change C# compiler optimization to release, it removes AsyncStateMachine allocation. Andalso optimization option can set via `Compilation.CompilationPipeline-codeOptimization`, and `Compilation.CodeOptimization`.
|
You can change C# compiler optimization to release to remove AsyncStateMachine allocation in development builds. This optimization option can also be set via `Compilation.CompilationPipeline-codeOptimization`, and `Compilation.CodeOptimization`.
|
||||||
|
|
||||||
UniTaskSynchronizationContext
|
UniTaskSynchronizationContext
|
||||||
---
|
---
|
||||||
Unity's default SynchronizationContext(`UnitySynchronizationContext`) is poor implementation for performance. UniTask itself is bypass `SynchronizationContext`(and `ExecutionContext`) so does not use it but if exists in `async Task`, still used it. `UniTaskSynchronizationContext` is replacement of `UnitySynchronizationContext`, it is better for performance.
|
Unity's default SynchronizationContext(`UnitySynchronizationContext`) is a poor implementation for performance. UniTask bypasses `SynchronizationContext`(and `ExecutionContext`) so it does not use it but if exists in `async Task`, still used it. `UniTaskSynchronizationContext` is a replacement of `UnitySynchronizationContext` which is better for performance.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
public class SyncContextInjecter
|
public class SyncContextInjecter
|
||||||
@@ -888,19 +1021,19 @@ public class SyncContextInjecter
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
This is an optional choice and is not always recommended; `UniTaskSynchronizationContext` is less performance than `async UniTask` and is not a complete UniTask replacement. It also does not guarantee full behavioral compatibility with the `UnitySynchronizationContext`.
|
This is an optional choice and is not always recommended; `UniTaskSynchronizationContext` is less performant than `async UniTask` and is not a complete UniTask replacement. It also does not guarantee full behavioral compatibility with the `UnitySynchronizationContext`.
|
||||||
|
|
||||||
API References
|
API References
|
||||||
---
|
---
|
||||||
UniTask's API References is hosted at [cysharp.github.io/UniTask](https://cysharp.github.io/UniTask/api/Cysharp.Threading.Tasks.html) by [DocFX](https://dotnet.github.io/docfx/) and [Cysharp/DocfXTemplate](https://github.com/Cysharp/DocfxTemplate).
|
UniTask's API References are hosted at [cysharp.github.io/UniTask](https://cysharp.github.io/UniTask/api/Cysharp.Threading.Tasks.html) by [DocFX](https://dotnet.github.io/docfx/) and [Cysharp/DocfXTemplate](https://github.com/Cysharp/DocfxTemplate).
|
||||||
|
|
||||||
For example, UniTask's factory methods can see at [UniTask#methods](https://cysharp.github.io/UniTask/api/Cysharp.Threading.Tasks.UniTask.html#methods-1). UniTaskAsyncEnumerable's factory/extension methods can see at [UniTaskAsyncEnumerable#methods](https://cysharp.github.io/UniTask/api/Cysharp.Threading.Tasks.Linq.UniTaskAsyncEnumerable.html#methods-1).
|
For example, UniTask's factory methods can be seen at [UniTask#methods](https://cysharp.github.io/UniTask/api/Cysharp.Threading.Tasks.UniTask.html#methods-1). UniTaskAsyncEnumerable's factory/extension methods can be seen at [UniTaskAsyncEnumerable#methods](https://cysharp.github.io/UniTask/api/Cysharp.Threading.Tasks.Linq.UniTaskAsyncEnumerable.html#methods-1).
|
||||||
|
|
||||||
UPM Package
|
UPM Package
|
||||||
---
|
---
|
||||||
### Install via git URL
|
### Install via git URL
|
||||||
|
|
||||||
After Unity 2019.3.4f1, Unity 2020.1a21, that support path query parameter of git package. You can add `https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask` to Package Manager
|
Requires a version of unity that supports path query parameter for git packages (Unity >= 2019.3.4f1, Unity >= 2020.1a21). You can add `https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask` to Package Manager
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -908,7 +1041,7 @@ After Unity 2019.3.4f1, Unity 2020.1a21, that support path query parameter of gi
|
|||||||
|
|
||||||
or add `"com.cysharp.unitask": "https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask"` to `Packages/manifest.json`.
|
or add `"com.cysharp.unitask": "https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask"` to `Packages/manifest.json`.
|
||||||
|
|
||||||
If you want to set a target version, UniTask is using `*.*.*` release tag so you can specify a version like `#2.0.35`. For example `https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask#2.0.35`.
|
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
|
### Install via OpenUPM
|
||||||
|
|
||||||
@@ -924,11 +1057,11 @@ For .NET Core, use NuGet.
|
|||||||
|
|
||||||
> PM> Install-Package [UniTask](https://www.nuget.org/packages/UniTask)
|
> PM> Install-Package [UniTask](https://www.nuget.org/packages/UniTask)
|
||||||
|
|
||||||
UniTask of .NET Core version is a subset of Unity UniTask, removed PlayerLoop dependent methods.
|
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. `AysncLocal` also does not work because it ignores ExecutionContext.
|
||||||
|
|
||||||
If you use UniTask internally, but provide ValueTask as an external API, you can write 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)).
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
public class ZeroAllocAsyncAwaitInDotNetCore
|
public class ZeroAllocAsyncAwaitInDotNetCore
|
||||||
@@ -961,7 +1094,7 @@ public ValueTask TestAsync()
|
|||||||
|
|
||||||
.NET Core version is intended to allow users to use UniTask as an interface when sharing code with Unity (such as [Cysharp/MagicOnion](https://github.com/Cysharp/MagicOnion/)). .NET Core version of UniTask enables smooth code sharing.
|
.NET Core version is intended to allow users to use UniTask as an interface when sharing code with Unity (such as [Cysharp/MagicOnion](https://github.com/Cysharp/MagicOnion/)). .NET Core version of UniTask enables smooth code sharing.
|
||||||
|
|
||||||
Utility methods such as WhenAll which is equivalent to UniTask are provided as [Cysharp/ValueTaskSupplement](https://github.com/Cysharp/ValueTaskSupplement).
|
Utility methods such as WhenAll which are equivalent to UniTask are provided as [Cysharp/ValueTaskSupplement](https://github.com/Cysharp/ValueTaskSupplement).
|
||||||
|
|
||||||
License
|
License
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
..\UniTask\Assets\Plugins\UniTask\Runtime\UniTaskSynchronizationContext.cs;
|
..\UniTask\Assets\Plugins\UniTask\Runtime\UniTaskSynchronizationContext.cs;
|
||||||
..\UniTask\Assets\Plugins\UniTask\Runtime\CancellationTokenSourceExtensions.cs;
|
..\UniTask\Assets\Plugins\UniTask\Runtime\CancellationTokenSourceExtensions.cs;
|
||||||
..\UniTask\Assets\Plugins\UniTask\Runtime\EnumeratorAsyncExtensions.cs;
|
..\UniTask\Assets\Plugins\UniTask\Runtime\EnumeratorAsyncExtensions.cs;
|
||||||
|
..\UniTask\Assets\Plugins\UniTask\Runtime\TimeoutController.cs;
|
||||||
..\UniTask\Assets\Plugins\UniTask\Runtime\PlayerLoopHelper.cs;
|
..\UniTask\Assets\Plugins\UniTask\Runtime\PlayerLoopHelper.cs;
|
||||||
..\UniTask\Assets\Plugins\UniTask\Runtime\UniTask.Delay.cs;
|
..\UniTask\Assets\Plugins\UniTask\Runtime\UniTask.Delay.cs;
|
||||||
..\UniTask\Assets\Plugins\UniTask\Runtime\UniTask.Run.cs;
|
..\UniTask\Assets\Plugins\UniTask\Runtime\UniTask.Run.cs;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ namespace NetCoreTests
|
|||||||
{
|
{
|
||||||
CancellationTokenSource cts = new CancellationTokenSource();
|
CancellationTokenSource cts = new CancellationTokenSource();
|
||||||
|
|
||||||
var v = await UniTask.Run(() => 10).WithCancellation(cts.Token);
|
var v = await UniTask.Run(() => 10).AttachExternalCancellation(cts.Token);
|
||||||
|
|
||||||
v.Should().Be(10);
|
v.Should().Be(10);
|
||||||
}
|
}
|
||||||
@@ -30,7 +30,7 @@ namespace NetCoreTests
|
|||||||
{
|
{
|
||||||
await Task.Delay(TimeSpan.FromSeconds(1));
|
await Task.Delay(TimeSpan.FromSeconds(1));
|
||||||
return 10;
|
return 10;
|
||||||
}).WithCancellation(cts.Token);
|
}).AttachExternalCancellation(cts.Token);
|
||||||
|
|
||||||
cts.Cancel();
|
cts.Cancel();
|
||||||
|
|
||||||
|
|||||||
@@ -20,8 +20,9 @@ public static class EditorRunnerChecker
|
|||||||
{
|
{
|
||||||
Debug.Log("Start");
|
Debug.Log("Start");
|
||||||
|
|
||||||
var r = await UnityWebRequest.Get("https://bing.com/").SendWebRequest().ToUniTask();
|
//var r = await UnityWebRequest.Get("https://bing.com/").SendWebRequest().ToUniTask();
|
||||||
Debug.Log(r.downloadHandler.text.Substring(0, 100));
|
//Debug.Log(r.downloadHandler.text.Substring(0, 100));
|
||||||
|
await UniTask.Yield();
|
||||||
|
|
||||||
Debug.Log("End");
|
Debug.Log("End");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using System;
|
|||||||
|
|
||||||
namespace Cysharp.Threading.Tasks
|
namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
|
|
||||||
public static class CancellationTokenSourceExtensions
|
public static class CancellationTokenSourceExtensions
|
||||||
{
|
{
|
||||||
public static void CancelAfterSlim(this CancellationTokenSource cts, int millisecondsDelay, DelayType delayType = DelayType.DeltaTime, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update)
|
public static void CancelAfterSlim(this CancellationTokenSource cts, int millisecondsDelay, DelayType delayType = DelayType.DeltaTime, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update)
|
||||||
|
|||||||
@@ -32,6 +32,19 @@ namespace Cysharp.Threading.Tasks
|
|||||||
return new UniTask(EnumeratorPromise.Create(enumerator, timing, cancellationToken, out var token), token);
|
return new UniTask(EnumeratorPromise.Create(enumerator, timing, cancellationToken, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static UniTask ToUniTask(this IEnumerator enumerator, MonoBehaviour coroutineRunner)
|
||||||
|
{
|
||||||
|
var source = AutoResetUniTaskCompletionSource.Create();
|
||||||
|
coroutineRunner.StartCoroutine(Core(enumerator, coroutineRunner, source));
|
||||||
|
return source.Task;
|
||||||
|
}
|
||||||
|
|
||||||
|
static IEnumerator Core(IEnumerator inner, MonoBehaviour coroutineRunner, AutoResetUniTaskCompletionSource source)
|
||||||
|
{
|
||||||
|
yield return coroutineRunner.StartCoroutine(inner);
|
||||||
|
source.TrySetResult();
|
||||||
|
}
|
||||||
|
|
||||||
sealed class EnumeratorPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<EnumeratorPromise>
|
sealed class EnumeratorPromise : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<EnumeratorPromise>
|
||||||
{
|
{
|
||||||
static TaskPool<EnumeratorPromise> pool;
|
static TaskPool<EnumeratorPromise> pool;
|
||||||
@@ -74,11 +87,14 @@ namespace Cysharp.Threading.Tasks
|
|||||||
result.calledGetResult = false;
|
result.calledGetResult = false;
|
||||||
result.initialFrame = -1;
|
result.initialFrame = -1;
|
||||||
|
|
||||||
PlayerLoopHelper.AddAction(timing, result);
|
|
||||||
|
|
||||||
token = result.core.Version;
|
token = result.core.Version;
|
||||||
|
|
||||||
result.MoveNext(); // run immediately.
|
// run immediately.
|
||||||
|
if (result.MoveNext())
|
||||||
|
{
|
||||||
|
PlayerLoopHelper.AddAction(timing, result);
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,6 +188,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
core.Reset();
|
core.Reset();
|
||||||
innerEnumerator = default;
|
innerEnumerator = default;
|
||||||
cancellationToken = default;
|
cancellationToken = default;
|
||||||
|
|
||||||
return pool.TryPush(this);
|
return pool.TryPush(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,7 +232,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
yield return null;
|
goto WARN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (current is IEnumerator e3)
|
else if (current is IEnumerator e3)
|
||||||
@@ -228,9 +245,15 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// WaitForEndOfFrame, WaitForFixedUpdate, others.
|
goto WARN;
|
||||||
yield return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
|
||||||
|
WARN:
|
||||||
|
// WaitForEndOfFrame, WaitForFixedUpdate, others.
|
||||||
|
UnityEngine.Debug.LogWarning($"yield {current.GetType().Name} is not supported on await IEnumerator or IEnumerator.ToUniTask(), please use ToUniTask(MonoBehaviour coroutineRunner) instead.");
|
||||||
|
yield return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,5 +284,4 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,6 +223,17 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
void OnCompleteCallbackDelegate()
|
void OnCompleteCallbackDelegate()
|
||||||
{
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
if (this.cancelBehaviour == TweenCancelBehaviour.KillAndCancelAwait
|
||||||
|
|| this.cancelBehaviour == TweenCancelBehaviour.KillWithCompleteCallbackAndCancelAwait
|
||||||
|
|| this.cancelBehaviour == TweenCancelBehaviour.CompleteAndCancelAwait
|
||||||
|
|| this.cancelBehaviour == TweenCancelBehaviour.CompleteWithSeqeunceCallbackAndCancelAwait
|
||||||
|
|| this.cancelBehaviour == TweenCancelBehaviour.CancelAwait)
|
||||||
|
{
|
||||||
|
canceled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (canceled)
|
if (canceled)
|
||||||
{
|
{
|
||||||
core.TrySetCanceled(cancellationToken);
|
core.TrySetCanceled(cancellationToken);
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ namespace Cysharp.Threading.Tasks.Internal
|
|||||||
|
|
||||||
readonly PlayerLoopTiming timing;
|
readonly PlayerLoopTiming timing;
|
||||||
|
|
||||||
SpinLock gate = new SpinLock();
|
SpinLock gate = new SpinLock(false);
|
||||||
bool dequing = false;
|
bool dequing = false;
|
||||||
|
|
||||||
int actionListCount = 0;
|
int actionListCount = 0;
|
||||||
@@ -132,6 +132,14 @@ namespace Cysharp.Threading.Tasks.Internal
|
|||||||
case PlayerLoopTiming.LastPostLateUpdate:
|
case PlayerLoopTiming.LastPostLateUpdate:
|
||||||
LastPostLateUpdate();
|
LastPostLateUpdate();
|
||||||
break;
|
break;
|
||||||
|
#if UNITY_2020_2_OR_NEWER
|
||||||
|
case PlayerLoopTiming.TimeUpdate:
|
||||||
|
TimeUpdate();
|
||||||
|
break;
|
||||||
|
case PlayerLoopTiming.LastTimeUpdate:
|
||||||
|
LastTimeUpdate();
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -154,6 +162,10 @@ namespace Cysharp.Threading.Tasks.Internal
|
|||||||
void LastPreLateUpdate() => RunCore();
|
void LastPreLateUpdate() => RunCore();
|
||||||
void PostLateUpdate() => RunCore();
|
void PostLateUpdate() => RunCore();
|
||||||
void LastPostLateUpdate() => RunCore();
|
void LastPostLateUpdate() => RunCore();
|
||||||
|
#if UNITY_2020_2_OR_NEWER
|
||||||
|
void TimeUpdate() => RunCore();
|
||||||
|
void LastTimeUpdate() => RunCore();
|
||||||
|
#endif
|
||||||
|
|
||||||
[System.Diagnostics.DebuggerHidden]
|
[System.Diagnostics.DebuggerHidden]
|
||||||
void RunCore()
|
void RunCore()
|
||||||
|
|||||||
@@ -118,6 +118,14 @@ namespace Cysharp.Threading.Tasks.Internal
|
|||||||
case PlayerLoopTiming.LastPostLateUpdate:
|
case PlayerLoopTiming.LastPostLateUpdate:
|
||||||
LastPostLateUpdate();
|
LastPostLateUpdate();
|
||||||
break;
|
break;
|
||||||
|
#if UNITY_2020_2_OR_NEWER
|
||||||
|
case PlayerLoopTiming.TimeUpdate:
|
||||||
|
TimeUpdate();
|
||||||
|
break;
|
||||||
|
case PlayerLoopTiming.LastTimeUpdate:
|
||||||
|
LastTimeUpdate();
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -140,6 +148,10 @@ namespace Cysharp.Threading.Tasks.Internal
|
|||||||
void LastPreLateUpdate() => RunCore();
|
void LastPreLateUpdate() => RunCore();
|
||||||
void PostLateUpdate() => RunCore();
|
void PostLateUpdate() => RunCore();
|
||||||
void LastPostLateUpdate() => RunCore();
|
void LastPostLateUpdate() => RunCore();
|
||||||
|
#if UNITY_2020_2_OR_NEWER
|
||||||
|
void TimeUpdate() => RunCore();
|
||||||
|
void LastTimeUpdate() => RunCore();
|
||||||
|
#endif
|
||||||
|
|
||||||
[System.Diagnostics.DebuggerHidden]
|
[System.Diagnostics.DebuggerHidden]
|
||||||
void RunCore()
|
void RunCore()
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ using UnityEngine.Networking;
|
|||||||
|
|
||||||
namespace Cysharp.Threading.Tasks.Internal
|
namespace Cysharp.Threading.Tasks.Internal
|
||||||
{
|
{
|
||||||
|
#if ENABLE_UNITYWEBREQUEST && (!UNITY_2019_1_OR_NEWER || UNITASK_WEBREQUEST_SUPPORT)
|
||||||
|
|
||||||
internal static class UnityWebRequestResultExtensions
|
internal static class UnityWebRequestResultExtensions
|
||||||
{
|
{
|
||||||
public static bool IsError(this UnityWebRequest unityWebRequest)
|
public static bool IsError(this UnityWebRequest unityWebRequest)
|
||||||
@@ -21,4 +23,6 @@ namespace Cysharp.Threading.Tasks.Internal
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
@@ -18,6 +18,8 @@ namespace Cysharp.Threading.Tasks.Internal
|
|||||||
|
|
||||||
public TimeSpan Elapsed => TimeSpan.FromTicks(this.ElapsedTicks);
|
public TimeSpan Elapsed => TimeSpan.FromTicks(this.ElapsedTicks);
|
||||||
|
|
||||||
|
public bool IsInvalid => startTimestamp == 0;
|
||||||
|
|
||||||
public long ElapsedTicks
|
public long ElapsedTicks
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
|||||||
@@ -8,8 +8,10 @@ using System.Threading;
|
|||||||
|
|
||||||
#if UNITY_2019_3_OR_NEWER
|
#if UNITY_2019_3_OR_NEWER
|
||||||
using UnityEngine.LowLevel;
|
using UnityEngine.LowLevel;
|
||||||
|
using PlayerLoopType = UnityEngine.PlayerLoop;
|
||||||
#else
|
#else
|
||||||
using UnityEngine.Experimental.LowLevel;
|
using UnityEngine.Experimental.LowLevel;
|
||||||
|
using PlayerLoopType = UnityEngine.Experimental.PlayerLoop;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
@@ -57,6 +59,13 @@ namespace Cysharp.Threading.Tasks
|
|||||||
public struct UniTaskLoopRunnerLastYieldUpdate { };
|
public struct UniTaskLoopRunnerLastYieldUpdate { };
|
||||||
public struct UniTaskLoopRunnerLastYieldPreLateUpdate { };
|
public struct UniTaskLoopRunnerLastYieldPreLateUpdate { };
|
||||||
public struct UniTaskLoopRunnerLastYieldPostLateUpdate { };
|
public struct UniTaskLoopRunnerLastYieldPostLateUpdate { };
|
||||||
|
|
||||||
|
#if UNITY_2020_2_OR_NEWER
|
||||||
|
public struct UniTaskLoopRunnerTimeUpdate { };
|
||||||
|
public struct UniTaskLoopRunnerLastTimeUpdate { };
|
||||||
|
public struct UniTaskLoopRunnerYieldTimeUpdate { };
|
||||||
|
public struct UniTaskLoopRunnerLastYieldTimeUpdate { };
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum PlayerLoopTiming
|
public enum PlayerLoopTiming
|
||||||
@@ -80,7 +89,86 @@ namespace Cysharp.Threading.Tasks
|
|||||||
LastPreLateUpdate = 11,
|
LastPreLateUpdate = 11,
|
||||||
|
|
||||||
PostLateUpdate = 12,
|
PostLateUpdate = 12,
|
||||||
LastPostLateUpdate = 13
|
LastPostLateUpdate = 13,
|
||||||
|
|
||||||
|
#if UNITY_2020_2_OR_NEWER
|
||||||
|
// Unity 2020.2 added TimeUpdate https://docs.unity3d.com/2020.2/Documentation/ScriptReference/PlayerLoop.TimeUpdate.html
|
||||||
|
TimeUpdate = 14,
|
||||||
|
LastTimeUpdate = 15,
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
public enum InjectPlayerLoopTimings
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Preset: All loops(default).
|
||||||
|
/// </summary>
|
||||||
|
All =
|
||||||
|
Initialization | LastInitialization |
|
||||||
|
EarlyUpdate | LastEarlyUpdate |
|
||||||
|
FixedUpdate | LastFixedUpdate |
|
||||||
|
PreUpdate | LastPreUpdate |
|
||||||
|
Update | LastUpdate |
|
||||||
|
PreLateUpdate | LastPreLateUpdate |
|
||||||
|
PostLateUpdate | LastPostLateUpdate
|
||||||
|
#if UNITY_2020_2_OR_NEWER
|
||||||
|
| TimeUpdate | LastTimeUpdate,
|
||||||
|
#else
|
||||||
|
,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Preset: All without last except LastPostLateUpdate.
|
||||||
|
/// </summary>
|
||||||
|
Standard =
|
||||||
|
Initialization |
|
||||||
|
EarlyUpdate |
|
||||||
|
FixedUpdate |
|
||||||
|
PreUpdate |
|
||||||
|
Update |
|
||||||
|
PreLateUpdate |
|
||||||
|
PostLateUpdate | LastPostLateUpdate
|
||||||
|
#if UNITY_2020_2_OR_NEWER
|
||||||
|
| TimeUpdate
|
||||||
|
#endif
|
||||||
|
,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Preset: Minimum pattern, Update | FixedUpdate | LastPostLateUpdate
|
||||||
|
/// </summary>
|
||||||
|
Minimum =
|
||||||
|
Update | FixedUpdate | LastPostLateUpdate,
|
||||||
|
|
||||||
|
// PlayerLoopTiming
|
||||||
|
|
||||||
|
Initialization = 1,
|
||||||
|
LastInitialization = 2,
|
||||||
|
|
||||||
|
EarlyUpdate = 4,
|
||||||
|
LastEarlyUpdate = 8,
|
||||||
|
|
||||||
|
FixedUpdate = 16,
|
||||||
|
LastFixedUpdate = 32,
|
||||||
|
|
||||||
|
PreUpdate = 64,
|
||||||
|
LastPreUpdate = 128,
|
||||||
|
|
||||||
|
Update = 256,
|
||||||
|
LastUpdate = 512,
|
||||||
|
|
||||||
|
PreLateUpdate = 1024,
|
||||||
|
LastPreLateUpdate = 2048,
|
||||||
|
|
||||||
|
PostLateUpdate = 4096,
|
||||||
|
LastPostLateUpdate = 8192
|
||||||
|
|
||||||
|
#if UNITY_2020_2_OR_NEWER
|
||||||
|
,
|
||||||
|
// Unity 2020.2 added TimeUpdate https://docs.unity3d.com/2020.2/Documentation/ScriptReference/PlayerLoop.TimeUpdate.html
|
||||||
|
TimeUpdate = 16384,
|
||||||
|
LastTimeUpdate = 32768
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IPlayerLoopItem
|
public interface IPlayerLoopItem
|
||||||
@@ -90,6 +178,9 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
public static class PlayerLoopHelper
|
public static class PlayerLoopHelper
|
||||||
{
|
{
|
||||||
|
static readonly ContinuationQueue ThrowMarkerContinuationQueue = new ContinuationQueue(PlayerLoopTiming.Initialization);
|
||||||
|
static readonly PlayerLoopRunner ThrowMarkerPlayerLoopRunner = new PlayerLoopRunner(PlayerLoopTiming.Initialization);
|
||||||
|
|
||||||
public static SynchronizationContext UnitySynchronizationContext => unitySynchronizationContetext;
|
public static SynchronizationContext UnitySynchronizationContext => unitySynchronizationContetext;
|
||||||
public static int MainThreadId => mainThreadId;
|
public static int MainThreadId => mainThreadId;
|
||||||
internal static string ApplicationDataPath => applicationDataPath;
|
internal static string ApplicationDataPath => applicationDataPath;
|
||||||
@@ -101,10 +192,11 @@ namespace Cysharp.Threading.Tasks
|
|||||||
static SynchronizationContext unitySynchronizationContetext;
|
static SynchronizationContext unitySynchronizationContetext;
|
||||||
static ContinuationQueue[] yielders;
|
static ContinuationQueue[] yielders;
|
||||||
static PlayerLoopRunner[] runners;
|
static PlayerLoopRunner[] runners;
|
||||||
|
internal static bool IsEditorApplicationQuitting { get; private set; }
|
||||||
static PlayerLoopSystem[] InsertRunner(PlayerLoopSystem loopSystem,
|
static PlayerLoopSystem[] InsertRunner(PlayerLoopSystem loopSystem,
|
||||||
Type loopRunnerYieldType, ContinuationQueue cq, Type lastLoopRunnerYieldType, ContinuationQueue lastCq,
|
bool injectOnFirst,
|
||||||
Type loopRunnerType, PlayerLoopRunner runner, Type lastLoopRunnerType, PlayerLoopRunner lastRunner)
|
Type loopRunnerYieldType, ContinuationQueue cq,
|
||||||
|
Type loopRunnerType, PlayerLoopRunner runner)
|
||||||
{
|
{
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
@@ -112,28 +204,19 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
if (state == PlayModeStateChange.EnteredEditMode || state == PlayModeStateChange.ExitingEditMode)
|
if (state == PlayModeStateChange.EnteredEditMode || state == PlayModeStateChange.ExitingEditMode)
|
||||||
{
|
{
|
||||||
|
IsEditorApplicationQuitting = true;
|
||||||
// run rest action before clear.
|
// run rest action before clear.
|
||||||
if (runner != null)
|
if (runner != null)
|
||||||
{
|
{
|
||||||
runner.Run();
|
runner.Run();
|
||||||
runner.Clear();
|
runner.Clear();
|
||||||
}
|
}
|
||||||
if (lastRunner != null)
|
|
||||||
{
|
|
||||||
lastRunner.Run();
|
|
||||||
lastRunner.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cq != null)
|
if (cq != null)
|
||||||
{
|
{
|
||||||
cq.Run();
|
cq.Run();
|
||||||
cq.Clear();
|
cq.Clear();
|
||||||
}
|
}
|
||||||
if (lastCq != null)
|
IsEditorApplicationQuitting = false;
|
||||||
{
|
|
||||||
lastCq.Run();
|
|
||||||
lastCq.Clear();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
@@ -144,40 +227,38 @@ namespace Cysharp.Threading.Tasks
|
|||||||
updateDelegate = cq.Run
|
updateDelegate = cq.Run
|
||||||
};
|
};
|
||||||
|
|
||||||
var lastYieldLoop = new PlayerLoopSystem
|
|
||||||
{
|
|
||||||
type = lastLoopRunnerYieldType,
|
|
||||||
updateDelegate = lastCq.Run
|
|
||||||
};
|
|
||||||
|
|
||||||
var runnerLoop = new PlayerLoopSystem
|
var runnerLoop = new PlayerLoopSystem
|
||||||
{
|
{
|
||||||
type = loopRunnerType,
|
type = loopRunnerType,
|
||||||
updateDelegate = runner.Run
|
updateDelegate = runner.Run
|
||||||
};
|
};
|
||||||
|
|
||||||
var lastRunnerLoop = new PlayerLoopSystem
|
|
||||||
{
|
|
||||||
type = lastLoopRunnerType,
|
|
||||||
updateDelegate = lastRunner.Run
|
|
||||||
};
|
|
||||||
|
|
||||||
// Remove items from previous initializations.
|
// Remove items from previous initializations.
|
||||||
var source = loopSystem.subSystemList
|
var source = RemoveRunner(loopSystem, loopRunnerYieldType, loopRunnerType);
|
||||||
.Where(ls => ls.type != loopRunnerYieldType && ls.type != loopRunnerType && ls.type != lastLoopRunnerYieldType && ls.type != lastLoopRunnerType)
|
var dest = new PlayerLoopSystem[source.Length + 2];
|
||||||
.ToArray();
|
|
||||||
|
|
||||||
var dest = new PlayerLoopSystem[source.Length + 4];
|
Array.Copy(source, 0, dest, injectOnFirst ? 2 : 0, source.Length);
|
||||||
|
if (injectOnFirst)
|
||||||
Array.Copy(source, 0, dest, 2, source.Length);
|
{
|
||||||
dest[0] = yieldLoop;
|
dest[0] = yieldLoop;
|
||||||
dest[1] = runnerLoop;
|
dest[1] = runnerLoop;
|
||||||
dest[dest.Length - 2] = lastYieldLoop;
|
}
|
||||||
dest[dest.Length - 1] = lastRunnerLoop;
|
else
|
||||||
|
{
|
||||||
|
dest[dest.Length - 2] = yieldLoop;
|
||||||
|
dest[dest.Length - 1] = runnerLoop;
|
||||||
|
}
|
||||||
|
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PlayerLoopSystem[] RemoveRunner(PlayerLoopSystem loopSystem, Type loopRunnerYieldType, Type loopRunnerType)
|
||||||
|
{
|
||||||
|
return loopSystem.subSystemList
|
||||||
|
.Where(ls => ls.type != loopRunnerYieldType && ls.type != loopRunnerType)
|
||||||
|
.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
static PlayerLoopSystem[] InsertUniTaskSynchronizationContext(PlayerLoopSystem loopSystem)
|
static PlayerLoopSystem[] InsertUniTaskSynchronizationContext(PlayerLoopSystem loopSystem)
|
||||||
{
|
{
|
||||||
var loop = new PlayerLoopSystem
|
var loop = new PlayerLoopSystem
|
||||||
@@ -281,51 +362,124 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public static void Initialize(ref PlayerLoopSystem playerLoop)
|
private static int FindLoopSystemIndex(PlayerLoopSystem[] playerLoopList, Type systemType)
|
||||||
{
|
{
|
||||||
|
for (int i = 0; i < playerLoopList.Length; i++)
|
||||||
|
{
|
||||||
|
if (playerLoopList[i].type == systemType)
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Exception("Target PlayerLoopSystem does not found. Type:" + systemType.FullName);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void InsertLoop(PlayerLoopSystem[] copyList, InjectPlayerLoopTimings injectTimings, Type loopType, InjectPlayerLoopTimings targetTimings,
|
||||||
|
int index, bool injectOnFirst, Type loopRunnerYieldType, Type loopRunnerType, PlayerLoopTiming playerLoopTiming)
|
||||||
|
{
|
||||||
|
var i = FindLoopSystemIndex(copyList, loopType);
|
||||||
|
if ((injectTimings & targetTimings) == targetTimings)
|
||||||
|
{
|
||||||
|
copyList[i].subSystemList = InsertRunner(copyList[i], injectOnFirst,
|
||||||
|
loopRunnerYieldType, yielders[index] = new ContinuationQueue(playerLoopTiming),
|
||||||
|
loopRunnerType, runners[index] = new PlayerLoopRunner(playerLoopTiming));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
copyList[i].subSystemList = RemoveRunner(copyList[i], loopRunnerYieldType, loopRunnerType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Initialize(ref PlayerLoopSystem playerLoop, InjectPlayerLoopTimings injectTimings = InjectPlayerLoopTimings.All)
|
||||||
|
{
|
||||||
|
#if UNITY_2020_2_OR_NEWER
|
||||||
|
yielders = new ContinuationQueue[16];
|
||||||
|
runners = new PlayerLoopRunner[16];
|
||||||
|
#else
|
||||||
yielders = new ContinuationQueue[14];
|
yielders = new ContinuationQueue[14];
|
||||||
runners = new PlayerLoopRunner[14];
|
runners = new PlayerLoopRunner[14];
|
||||||
|
#endif
|
||||||
|
|
||||||
var copyList = playerLoop.subSystemList.ToArray();
|
var copyList = playerLoop.subSystemList.ToArray();
|
||||||
|
|
||||||
// Initialization
|
// Initialization
|
||||||
copyList[0].subSystemList = InsertRunner(copyList[0], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldInitialization), yielders[0] = new ContinuationQueue(PlayerLoopTiming.Initialization),
|
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.Initialization),
|
||||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldInitialization), yielders[1] = new ContinuationQueue(PlayerLoopTiming.LastInitialization),
|
InjectPlayerLoopTimings.Initialization, 0, true,
|
||||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerInitialization), runners[0] = new PlayerLoopRunner(PlayerLoopTiming.Initialization),
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldInitialization), typeof(UniTaskLoopRunners.UniTaskLoopRunnerInitialization), PlayerLoopTiming.Initialization);
|
||||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastInitialization), runners[1] = new PlayerLoopRunner(PlayerLoopTiming.LastInitialization));
|
|
||||||
|
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.Initialization),
|
||||||
|
InjectPlayerLoopTimings.LastInitialization, 1, false,
|
||||||
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldInitialization), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastInitialization), PlayerLoopTiming.LastInitialization);
|
||||||
|
|
||||||
// EarlyUpdate
|
// EarlyUpdate
|
||||||
copyList[1].subSystemList = InsertRunner(copyList[1], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldEarlyUpdate), yielders[2] = new ContinuationQueue(PlayerLoopTiming.EarlyUpdate),
|
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.EarlyUpdate),
|
||||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldEarlyUpdate), yielders[3] = new ContinuationQueue(PlayerLoopTiming.LastEarlyUpdate),
|
InjectPlayerLoopTimings.EarlyUpdate, 2, true,
|
||||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerEarlyUpdate), runners[2] = new PlayerLoopRunner(PlayerLoopTiming.EarlyUpdate),
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldEarlyUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerEarlyUpdate), PlayerLoopTiming.EarlyUpdate);
|
||||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastEarlyUpdate), runners[3] = new PlayerLoopRunner(PlayerLoopTiming.LastEarlyUpdate));
|
|
||||||
|
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.EarlyUpdate),
|
||||||
|
InjectPlayerLoopTimings.LastEarlyUpdate, 3, false,
|
||||||
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldEarlyUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastEarlyUpdate), PlayerLoopTiming.LastEarlyUpdate);
|
||||||
|
|
||||||
// FixedUpdate
|
// FixedUpdate
|
||||||
copyList[2].subSystemList = InsertRunner(copyList[2], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldFixedUpdate), yielders[4] = new ContinuationQueue(PlayerLoopTiming.FixedUpdate),
|
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.FixedUpdate),
|
||||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldFixedUpdate), yielders[5] = new ContinuationQueue(PlayerLoopTiming.LastFixedUpdate),
|
InjectPlayerLoopTimings.FixedUpdate, 4, true,
|
||||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerFixedUpdate), runners[4] = new PlayerLoopRunner(PlayerLoopTiming.FixedUpdate),
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldFixedUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerFixedUpdate), PlayerLoopTiming.FixedUpdate);
|
||||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastFixedUpdate), runners[5] = new PlayerLoopRunner(PlayerLoopTiming.LastFixedUpdate));
|
|
||||||
|
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.FixedUpdate),
|
||||||
|
InjectPlayerLoopTimings.LastFixedUpdate, 5, false,
|
||||||
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldFixedUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastFixedUpdate), PlayerLoopTiming.LastFixedUpdate);
|
||||||
|
|
||||||
// PreUpdate
|
// PreUpdate
|
||||||
copyList[3].subSystemList = InsertRunner(copyList[3], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldPreUpdate), yielders[6] = new ContinuationQueue(PlayerLoopTiming.PreUpdate),
|
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.PreUpdate),
|
||||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldPreUpdate), yielders[7] = new ContinuationQueue(PlayerLoopTiming.LastPreUpdate),
|
InjectPlayerLoopTimings.PreUpdate, 6, true,
|
||||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerPreUpdate), runners[6] = new PlayerLoopRunner(PlayerLoopTiming.PreUpdate),
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldPreUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerPreUpdate), PlayerLoopTiming.PreUpdate);
|
||||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastPreUpdate), runners[7] = new PlayerLoopRunner(PlayerLoopTiming.LastPreUpdate));
|
|
||||||
|
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.PreUpdate),
|
||||||
|
InjectPlayerLoopTimings.LastPreUpdate, 7, false,
|
||||||
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldPreUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastPreUpdate), PlayerLoopTiming.LastPreUpdate);
|
||||||
|
|
||||||
// Update
|
// Update
|
||||||
copyList[4].subSystemList = InsertRunner(copyList[4], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldUpdate), yielders[8] = new ContinuationQueue(PlayerLoopTiming.Update),
|
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.Update),
|
||||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldUpdate), yielders[9] = new ContinuationQueue(PlayerLoopTiming.LastUpdate),
|
InjectPlayerLoopTimings.Update, 8, true,
|
||||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerUpdate), runners[8] = new PlayerLoopRunner(PlayerLoopTiming.Update),
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerUpdate), PlayerLoopTiming.Update);
|
||||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastUpdate), runners[9] = new PlayerLoopRunner(PlayerLoopTiming.LastUpdate));
|
|
||||||
|
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.Update),
|
||||||
|
InjectPlayerLoopTimings.LastUpdate, 9, false,
|
||||||
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastUpdate), PlayerLoopTiming.LastUpdate);
|
||||||
|
|
||||||
// PreLateUpdate
|
// PreLateUpdate
|
||||||
copyList[5].subSystemList = InsertRunner(copyList[5], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldPreLateUpdate), yielders[10] = new ContinuationQueue(PlayerLoopTiming.PreLateUpdate),
|
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.PreLateUpdate),
|
||||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldPreLateUpdate), yielders[11] = new ContinuationQueue(PlayerLoopTiming.LastPreLateUpdate),
|
InjectPlayerLoopTimings.PreLateUpdate, 10, true,
|
||||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerPreLateUpdate), runners[10] = new PlayerLoopRunner(PlayerLoopTiming.PreLateUpdate),
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldPreLateUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerPreLateUpdate), PlayerLoopTiming.PreLateUpdate);
|
||||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastPreLateUpdate), runners[11] = new PlayerLoopRunner(PlayerLoopTiming.LastPreLateUpdate));
|
|
||||||
|
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.PreLateUpdate),
|
||||||
|
InjectPlayerLoopTimings.LastPreLateUpdate, 11, false,
|
||||||
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldPreLateUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastPreLateUpdate), PlayerLoopTiming.LastPreLateUpdate);
|
||||||
|
|
||||||
// PostLateUpdate
|
// PostLateUpdate
|
||||||
copyList[6].subSystemList = InsertRunner(copyList[6], typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldPostLateUpdate), yielders[12] = new ContinuationQueue(PlayerLoopTiming.PostLateUpdate),
|
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.PostLateUpdate),
|
||||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldPostLateUpdate), yielders[13] = new ContinuationQueue(PlayerLoopTiming.LastPostLateUpdate),
|
InjectPlayerLoopTimings.PostLateUpdate, 12, true,
|
||||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerPostLateUpdate), runners[12] = new PlayerLoopRunner(PlayerLoopTiming.PostLateUpdate),
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldPostLateUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerPostLateUpdate), PlayerLoopTiming.PostLateUpdate);
|
||||||
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastPostLateUpdate), runners[13] = new PlayerLoopRunner(PlayerLoopTiming.LastPostLateUpdate));
|
|
||||||
|
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.PostLateUpdate),
|
||||||
|
InjectPlayerLoopTimings.LastPostLateUpdate, 13, false,
|
||||||
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldPostLateUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastPostLateUpdate), PlayerLoopTiming.LastPostLateUpdate);
|
||||||
|
|
||||||
|
#if UNITY_2020_2_OR_NEWER
|
||||||
|
// TimeUpdate
|
||||||
|
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.TimeUpdate),
|
||||||
|
InjectPlayerLoopTimings.TimeUpdate, 14, true,
|
||||||
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerYieldTimeUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerTimeUpdate), PlayerLoopTiming.TimeUpdate);
|
||||||
|
|
||||||
|
InsertLoop(copyList, injectTimings, typeof(PlayerLoopType.TimeUpdate),
|
||||||
|
InjectPlayerLoopTimings.LastTimeUpdate, 15, false,
|
||||||
|
typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastYieldTimeUpdate), typeof(UniTaskLoopRunners.UniTaskLoopRunnerLastTimeUpdate), PlayerLoopTiming.LastTimeUpdate);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Insert UniTaskSynchronizationContext to Update loop
|
// Insert UniTaskSynchronizationContext to Update loop
|
||||||
copyList[4].subSystemList = InsertUniTaskSynchronizationContext(copyList[4]);
|
var i = FindLoopSystemIndex(copyList, typeof(PlayerLoopType.Update));
|
||||||
|
copyList[i].subSystemList = InsertUniTaskSynchronizationContext(copyList[i]);
|
||||||
|
|
||||||
playerLoop.subSystemList = copyList;
|
playerLoop.subSystemList = copyList;
|
||||||
PlayerLoop.SetPlayerLoop(playerLoop);
|
PlayerLoop.SetPlayerLoop(playerLoop);
|
||||||
@@ -333,12 +487,27 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
public static void AddAction(PlayerLoopTiming timing, IPlayerLoopItem action)
|
public static void AddAction(PlayerLoopTiming timing, IPlayerLoopItem action)
|
||||||
{
|
{
|
||||||
runners[(int)timing].AddAction(action);
|
var runner = runners[(int)timing];
|
||||||
|
if (runner == null)
|
||||||
|
{
|
||||||
|
ThrowInvalidLoopTiming(timing);
|
||||||
|
}
|
||||||
|
runner.AddAction(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ThrowInvalidLoopTiming(PlayerLoopTiming playerLoopTiming)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Target playerLoopTiming is not injected. Please check PlayerLoopHelper.Initialize. PlayerLoopTiming:" + playerLoopTiming);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void AddContinuation(PlayerLoopTiming timing, Action continuation)
|
public static void AddContinuation(PlayerLoopTiming timing, Action continuation)
|
||||||
{
|
{
|
||||||
yielders[(int)timing].Enqueue(continuation);
|
var q = yielders[(int)timing];
|
||||||
|
if (q == null)
|
||||||
|
{
|
||||||
|
ThrowInvalidLoopTiming(timing);
|
||||||
|
}
|
||||||
|
q.Enqueue(continuation);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Diagnostics helper
|
// Diagnostics helper
|
||||||
|
|||||||
@@ -12,7 +12,9 @@ namespace Cysharp.Threading.Tasks
|
|||||||
public static class TaskPool
|
public static class TaskPool
|
||||||
{
|
{
|
||||||
internal static int MaxPoolSize;
|
internal static int MaxPoolSize;
|
||||||
static ConcurrentDictionary<Type, Func<int>> sizes = new ConcurrentDictionary<Type, Func<int>>();
|
|
||||||
|
// avoid to use ConcurrentDictionary for safety of WebGL build.
|
||||||
|
static Dictionary<Type, Func<int>> sizes = new Dictionary<Type, Func<int>>();
|
||||||
|
|
||||||
static TaskPool()
|
static TaskPool()
|
||||||
{
|
{
|
||||||
@@ -40,19 +42,24 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
public static IEnumerable<(Type, int)> GetCacheSizeInfo()
|
public static IEnumerable<(Type, int)> GetCacheSizeInfo()
|
||||||
{
|
{
|
||||||
foreach (var item in sizes)
|
lock (sizes)
|
||||||
{
|
{
|
||||||
yield return (item.Key, item.Value());
|
foreach (var item in sizes)
|
||||||
|
{
|
||||||
|
yield return (item.Key, item.Value());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void RegisterSizeGetter(Type type, Func<int> getSize)
|
public static void RegisterSizeGetter(Type type, Func<int> getSize)
|
||||||
{
|
{
|
||||||
sizes[type] = getSize;
|
lock (sizes)
|
||||||
|
{
|
||||||
|
sizes[type] = getSize;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public interface ITaskPoolNode<T>
|
public interface ITaskPoolNode<T>
|
||||||
{
|
{
|
||||||
ref T NextNode { get; }
|
ref T NextNode { get; }
|
||||||
|
|||||||
258
src/UniTask/Assets/Plugins/UniTask/Runtime/TimeoutController.cs
Normal file
258
src/UniTask/Assets/Plugins/UniTask/Runtime/TimeoutController.cs
Normal file
@@ -0,0 +1,258 @@
|
|||||||
|
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||||
|
|
||||||
|
using System.Threading;
|
||||||
|
using System;
|
||||||
|
using Cysharp.Threading.Tasks.Internal;
|
||||||
|
|
||||||
|
namespace Cysharp.Threading.Tasks
|
||||||
|
{
|
||||||
|
// CancellationTokenSource itself can not reuse but CancelAfter(Timeout.InfiniteTimeSpan) allows reuse if did not reach timeout.
|
||||||
|
// Similar discussion:
|
||||||
|
// https://github.com/dotnet/runtime/issues/4694
|
||||||
|
// https://github.com/dotnet/runtime/issues/48492
|
||||||
|
// This TimeoutController emulate similar implementation, using CancelAfterSlim; to achieve zero allocation timeout.
|
||||||
|
|
||||||
|
public sealed class TimeoutController : IDisposable
|
||||||
|
{
|
||||||
|
CancellationTokenSource timeoutSource;
|
||||||
|
CancellationTokenSource linkedSource;
|
||||||
|
StoppableDelayRealtimePromise timeoutDelay;
|
||||||
|
|
||||||
|
readonly CancellationTokenSource originalLinkCancellationTokenSource;
|
||||||
|
|
||||||
|
public TimeoutController()
|
||||||
|
{
|
||||||
|
this.timeoutSource = new CancellationTokenSource();
|
||||||
|
this.originalLinkCancellationTokenSource = null;
|
||||||
|
this.linkedSource = null;
|
||||||
|
this.timeoutDelay = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TimeoutController(CancellationTokenSource linkCancellationTokenSource)
|
||||||
|
{
|
||||||
|
this.timeoutSource = new CancellationTokenSource();
|
||||||
|
this.originalLinkCancellationTokenSource = linkCancellationTokenSource;
|
||||||
|
this.linkedSource = CancellationTokenSource.CreateLinkedTokenSource(timeoutSource.Token, linkCancellationTokenSource.Token);
|
||||||
|
this.timeoutDelay = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CancellationToken Timeout(TimeSpan timeout)
|
||||||
|
{
|
||||||
|
if (originalLinkCancellationTokenSource != null && originalLinkCancellationTokenSource.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
return originalLinkCancellationTokenSource.Token;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timeoutSource.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
timeoutSource.Dispose();
|
||||||
|
timeoutSource = new CancellationTokenSource();
|
||||||
|
if (linkedSource != null)
|
||||||
|
{
|
||||||
|
this.linkedSource.Cancel();
|
||||||
|
this.linkedSource.Dispose();
|
||||||
|
this.linkedSource = CancellationTokenSource.CreateLinkedTokenSource(timeoutSource.Token, originalLinkCancellationTokenSource.Token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timeoutDelay == null)
|
||||||
|
{
|
||||||
|
RunDelayAsync(timeout).Forget(); // timeoutDelay = ... in RunDelayAsync(immediately, before await)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
timeoutDelay.RestartStopwatch(); // already running RunDelayAsync
|
||||||
|
}
|
||||||
|
|
||||||
|
return (linkedSource != null) ? linkedSource.Token : timeoutSource.Token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsTimeout()
|
||||||
|
{
|
||||||
|
return timeoutSource.IsCancellationRequested;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
if (timeoutDelay != null)
|
||||||
|
{
|
||||||
|
timeoutDelay.Stop(); // stop delay, will finish RunDelayAsync
|
||||||
|
timeoutDelay = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async UniTaskVoid RunDelayAsync(TimeSpan timeout)
|
||||||
|
{
|
||||||
|
timeoutDelay = StoppableDelayRealtimePromise.Create(timeout, PlayerLoopTiming.Update, (linkedSource == null) ? CancellationToken.None : linkedSource.Token, out var version);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var reason = await new UniTask<DelayResult>(timeoutDelay, version);
|
||||||
|
if (reason == DelayResult.DelayCompleted)
|
||||||
|
{
|
||||||
|
// UnityEngine.Debug.Log("DEBUG:Timeout Complete, try to call timeoutSource.Cancel");
|
||||||
|
timeoutSource.Cancel();
|
||||||
|
}
|
||||||
|
else if (reason == DelayResult.LinkedTokenCanceled)
|
||||||
|
{
|
||||||
|
// UnityEngine.Debug.Log("DEBUG:LinkedSource IsCancellationRequested");
|
||||||
|
}
|
||||||
|
else if (reason == DelayResult.ExternalStopped)
|
||||||
|
{
|
||||||
|
// Reset(Promise.Stop) called, do nothing.
|
||||||
|
// UnityEngine.Debug.Log("DEBUG:Reset called");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
timeoutDelay = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (timeoutDelay != null)
|
||||||
|
{
|
||||||
|
timeoutDelay.Stop();
|
||||||
|
}
|
||||||
|
timeoutSource.Dispose();
|
||||||
|
if (linkedSource != null)
|
||||||
|
{
|
||||||
|
linkedSource.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum DelayResult
|
||||||
|
{
|
||||||
|
LinkedTokenCanceled,
|
||||||
|
ExternalStopped,
|
||||||
|
DelayCompleted, // as Timeout.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop + SuppressCancellationThrow.
|
||||||
|
sealed class StoppableDelayRealtimePromise : IUniTaskSource<DelayResult>, IPlayerLoopItem, ITaskPoolNode<StoppableDelayRealtimePromise>
|
||||||
|
{
|
||||||
|
static OperationCanceledException ExterenalStopException = new OperationCanceledException();
|
||||||
|
|
||||||
|
static TaskPool<StoppableDelayRealtimePromise> pool;
|
||||||
|
StoppableDelayRealtimePromise nextNode;
|
||||||
|
public ref StoppableDelayRealtimePromise NextNode => ref nextNode;
|
||||||
|
|
||||||
|
static StoppableDelayRealtimePromise()
|
||||||
|
{
|
||||||
|
TaskPool.RegisterSizeGetter(typeof(StoppableDelayRealtimePromise), () => pool.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
long delayTimeSpanTicks;
|
||||||
|
ValueStopwatch stopwatch;
|
||||||
|
CancellationToken cancellationToken;
|
||||||
|
bool externalStop;
|
||||||
|
|
||||||
|
UniTaskCompletionSourceCore<DelayResult> core;
|
||||||
|
|
||||||
|
StoppableDelayRealtimePromise()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static StoppableDelayRealtimePromise Create(TimeSpan delayTimeSpan, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
|
||||||
|
{
|
||||||
|
if (!pool.TryPop(out var result))
|
||||||
|
{
|
||||||
|
result = new StoppableDelayRealtimePromise();
|
||||||
|
}
|
||||||
|
|
||||||
|
result.stopwatch = ValueStopwatch.StartNew();
|
||||||
|
result.delayTimeSpanTicks = delayTimeSpan.Ticks;
|
||||||
|
result.cancellationToken = cancellationToken;
|
||||||
|
result.externalStop = false;
|
||||||
|
|
||||||
|
TaskTracker.TrackActiveTask(result, 3);
|
||||||
|
|
||||||
|
PlayerLoopHelper.AddAction(timing, result);
|
||||||
|
|
||||||
|
token = result.core.Version;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Stop()
|
||||||
|
{
|
||||||
|
externalStop = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RestartStopwatch()
|
||||||
|
{
|
||||||
|
stopwatch = ValueStopwatch.StartNew();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DelayResult GetResult(short token)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return core.GetResult(token);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
TryReturn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
core.TrySetResult(DelayResult.LinkedTokenCanceled);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (externalStop)
|
||||||
|
{
|
||||||
|
core.TrySetResult(DelayResult.ExternalStopped);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stopwatch.IsInvalid)
|
||||||
|
{
|
||||||
|
core.TrySetResult(DelayResult.DelayCompleted);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stopwatch.ElapsedTicks >= delayTimeSpanTicks)
|
||||||
|
{
|
||||||
|
core.TrySetResult(DelayResult.DelayCompleted);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TryReturn()
|
||||||
|
{
|
||||||
|
TaskTracker.RemoveTracking(this);
|
||||||
|
core.Reset();
|
||||||
|
stopwatch = default;
|
||||||
|
cancellationToken = default;
|
||||||
|
externalStop = false;
|
||||||
|
return pool.TryPush(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 6347ab34d2db6d744a654e8d62d96b96
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -2,7 +2,9 @@
|
|||||||
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Cysharp.Threading.Tasks.Triggers
|
namespace Cysharp.Threading.Tasks.Triggers
|
||||||
{
|
{
|
||||||
@@ -715,6 +717,7 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region CollisionEnter
|
#region CollisionEnter
|
||||||
|
#if !UNITY_2019_1_OR_NEWER || UNITASK_PHYSICS_SUPPORT
|
||||||
|
|
||||||
public interface IAsyncOnCollisionEnterHandler
|
public interface IAsyncOnCollisionEnterHandler
|
||||||
{
|
{
|
||||||
@@ -771,9 +774,11 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||||||
return ((IAsyncOnCollisionEnterHandler)new AsyncTriggerHandler<Collision>(this, cancellationToken, true)).OnCollisionEnterAsync();
|
return ((IAsyncOnCollisionEnterHandler)new AsyncTriggerHandler<Collision>(this, cancellationToken, true)).OnCollisionEnterAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region CollisionEnter2D
|
#region CollisionEnter2D
|
||||||
|
#if !UNITY_2019_1_OR_NEWER || UNITASK_PHYSICS2D_SUPPORT
|
||||||
|
|
||||||
public interface IAsyncOnCollisionEnter2DHandler
|
public interface IAsyncOnCollisionEnter2DHandler
|
||||||
{
|
{
|
||||||
@@ -830,9 +835,11 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||||||
return ((IAsyncOnCollisionEnter2DHandler)new AsyncTriggerHandler<Collision2D>(this, cancellationToken, true)).OnCollisionEnter2DAsync();
|
return ((IAsyncOnCollisionEnter2DHandler)new AsyncTriggerHandler<Collision2D>(this, cancellationToken, true)).OnCollisionEnter2DAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region CollisionExit
|
#region CollisionExit
|
||||||
|
#if !UNITY_2019_1_OR_NEWER || UNITASK_PHYSICS_SUPPORT
|
||||||
|
|
||||||
public interface IAsyncOnCollisionExitHandler
|
public interface IAsyncOnCollisionExitHandler
|
||||||
{
|
{
|
||||||
@@ -889,9 +896,11 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||||||
return ((IAsyncOnCollisionExitHandler)new AsyncTriggerHandler<Collision>(this, cancellationToken, true)).OnCollisionExitAsync();
|
return ((IAsyncOnCollisionExitHandler)new AsyncTriggerHandler<Collision>(this, cancellationToken, true)).OnCollisionExitAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region CollisionExit2D
|
#region CollisionExit2D
|
||||||
|
#if !UNITY_2019_1_OR_NEWER || UNITASK_PHYSICS2D_SUPPORT
|
||||||
|
|
||||||
public interface IAsyncOnCollisionExit2DHandler
|
public interface IAsyncOnCollisionExit2DHandler
|
||||||
{
|
{
|
||||||
@@ -948,9 +957,11 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||||||
return ((IAsyncOnCollisionExit2DHandler)new AsyncTriggerHandler<Collision2D>(this, cancellationToken, true)).OnCollisionExit2DAsync();
|
return ((IAsyncOnCollisionExit2DHandler)new AsyncTriggerHandler<Collision2D>(this, cancellationToken, true)).OnCollisionExit2DAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region CollisionStay
|
#region CollisionStay
|
||||||
|
#if !UNITY_2019_1_OR_NEWER || UNITASK_PHYSICS_SUPPORT
|
||||||
|
|
||||||
public interface IAsyncOnCollisionStayHandler
|
public interface IAsyncOnCollisionStayHandler
|
||||||
{
|
{
|
||||||
@@ -1007,9 +1018,11 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||||||
return ((IAsyncOnCollisionStayHandler)new AsyncTriggerHandler<Collision>(this, cancellationToken, true)).OnCollisionStayAsync();
|
return ((IAsyncOnCollisionStayHandler)new AsyncTriggerHandler<Collision>(this, cancellationToken, true)).OnCollisionStayAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region CollisionStay2D
|
#region CollisionStay2D
|
||||||
|
#if !UNITY_2019_1_OR_NEWER || UNITASK_PHYSICS2D_SUPPORT
|
||||||
|
|
||||||
public interface IAsyncOnCollisionStay2DHandler
|
public interface IAsyncOnCollisionStay2DHandler
|
||||||
{
|
{
|
||||||
@@ -1066,9 +1079,11 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||||||
return ((IAsyncOnCollisionStay2DHandler)new AsyncTriggerHandler<Collision2D>(this, cancellationToken, true)).OnCollisionStay2DAsync();
|
return ((IAsyncOnCollisionStay2DHandler)new AsyncTriggerHandler<Collision2D>(this, cancellationToken, true)).OnCollisionStay2DAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region ControllerColliderHit
|
#region ControllerColliderHit
|
||||||
|
#if !UNITY_2019_1_OR_NEWER || UNITASK_PHYSICS_SUPPORT
|
||||||
|
|
||||||
public interface IAsyncOnControllerColliderHitHandler
|
public interface IAsyncOnControllerColliderHitHandler
|
||||||
{
|
{
|
||||||
@@ -1125,6 +1140,7 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||||||
return ((IAsyncOnControllerColliderHitHandler)new AsyncTriggerHandler<ControllerColliderHit>(this, cancellationToken, true)).OnControllerColliderHitAsync();
|
return ((IAsyncOnControllerColliderHitHandler)new AsyncTriggerHandler<ControllerColliderHit>(this, cancellationToken, true)).OnControllerColliderHitAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Disable
|
#region Disable
|
||||||
@@ -1423,6 +1439,7 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region JointBreak
|
#region JointBreak
|
||||||
|
#if !UNITY_2019_1_OR_NEWER || UNITASK_PHYSICS_SUPPORT
|
||||||
|
|
||||||
public interface IAsyncOnJointBreakHandler
|
public interface IAsyncOnJointBreakHandler
|
||||||
{
|
{
|
||||||
@@ -1479,9 +1496,11 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||||||
return ((IAsyncOnJointBreakHandler)new AsyncTriggerHandler<float>(this, cancellationToken, true)).OnJointBreakAsync();
|
return ((IAsyncOnJointBreakHandler)new AsyncTriggerHandler<float>(this, cancellationToken, true)).OnJointBreakAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region JointBreak2D
|
#region JointBreak2D
|
||||||
|
#if !UNITY_2019_1_OR_NEWER || UNITASK_PHYSICS2D_SUPPORT
|
||||||
|
|
||||||
public interface IAsyncOnJointBreak2DHandler
|
public interface IAsyncOnJointBreak2DHandler
|
||||||
{
|
{
|
||||||
@@ -1538,6 +1557,7 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||||||
return ((IAsyncOnJointBreak2DHandler)new AsyncTriggerHandler<Joint2D>(this, cancellationToken, true)).OnJointBreak2DAsync();
|
return ((IAsyncOnJointBreak2DHandler)new AsyncTriggerHandler<Joint2D>(this, cancellationToken, true)).OnJointBreak2DAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region MouseDown
|
#region MouseDown
|
||||||
@@ -2145,7 +2165,7 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region ParticleUpdateJobScheduled
|
#region ParticleUpdateJobScheduled
|
||||||
#if UNITY_2019_3_OR_NEWER
|
#if UNITY_2019_3_OR_NEWER && (!UNITY_2019_1_OR_NEWER || UNITASK_PARTICLESYSTEM_SUPPORT)
|
||||||
|
|
||||||
public interface IAsyncOnParticleUpdateJobScheduledHandler
|
public interface IAsyncOnParticleUpdateJobScheduledHandler
|
||||||
{
|
{
|
||||||
@@ -2796,6 +2816,7 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region TriggerEnter
|
#region TriggerEnter
|
||||||
|
#if !UNITY_2019_1_OR_NEWER || UNITASK_PHYSICS_SUPPORT
|
||||||
|
|
||||||
public interface IAsyncOnTriggerEnterHandler
|
public interface IAsyncOnTriggerEnterHandler
|
||||||
{
|
{
|
||||||
@@ -2852,9 +2873,11 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||||||
return ((IAsyncOnTriggerEnterHandler)new AsyncTriggerHandler<Collider>(this, cancellationToken, true)).OnTriggerEnterAsync();
|
return ((IAsyncOnTriggerEnterHandler)new AsyncTriggerHandler<Collider>(this, cancellationToken, true)).OnTriggerEnterAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region TriggerEnter2D
|
#region TriggerEnter2D
|
||||||
|
#if !UNITY_2019_1_OR_NEWER || UNITASK_PHYSICS2D_SUPPORT
|
||||||
|
|
||||||
public interface IAsyncOnTriggerEnter2DHandler
|
public interface IAsyncOnTriggerEnter2DHandler
|
||||||
{
|
{
|
||||||
@@ -2911,9 +2934,11 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||||||
return ((IAsyncOnTriggerEnter2DHandler)new AsyncTriggerHandler<Collider2D>(this, cancellationToken, true)).OnTriggerEnter2DAsync();
|
return ((IAsyncOnTriggerEnter2DHandler)new AsyncTriggerHandler<Collider2D>(this, cancellationToken, true)).OnTriggerEnter2DAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region TriggerExit
|
#region TriggerExit
|
||||||
|
#if !UNITY_2019_1_OR_NEWER || UNITASK_PHYSICS_SUPPORT
|
||||||
|
|
||||||
public interface IAsyncOnTriggerExitHandler
|
public interface IAsyncOnTriggerExitHandler
|
||||||
{
|
{
|
||||||
@@ -2970,9 +2995,11 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||||||
return ((IAsyncOnTriggerExitHandler)new AsyncTriggerHandler<Collider>(this, cancellationToken, true)).OnTriggerExitAsync();
|
return ((IAsyncOnTriggerExitHandler)new AsyncTriggerHandler<Collider>(this, cancellationToken, true)).OnTriggerExitAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region TriggerExit2D
|
#region TriggerExit2D
|
||||||
|
#if !UNITY_2019_1_OR_NEWER || UNITASK_PHYSICS2D_SUPPORT
|
||||||
|
|
||||||
public interface IAsyncOnTriggerExit2DHandler
|
public interface IAsyncOnTriggerExit2DHandler
|
||||||
{
|
{
|
||||||
@@ -3029,9 +3056,11 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||||||
return ((IAsyncOnTriggerExit2DHandler)new AsyncTriggerHandler<Collider2D>(this, cancellationToken, true)).OnTriggerExit2DAsync();
|
return ((IAsyncOnTriggerExit2DHandler)new AsyncTriggerHandler<Collider2D>(this, cancellationToken, true)).OnTriggerExit2DAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region TriggerStay
|
#region TriggerStay
|
||||||
|
#if !UNITY_2019_1_OR_NEWER || UNITASK_PHYSICS_SUPPORT
|
||||||
|
|
||||||
public interface IAsyncOnTriggerStayHandler
|
public interface IAsyncOnTriggerStayHandler
|
||||||
{
|
{
|
||||||
@@ -3088,9 +3117,11 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||||||
return ((IAsyncOnTriggerStayHandler)new AsyncTriggerHandler<Collider>(this, cancellationToken, true)).OnTriggerStayAsync();
|
return ((IAsyncOnTriggerStayHandler)new AsyncTriggerHandler<Collider>(this, cancellationToken, true)).OnTriggerStayAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region TriggerStay2D
|
#region TriggerStay2D
|
||||||
|
#if !UNITY_2019_1_OR_NEWER || UNITASK_PHYSICS2D_SUPPORT
|
||||||
|
|
||||||
public interface IAsyncOnTriggerStay2DHandler
|
public interface IAsyncOnTriggerStay2DHandler
|
||||||
{
|
{
|
||||||
@@ -3147,6 +3178,7 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||||||
return ((IAsyncOnTriggerStay2DHandler)new AsyncTriggerHandler<Collider2D>(this, cancellationToken, true)).OnTriggerStay2DAsync();
|
return ((IAsyncOnTriggerStay2DHandler)new AsyncTriggerHandler<Collider2D>(this, cancellationToken, true)).OnTriggerStay2DAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Validate
|
#region Validate
|
||||||
@@ -3386,6 +3418,7 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region BeginDrag
|
#region BeginDrag
|
||||||
|
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
||||||
|
|
||||||
public interface IAsyncOnBeginDragHandler
|
public interface IAsyncOnBeginDragHandler
|
||||||
{
|
{
|
||||||
@@ -3442,9 +3475,11 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||||||
return ((IAsyncOnBeginDragHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnBeginDragAsync();
|
return ((IAsyncOnBeginDragHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnBeginDragAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Cancel
|
#region Cancel
|
||||||
|
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
||||||
|
|
||||||
public interface IAsyncOnCancelHandler
|
public interface IAsyncOnCancelHandler
|
||||||
{
|
{
|
||||||
@@ -3501,9 +3536,11 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||||||
return ((IAsyncOnCancelHandler)new AsyncTriggerHandler<BaseEventData>(this, cancellationToken, true)).OnCancelAsync();
|
return ((IAsyncOnCancelHandler)new AsyncTriggerHandler<BaseEventData>(this, cancellationToken, true)).OnCancelAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Deselect
|
#region Deselect
|
||||||
|
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
||||||
|
|
||||||
public interface IAsyncOnDeselectHandler
|
public interface IAsyncOnDeselectHandler
|
||||||
{
|
{
|
||||||
@@ -3560,9 +3597,11 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||||||
return ((IAsyncOnDeselectHandler)new AsyncTriggerHandler<BaseEventData>(this, cancellationToken, true)).OnDeselectAsync();
|
return ((IAsyncOnDeselectHandler)new AsyncTriggerHandler<BaseEventData>(this, cancellationToken, true)).OnDeselectAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Drag
|
#region Drag
|
||||||
|
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
||||||
|
|
||||||
public interface IAsyncOnDragHandler
|
public interface IAsyncOnDragHandler
|
||||||
{
|
{
|
||||||
@@ -3619,9 +3658,11 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||||||
return ((IAsyncOnDragHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnDragAsync();
|
return ((IAsyncOnDragHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnDragAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Drop
|
#region Drop
|
||||||
|
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
||||||
|
|
||||||
public interface IAsyncOnDropHandler
|
public interface IAsyncOnDropHandler
|
||||||
{
|
{
|
||||||
@@ -3678,9 +3719,11 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||||||
return ((IAsyncOnDropHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnDropAsync();
|
return ((IAsyncOnDropHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnDropAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region EndDrag
|
#region EndDrag
|
||||||
|
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
||||||
|
|
||||||
public interface IAsyncOnEndDragHandler
|
public interface IAsyncOnEndDragHandler
|
||||||
{
|
{
|
||||||
@@ -3737,9 +3780,11 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||||||
return ((IAsyncOnEndDragHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnEndDragAsync();
|
return ((IAsyncOnEndDragHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnEndDragAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region InitializePotentialDrag
|
#region InitializePotentialDrag
|
||||||
|
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
||||||
|
|
||||||
public interface IAsyncOnInitializePotentialDragHandler
|
public interface IAsyncOnInitializePotentialDragHandler
|
||||||
{
|
{
|
||||||
@@ -3796,9 +3841,11 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||||||
return ((IAsyncOnInitializePotentialDragHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnInitializePotentialDragAsync();
|
return ((IAsyncOnInitializePotentialDragHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnInitializePotentialDragAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Move
|
#region Move
|
||||||
|
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
||||||
|
|
||||||
public interface IAsyncOnMoveHandler
|
public interface IAsyncOnMoveHandler
|
||||||
{
|
{
|
||||||
@@ -3855,9 +3902,11 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||||||
return ((IAsyncOnMoveHandler)new AsyncTriggerHandler<AxisEventData>(this, cancellationToken, true)).OnMoveAsync();
|
return ((IAsyncOnMoveHandler)new AsyncTriggerHandler<AxisEventData>(this, cancellationToken, true)).OnMoveAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region PointerClick
|
#region PointerClick
|
||||||
|
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
||||||
|
|
||||||
public interface IAsyncOnPointerClickHandler
|
public interface IAsyncOnPointerClickHandler
|
||||||
{
|
{
|
||||||
@@ -3914,9 +3963,11 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||||||
return ((IAsyncOnPointerClickHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnPointerClickAsync();
|
return ((IAsyncOnPointerClickHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnPointerClickAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region PointerDown
|
#region PointerDown
|
||||||
|
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
||||||
|
|
||||||
public interface IAsyncOnPointerDownHandler
|
public interface IAsyncOnPointerDownHandler
|
||||||
{
|
{
|
||||||
@@ -3973,9 +4024,11 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||||||
return ((IAsyncOnPointerDownHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnPointerDownAsync();
|
return ((IAsyncOnPointerDownHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnPointerDownAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region PointerEnter
|
#region PointerEnter
|
||||||
|
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
||||||
|
|
||||||
public interface IAsyncOnPointerEnterHandler
|
public interface IAsyncOnPointerEnterHandler
|
||||||
{
|
{
|
||||||
@@ -4032,9 +4085,11 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||||||
return ((IAsyncOnPointerEnterHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnPointerEnterAsync();
|
return ((IAsyncOnPointerEnterHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnPointerEnterAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region PointerExit
|
#region PointerExit
|
||||||
|
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
||||||
|
|
||||||
public interface IAsyncOnPointerExitHandler
|
public interface IAsyncOnPointerExitHandler
|
||||||
{
|
{
|
||||||
@@ -4091,9 +4146,11 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||||||
return ((IAsyncOnPointerExitHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnPointerExitAsync();
|
return ((IAsyncOnPointerExitHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnPointerExitAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region PointerUp
|
#region PointerUp
|
||||||
|
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
||||||
|
|
||||||
public interface IAsyncOnPointerUpHandler
|
public interface IAsyncOnPointerUpHandler
|
||||||
{
|
{
|
||||||
@@ -4150,9 +4207,11 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||||||
return ((IAsyncOnPointerUpHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnPointerUpAsync();
|
return ((IAsyncOnPointerUpHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnPointerUpAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Scroll
|
#region Scroll
|
||||||
|
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
||||||
|
|
||||||
public interface IAsyncOnScrollHandler
|
public interface IAsyncOnScrollHandler
|
||||||
{
|
{
|
||||||
@@ -4209,9 +4268,11 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||||||
return ((IAsyncOnScrollHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnScrollAsync();
|
return ((IAsyncOnScrollHandler)new AsyncTriggerHandler<PointerEventData>(this, cancellationToken, true)).OnScrollAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Select
|
#region Select
|
||||||
|
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
||||||
|
|
||||||
public interface IAsyncOnSelectHandler
|
public interface IAsyncOnSelectHandler
|
||||||
{
|
{
|
||||||
@@ -4268,9 +4329,11 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||||||
return ((IAsyncOnSelectHandler)new AsyncTriggerHandler<BaseEventData>(this, cancellationToken, true)).OnSelectAsync();
|
return ((IAsyncOnSelectHandler)new AsyncTriggerHandler<BaseEventData>(this, cancellationToken, true)).OnSelectAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Submit
|
#region Submit
|
||||||
|
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
||||||
|
|
||||||
public interface IAsyncOnSubmitHandler
|
public interface IAsyncOnSubmitHandler
|
||||||
{
|
{
|
||||||
@@ -4327,9 +4390,11 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||||||
return ((IAsyncOnSubmitHandler)new AsyncTriggerHandler<BaseEventData>(this, cancellationToken, true)).OnSubmitAsync();
|
return ((IAsyncOnSubmitHandler)new AsyncTriggerHandler<BaseEventData>(this, cancellationToken, true)).OnSubmitAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region UpdateSelected
|
#region UpdateSelected
|
||||||
|
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
||||||
|
|
||||||
public interface IAsyncOnUpdateSelectedHandler
|
public interface IAsyncOnUpdateSelectedHandler
|
||||||
{
|
{
|
||||||
@@ -4386,6 +4451,7 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||||||
return ((IAsyncOnUpdateSelectedHandler)new AsyncTriggerHandler<BaseEventData>(this, cancellationToken, true)).OnUpdateSelectedAsync();
|
return ((IAsyncOnUpdateSelectedHandler)new AsyncTriggerHandler<BaseEventData>(this, cancellationToken, true)).OnUpdateSelectedAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -106,24 +106,36 @@
|
|||||||
Func<(string argType, string argName)[], string> BuildMethodArgument = x => string.Join(", ", x.Select(y => y.argType + " " + y.argName));
|
Func<(string argType, string argName)[], string> BuildMethodArgument = x => string.Join(", ", x.Select(y => y.argType + " " + y.argName));
|
||||||
Func<(string argType, string argName)[], string> BuildResultParameter = x => x.Length == 0 ? "AsyncUnit.Default" : "(" + string.Join(", ", x.Select(y => y.argName)) + ")";
|
Func<(string argType, string argName)[], string> BuildResultParameter = x => x.Length == 0 ? "AsyncUnit.Default" : "(" + string.Join(", ", x.Select(y => y.argName)) + ")";
|
||||||
|
|
||||||
Func<string, bool> Is2019_3 = x => x == "ParticleUpdateJobScheduled";
|
Func<string, bool> IsParticleSystem = x => x == "ParticleUpdateJobScheduled";
|
||||||
Func<string, bool> IsMouseTrigger = x => x.StartsWith("Mouse");
|
Func<string, bool> IsMouseTrigger = x => x.StartsWith("Mouse");
|
||||||
|
Func<string, string> RequirePhysicsModule = x => (x.StartsWith("Collision") || x.StartsWith("Collider") || x.StartsWith("ControllerCollider") || x.StartsWith("Joint") || x.StartsWith("Trigger"))
|
||||||
|
? (x.Contains("2D") ? "UNITASK_PHYSICS2D_SUPPORT" : "UNITASK_PHYSICS_SUPPORT")
|
||||||
|
: null;
|
||||||
|
Func<string, bool> IsUguiSystem = x => x != null;
|
||||||
#>
|
#>
|
||||||
#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 System.Threading;
|
using System.Threading;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
||||||
using UnityEngine.EventSystems;
|
using UnityEngine.EventSystems;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Cysharp.Threading.Tasks.Triggers
|
namespace Cysharp.Threading.Tasks.Triggers
|
||||||
{
|
{
|
||||||
<# foreach(var t in triggers) { #>
|
<# foreach(var t in triggers) { #>
|
||||||
#region <#= t.triggerName #>
|
#region <#= t.triggerName #>
|
||||||
<# if(Is2019_3(t.triggerName)) { #>
|
<# if(IsUguiSystem(t.handlerInterface)) { #>
|
||||||
#if UNITY_2019_3_OR_NEWER
|
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
||||||
|
<# } #>
|
||||||
|
<# if(IsParticleSystem(t.triggerName)) { #>
|
||||||
|
#if UNITY_2019_3_OR_NEWER && (!UNITY_2019_1_OR_NEWER || UNITASK_PARTICLESYSTEM_SUPPORT)
|
||||||
<# } #>
|
<# } #>
|
||||||
<# if(IsMouseTrigger(t.triggerName)) { #>
|
<# if(IsMouseTrigger(t.triggerName)) { #>
|
||||||
#if !(UNITY_IPHONE || UNITY_ANDROID || UNITY_METRO)
|
#if !(UNITY_IPHONE || UNITY_ANDROID || UNITY_METRO)
|
||||||
|
<# } #>
|
||||||
|
<# if(RequirePhysicsModule(t.triggerName) != null) { #>
|
||||||
|
#if !UNITY_2019_1_OR_NEWER || <#= RequirePhysicsModule(t.triggerName) #>
|
||||||
<# } #>
|
<# } #>
|
||||||
|
|
||||||
public interface <#= ToInterfaceName(t.methodName) #>
|
public interface <#= ToInterfaceName(t.methodName) #>
|
||||||
@@ -181,7 +193,13 @@ namespace Cysharp.Threading.Tasks.Triggers
|
|||||||
return ((<#= ToInterfaceName(t.methodName) #>)new AsyncTriggerHandler<<#= t.returnType #>>(this, cancellationToken, true)).<#= t.methodName #>Async();
|
return ((<#= ToInterfaceName(t.methodName) #>)new AsyncTriggerHandler<<#= t.returnType #>>(this, cancellationToken, true)).<#= t.methodName #>Async();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
<# if(Is2019_3(t.triggerName) || IsMouseTrigger(t.triggerName)) { #>
|
<# if(IsUguiSystem(t.handlerInterface)) { #>
|
||||||
|
#endif
|
||||||
|
<# } #>
|
||||||
|
<# if(RequirePhysicsModule(t.triggerName) != null) { #>
|
||||||
|
#endif
|
||||||
|
<# } #>
|
||||||
|
<# if(IsParticleSystem(t.triggerName) || IsMouseTrigger(t.triggerName)) { #>
|
||||||
#endif
|
#endif
|
||||||
<# } #>
|
<# } #>
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@@ -20,12 +20,23 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
public partial struct UniTask
|
public partial struct UniTask
|
||||||
{
|
{
|
||||||
public static YieldAwaitable Yield(PlayerLoopTiming timing = PlayerLoopTiming.Update)
|
public static YieldAwaitable Yield()
|
||||||
|
{
|
||||||
|
// optimized for single continuation
|
||||||
|
return new YieldAwaitable(PlayerLoopTiming.Update);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static YieldAwaitable Yield(PlayerLoopTiming timing)
|
||||||
{
|
{
|
||||||
// optimized for single continuation
|
// optimized for single continuation
|
||||||
return new YieldAwaitable(timing);
|
return new YieldAwaitable(timing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static UniTask Yield(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return new UniTask(YieldPromise.Create(PlayerLoopTiming.Update, cancellationToken, out var token), token);
|
||||||
|
}
|
||||||
|
|
||||||
public static UniTask Yield(PlayerLoopTiming timing, CancellationToken cancellationToken)
|
public static UniTask Yield(PlayerLoopTiming timing, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return new UniTask(YieldPromise.Create(timing, cancellationToken, out var token), token);
|
return new UniTask(YieldPromise.Create(timing, cancellationToken, out var token), token);
|
||||||
@@ -34,11 +45,36 @@ namespace Cysharp.Threading.Tasks
|
|||||||
/// <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 = PlayerLoopTiming.Update, CancellationToken cancellationToken = default)
|
public static UniTask NextFrame()
|
||||||
|
{
|
||||||
|
return new UniTask(NextFramePromise.Create(PlayerLoopTiming.Update, CancellationToken.None, out var token), token);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Similar as UniTask.Yield but guaranteed run on next frame.
|
||||||
|
/// </summary>
|
||||||
|
public static UniTask NextFrame(PlayerLoopTiming timing)
|
||||||
|
{
|
||||||
|
return new UniTask(NextFramePromise.Create(timing, CancellationToken.None, out var token), token);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Similar as UniTask.Yield but guaranteed run on next frame.
|
||||||
|
/// </summary>
|
||||||
|
public static UniTask NextFrame(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return new UniTask(NextFramePromise.Create(PlayerLoopTiming.Update, cancellationToken, out var token), token);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Similar as UniTask.Yield but guaranteed run on next frame.
|
||||||
|
/// </summary>
|
||||||
|
public static UniTask NextFrame(PlayerLoopTiming timing, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return new UniTask(NextFramePromise.Create(timing, cancellationToken, out var token), token);
|
return new UniTask(NextFramePromise.Create(timing, cancellationToken, out var token), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Same as UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate).
|
/// Same as UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -106,6 +142,14 @@ namespace Cysharp.Threading.Tasks
|
|||||||
throw new ArgumentOutOfRangeException("Delay does not allow minus delayTimeSpan. delayTimeSpan:" + delayTimeSpan);
|
throw new ArgumentOutOfRangeException("Delay does not allow minus delayTimeSpan. delayTimeSpan:" + delayTimeSpan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
// force use Realtime.
|
||||||
|
if (PlayerLoopHelper.IsMainThread && !UnityEditor.EditorApplication.isPlaying)
|
||||||
|
{
|
||||||
|
delayType = DelayType.Realtime;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
switch (delayType)
|
switch (delayType)
|
||||||
{
|
{
|
||||||
case DelayType.UnscaledDeltaTime:
|
case DelayType.UnscaledDeltaTime:
|
||||||
@@ -726,6 +770,12 @@ namespace Cysharp.Threading.Tasks
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (stopwatch.IsInvalid)
|
||||||
|
{
|
||||||
|
core.TrySetResult(AsyncUnit.Default);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (stopwatch.ElapsedTicks >= delayTimeSpanTicks)
|
if (stopwatch.ElapsedTicks >= delayTimeSpanTicks)
|
||||||
{
|
{
|
||||||
core.TrySetResult(AsyncUnit.Default);
|
core.TrySetResult(AsyncUnit.Default);
|
||||||
|
|||||||
@@ -341,10 +341,12 @@ namespace Cysharp.Threading.Tasks
|
|||||||
public UniTaskStatus GetStatus(short token)
|
public UniTaskStatus GetStatus(short token)
|
||||||
{
|
{
|
||||||
var f = Interlocked.Exchange(ref factory, null);
|
var f = Interlocked.Exchange(ref factory, null);
|
||||||
if (f == null) throw new InvalidOperationException("Can't call twice.");
|
if (f != null)
|
||||||
|
{
|
||||||
|
task = f();
|
||||||
|
awaiter = task.GetAwaiter();
|
||||||
|
}
|
||||||
|
|
||||||
task = f();
|
|
||||||
awaiter = task.GetAwaiter();
|
|
||||||
return task.Status;
|
return task.Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -383,10 +385,12 @@ namespace Cysharp.Threading.Tasks
|
|||||||
public UniTaskStatus GetStatus(short token)
|
public UniTaskStatus GetStatus(short token)
|
||||||
{
|
{
|
||||||
var f = Interlocked.Exchange(ref factory, null);
|
var f = Interlocked.Exchange(ref factory, null);
|
||||||
if (f == null) throw new InvalidOperationException("Can't call twice.");
|
if (f != null)
|
||||||
|
{
|
||||||
|
task = f();
|
||||||
|
awaiter = task.GetAwaiter();
|
||||||
|
}
|
||||||
|
|
||||||
task = f();
|
|
||||||
awaiter = task.GetAwaiter();
|
|
||||||
return task.Status;
|
return task.Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "UniTask",
|
"name": "UniTask",
|
||||||
"references": [
|
"rootNamespace": "",
|
||||||
],
|
"references": [],
|
||||||
"includePlatforms": [],
|
"includePlatforms": [],
|
||||||
"excludePlatforms": [],
|
"excludePlatforms": [],
|
||||||
"allowUnsafeCode": false,
|
"allowUnsafeCode": false,
|
||||||
@@ -14,6 +14,31 @@
|
|||||||
"name": "com.unity.modules.assetbundle",
|
"name": "com.unity.modules.assetbundle",
|
||||||
"expression": "",
|
"expression": "",
|
||||||
"define": "UNITASK_ASSETBUNDLE_SUPPORT"
|
"define": "UNITASK_ASSETBUNDLE_SUPPORT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "com.unity.modules.physics",
|
||||||
|
"expression": "",
|
||||||
|
"define": "UNITASK_PHYSICS_SUPPORT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "com.unity.modules.physics2d",
|
||||||
|
"expression": "",
|
||||||
|
"define": "UNITASK_PHYSICS2D_SUPPORT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "com.unity.modules.particlesystem",
|
||||||
|
"expression": "",
|
||||||
|
"define": "UNITASK_PARTICLESYSTEM_SUPPORT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "com.unity.ugui",
|
||||||
|
"expression": "",
|
||||||
|
"define": "UNITASK_UGUI_SUPPORT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "com.unity.modules.unitywebrequest",
|
||||||
|
"expression": "",
|
||||||
|
"define": "UNITASK_WEBREQUEST_SUPPORT"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"noEngineReferences": false
|
"noEngineReferences": false
|
||||||
|
|||||||
@@ -115,8 +115,13 @@ namespace Cysharp.Threading.Tasks
|
|||||||
var status = this.source.GetStatus(this.token);
|
var status = this.source.GetStatus(this.token);
|
||||||
if (status.IsCompletedSuccessfully())
|
if (status.IsCompletedSuccessfully())
|
||||||
{
|
{
|
||||||
|
this.source.GetResult(this.token);
|
||||||
return CompletedTasks.AsyncUnit;
|
return CompletedTasks.AsyncUnit;
|
||||||
}
|
}
|
||||||
|
else if(this.source is IUniTaskSource<AsyncUnit> asyncUnitSource)
|
||||||
|
{
|
||||||
|
return new UniTask<AsyncUnit>(asyncUnitSource, this.token);
|
||||||
|
}
|
||||||
|
|
||||||
return new UniTask<AsyncUnit>(new AsyncUnitSource(this.source), this.token);
|
return new UniTask<AsyncUnit>(new AsyncUnitSource(this.source), this.token);
|
||||||
}
|
}
|
||||||
@@ -422,6 +427,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
var status = this.source.GetStatus(this.token);
|
var status = this.source.GetStatus(this.token);
|
||||||
if (status.IsCompletedSuccessfully())
|
if (status.IsCompletedSuccessfully())
|
||||||
{
|
{
|
||||||
|
this.source.GetResult(this.token);
|
||||||
return UniTask.CompletedTask;
|
return UniTask.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Ignore task result when cancel raised first.
|
/// Ignore task result when cancel raised first.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static UniTask WithCancellation(this UniTask task, CancellationToken cancellationToken)
|
public static UniTask AttachExternalCancellation(this UniTask task, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (!cancellationToken.CanBeCanceled)
|
if (!cancellationToken.CanBeCanceled)
|
||||||
{
|
{
|
||||||
@@ -209,13 +209,13 @@ namespace Cysharp.Threading.Tasks
|
|||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new UniTask(new WithCancellationSource(task, cancellationToken), 0);
|
return new UniTask(new AttachExternalCancellationSource(task, cancellationToken), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Ignore task result when cancel raised first.
|
/// Ignore task result when cancel raised first.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static UniTask<T> WithCancellation<T>(this UniTask<T> task, CancellationToken cancellationToken)
|
public static UniTask<T> AttachExternalCancellation<T>(this UniTask<T> task, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (!cancellationToken.CanBeCanceled)
|
if (!cancellationToken.CanBeCanceled)
|
||||||
{
|
{
|
||||||
@@ -232,10 +232,10 @@ namespace Cysharp.Threading.Tasks
|
|||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new UniTask<T>(new WithCancellationSource<T>(task, cancellationToken), 0);
|
return new UniTask<T>(new AttachExternalCancellationSource<T>(task, cancellationToken), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class WithCancellationSource : IUniTaskSource
|
sealed class AttachExternalCancellationSource : IUniTaskSource
|
||||||
{
|
{
|
||||||
static readonly Action<object> cancellationCallbackDelegate = CancellationCallback;
|
static readonly Action<object> cancellationCallbackDelegate = CancellationCallback;
|
||||||
|
|
||||||
@@ -243,7 +243,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
CancellationTokenRegistration tokenRegistration;
|
CancellationTokenRegistration tokenRegistration;
|
||||||
UniTaskCompletionSourceCore<AsyncUnit> core;
|
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||||
|
|
||||||
public WithCancellationSource(UniTask task, CancellationToken cancellationToken)
|
public AttachExternalCancellationSource(UniTask task, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
this.cancellationToken = cancellationToken;
|
this.cancellationToken = cancellationToken;
|
||||||
this.tokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationCallbackDelegate, this);
|
this.tokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationCallbackDelegate, this);
|
||||||
@@ -269,7 +269,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
static void CancellationCallback(object state)
|
static void CancellationCallback(object state)
|
||||||
{
|
{
|
||||||
var self = (WithCancellationSource)state;
|
var self = (AttachExternalCancellationSource)state;
|
||||||
self.core.TrySetCanceled(self.cancellationToken);
|
self.core.TrySetCanceled(self.cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,7 +294,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class WithCancellationSource<T> : IUniTaskSource<T>
|
sealed class AttachExternalCancellationSource<T> : IUniTaskSource<T>
|
||||||
{
|
{
|
||||||
static readonly Action<object> cancellationCallbackDelegate = CancellationCallback;
|
static readonly Action<object> cancellationCallbackDelegate = CancellationCallback;
|
||||||
|
|
||||||
@@ -302,7 +302,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
CancellationTokenRegistration tokenRegistration;
|
CancellationTokenRegistration tokenRegistration;
|
||||||
UniTaskCompletionSourceCore<T> core;
|
UniTaskCompletionSourceCore<T> core;
|
||||||
|
|
||||||
public WithCancellationSource(UniTask<T> task, CancellationToken cancellationToken)
|
public AttachExternalCancellationSource(UniTask<T> task, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
this.cancellationToken = cancellationToken;
|
this.cancellationToken = cancellationToken;
|
||||||
this.tokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationCallbackDelegate, this);
|
this.tokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationCallbackDelegate, this);
|
||||||
@@ -327,7 +327,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
static void CancellationCallback(object state)
|
static void CancellationCallback(object state)
|
||||||
{
|
{
|
||||||
var self = (WithCancellationSource<T>)state;
|
var self = (AttachExternalCancellationSource<T>)state;
|
||||||
self.core.TrySetCanceled(self.cancellationToken);
|
self.core.TrySetCanceled(self.cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -561,21 +561,23 @@ namespace Cysharp.Threading.Tasks
|
|||||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
awaiter.SourceOnCompleted(state =>
|
|
||||||
{
|
{
|
||||||
using (var t = (StateTuple<UniTask.Awaiter>)state)
|
awaiter.SourceOnCompleted(state =>
|
||||||
{
|
{
|
||||||
try
|
using (var t = (StateTuple<UniTask.Awaiter>)state)
|
||||||
{
|
{
|
||||||
t.Item1.GetResult();
|
try
|
||||||
|
{
|
||||||
|
t.Item1.GetResult();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
}, StateTuple.Create(awaiter));
|
||||||
{
|
}
|
||||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, StateTuple.Create(awaiter));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Forget(this UniTask task, Action<Exception> exceptionHandler, bool handleExceptionOnMainThread = true)
|
public static void Forget(this UniTask task, Action<Exception> exceptionHandler, bool handleExceptionOnMainThread = true)
|
||||||
@@ -629,21 +631,23 @@ namespace Cysharp.Threading.Tasks
|
|||||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
awaiter.SourceOnCompleted(state =>
|
|
||||||
{
|
{
|
||||||
using (var t = (StateTuple<UniTask<T>.Awaiter>)state)
|
awaiter.SourceOnCompleted(state =>
|
||||||
{
|
{
|
||||||
try
|
using (var t = (StateTuple<UniTask<T>.Awaiter>)state)
|
||||||
{
|
{
|
||||||
t.Item1.GetResult();
|
try
|
||||||
|
{
|
||||||
|
t.Item1.GetResult();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
}, StateTuple.Create(awaiter));
|
||||||
{
|
}
|
||||||
UniTaskScheduler.PublishUnobservedTaskException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, StateTuple.Create(awaiter));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Forget<T>(this UniTask<T> task, Action<Exception> exceptionHandler, bool handleExceptionOnMainThread = true)
|
public static void Forget<T>(this UniTask<T> task, Action<Exception> exceptionHandler, bool handleExceptionOnMainThread = true)
|
||||||
@@ -736,12 +740,12 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
await await task;
|
await await task;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async UniTask<T> Unwrap<T>(this Task<UniTask<T>> task)
|
public static async UniTask<T> Unwrap<T>(this Task<UniTask<T>> task)
|
||||||
{
|
{
|
||||||
return await await task;
|
return await await task;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async UniTask<T> Unwrap<T>(this Task<UniTask<T>> task, bool continueOnCapturedContext)
|
public static async UniTask<T> Unwrap<T>(this Task<UniTask<T>> task, bool continueOnCapturedContext)
|
||||||
{
|
{
|
||||||
return await await task.ConfigureAwait(continueOnCapturedContext);
|
return await await task.ConfigureAwait(continueOnCapturedContext);
|
||||||
@@ -756,12 +760,12 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
await await task.ConfigureAwait(continueOnCapturedContext);
|
await await task.ConfigureAwait(continueOnCapturedContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async UniTask<T> Unwrap<T>(this UniTask<Task<T>> task)
|
public static async UniTask<T> Unwrap<T>(this UniTask<Task<T>> task)
|
||||||
{
|
{
|
||||||
return await await task;
|
return await await task;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async UniTask<T> Unwrap<T>(this UniTask<Task<T>> task, bool continueOnCapturedContext)
|
public static async UniTask<T> Unwrap<T>(this UniTask<Task<T>> task, bool continueOnCapturedContext)
|
||||||
{
|
{
|
||||||
return await (await task).ConfigureAwait(continueOnCapturedContext);
|
return await (await task).ConfigureAwait(continueOnCapturedContext);
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
const int MaxArrayLength = 0X7FEFFFFF;
|
const int MaxArrayLength = 0X7FEFFFFF;
|
||||||
const int InitialSize = 16;
|
const int InitialSize = 16;
|
||||||
|
|
||||||
static SpinLock gate = new SpinLock();
|
static SpinLock gate = new SpinLock(false);
|
||||||
static bool dequing = false;
|
static bool dequing = false;
|
||||||
|
|
||||||
static int actionListCount = 0;
|
static int actionListCount = 0;
|
||||||
|
|||||||
@@ -21,10 +21,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
public static UniTask<UnityEngine.Object[]> AwaitForAllAssets(this AssetBundleRequest asyncOperation, CancellationToken cancellationToken)
|
public static UniTask<UnityEngine.Object[]> AwaitForAllAssets(this AssetBundleRequest asyncOperation, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
return AwaitForAllAssets(asyncOperation, cancellationToken: cancellationToken);
|
||||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<UnityEngine.Object[]>(cancellationToken);
|
|
||||||
if (asyncOperation.isDone) return UniTask.FromResult<UnityEngine.Object[]>(asyncOperation.allAssets);
|
|
||||||
return new UniTask<UnityEngine.Object[]>(AssetBundleRequestAllAssetsWithCancellationSource.Create(asyncOperation, cancellationToken, out var token), token);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
@@ -84,129 +81,6 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class AssetBundleRequestAllAssetsWithCancellationSource : IUniTaskSource<UnityEngine.Object[]>, IPlayerLoopItem, ITaskPoolNode<AssetBundleRequestAllAssetsWithCancellationSource>
|
|
||||||
{
|
|
||||||
static TaskPool<AssetBundleRequestAllAssetsWithCancellationSource> pool;
|
|
||||||
AssetBundleRequestAllAssetsWithCancellationSource nextNode;
|
|
||||||
public ref AssetBundleRequestAllAssetsWithCancellationSource NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static AssetBundleRequestAllAssetsWithCancellationSource()
|
|
||||||
{
|
|
||||||
TaskPool.RegisterSizeGetter(typeof(AssetBundleRequestAllAssetsWithCancellationSource), () => pool.Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
readonly Action<AsyncOperation> continuationAction;
|
|
||||||
AssetBundleRequest asyncOperation;
|
|
||||||
CancellationToken cancellationToken;
|
|
||||||
bool completed;
|
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<UnityEngine.Object[]> core;
|
|
||||||
|
|
||||||
AssetBundleRequestAllAssetsWithCancellationSource()
|
|
||||||
{
|
|
||||||
continuationAction = Continuation;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IUniTaskSource<UnityEngine.Object[]> Create(AssetBundleRequest asyncOperation, CancellationToken cancellationToken, out short token)
|
|
||||||
{
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
return AutoResetUniTaskCompletionSource<UnityEngine.Object[]>.CreateFromCanceled(cancellationToken, out token);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pool.TryPop(out var result))
|
|
||||||
{
|
|
||||||
result = new AssetBundleRequestAllAssetsWithCancellationSource();
|
|
||||||
}
|
|
||||||
|
|
||||||
result.asyncOperation = asyncOperation;
|
|
||||||
result.cancellationToken = cancellationToken;
|
|
||||||
result.completed = false;
|
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
|
||||||
|
|
||||||
PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, result);
|
|
||||||
|
|
||||||
asyncOperation.completed += result.continuationAction;
|
|
||||||
|
|
||||||
token = result.core.Version;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Continuation(AsyncOperation _)
|
|
||||||
{
|
|
||||||
asyncOperation.completed -= continuationAction;
|
|
||||||
|
|
||||||
if (completed)
|
|
||||||
{
|
|
||||||
TryReturn();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
completed = true;
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
core.TrySetCanceled(cancellationToken);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
core.TrySetResult(asyncOperation.allAssets);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public UnityEngine.Object[] GetResult(short token)
|
|
||||||
{
|
|
||||||
return core.GetResult(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
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()
|
|
||||||
{
|
|
||||||
if (completed)
|
|
||||||
{
|
|
||||||
TryReturn();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
completed = true;
|
|
||||||
core.TrySetCanceled(cancellationToken);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TryReturn()
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
core.Reset();
|
|
||||||
asyncOperation = default;
|
|
||||||
cancellationToken = default;
|
|
||||||
return pool.TryPush(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class AssetBundleRequestAllAssetsConfiguredSource : IUniTaskSource<UnityEngine.Object[]>, IPlayerLoopItem, ITaskPoolNode<AssetBundleRequestAllAssetsConfiguredSource>
|
sealed class AssetBundleRequestAllAssetsConfiguredSource : IUniTaskSource<UnityEngine.Object[]>, IPlayerLoopItem, ITaskPoolNode<AssetBundleRequestAllAssetsConfiguredSource>
|
||||||
{
|
{
|
||||||
static TaskPool<AssetBundleRequestAllAssetsConfiguredSource> pool;
|
static TaskPool<AssetBundleRequestAllAssetsConfiguredSource> pool;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#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 System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using Unity.Jobs;
|
using Unity.Jobs;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Cysharp.Threading.Tasks
|
namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
@@ -85,7 +86,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
public bool MoveNext()
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
if (jobHandle.IsCompleted)
|
if (jobHandle.IsCompleted | PlayerLoopHelper.IsEditorApplicationQuitting)
|
||||||
{
|
{
|
||||||
jobHandle.Complete();
|
jobHandle.Complete();
|
||||||
core.TrySetResult(AsyncUnit.Default);
|
core.TrySetResult(AsyncUnit.Default);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ using System.Runtime.CompilerServices;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using Cysharp.Threading.Tasks.Internal;
|
using Cysharp.Threading.Tasks.Internal;
|
||||||
#if ENABLE_UNITYWEBREQUEST
|
#if ENABLE_UNITYWEBREQUEST && (!UNITY_2019_1_OR_NEWER || UNITASK_WEBREQUEST_SUPPORT)
|
||||||
using UnityEngine.Networking;
|
using UnityEngine.Networking;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -23,10 +23,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
public static UniTask WithCancellation(this AsyncOperation asyncOperation, CancellationToken cancellationToken)
|
public static UniTask WithCancellation(this AsyncOperation asyncOperation, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
||||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled(cancellationToken);
|
|
||||||
if (asyncOperation.isDone) return UniTask.CompletedTask;
|
|
||||||
return new UniTask(AsyncOperationWithCancellationSource.Create(asyncOperation, cancellationToken, out var token), token);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask ToUniTask(this AsyncOperation asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask ToUniTask(this AsyncOperation asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
@@ -77,125 +74,6 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class AsyncOperationWithCancellationSource : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<AsyncOperationWithCancellationSource>
|
|
||||||
{
|
|
||||||
static TaskPool<AsyncOperationWithCancellationSource> pool;
|
|
||||||
AsyncOperationWithCancellationSource nextNode;
|
|
||||||
public ref AsyncOperationWithCancellationSource NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static AsyncOperationWithCancellationSource()
|
|
||||||
{
|
|
||||||
TaskPool.RegisterSizeGetter(typeof(AsyncOperationWithCancellationSource), () => pool.Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
readonly Action<AsyncOperation> continuationAction;
|
|
||||||
AsyncOperation asyncOperation;
|
|
||||||
CancellationToken cancellationToken;
|
|
||||||
bool completed;
|
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<AsyncUnit> core;
|
|
||||||
|
|
||||||
AsyncOperationWithCancellationSource()
|
|
||||||
{
|
|
||||||
continuationAction = Continuation;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IUniTaskSource Create(AsyncOperation asyncOperation, CancellationToken cancellationToken, out short token)
|
|
||||||
{
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pool.TryPop(out var result))
|
|
||||||
{
|
|
||||||
result = new AsyncOperationWithCancellationSource();
|
|
||||||
}
|
|
||||||
|
|
||||||
result.asyncOperation = asyncOperation;
|
|
||||||
result.cancellationToken = cancellationToken;
|
|
||||||
result.completed = false;
|
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
|
||||||
|
|
||||||
PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, result);
|
|
||||||
|
|
||||||
asyncOperation.completed += result.continuationAction;
|
|
||||||
|
|
||||||
token = result.core.Version;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Continuation(AsyncOperation _)
|
|
||||||
{
|
|
||||||
asyncOperation.completed -= continuationAction;
|
|
||||||
|
|
||||||
if (completed)
|
|
||||||
{
|
|
||||||
TryReturn();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
completed = true;
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
core.TrySetCanceled(cancellationToken);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
core.TrySetResult(AsyncUnit.Default);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void GetResult(short token)
|
|
||||||
{
|
|
||||||
core.GetResult(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public UniTaskStatus GetStatus(short token)
|
|
||||||
{
|
|
||||||
return core.GetStatus(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
public UniTaskStatus UnsafeGetStatus()
|
|
||||||
{
|
|
||||||
return core.UnsafeGetStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnCompleted(Action<object> continuation, object state, short token)
|
|
||||||
{
|
|
||||||
core.OnCompleted(continuation, state, token);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool MoveNext()
|
|
||||||
{
|
|
||||||
if (completed)
|
|
||||||
{
|
|
||||||
TryReturn();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
completed = true;
|
|
||||||
core.TrySetCanceled(cancellationToken);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TryReturn()
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
core.Reset();
|
|
||||||
asyncOperation = default;
|
|
||||||
cancellationToken = default;
|
|
||||||
return pool.TryPush(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class AsyncOperationConfiguredSource : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<AsyncOperationConfiguredSource>
|
sealed class AsyncOperationConfiguredSource : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<AsyncOperationConfiguredSource>
|
||||||
{
|
{
|
||||||
static TaskPool<AsyncOperationConfiguredSource> pool;
|
static TaskPool<AsyncOperationConfiguredSource> pool;
|
||||||
@@ -315,10 +193,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
public static UniTask<UnityEngine.Object> WithCancellation(this ResourceRequest asyncOperation, CancellationToken cancellationToken)
|
public static UniTask<UnityEngine.Object> WithCancellation(this ResourceRequest asyncOperation, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
||||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<UnityEngine.Object>(cancellationToken);
|
|
||||||
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.asset);
|
|
||||||
return new UniTask<UnityEngine.Object>(ResourceRequestWithCancellationSource.Create(asyncOperation, cancellationToken, out var token), token);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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> ToUniTask(this ResourceRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
@@ -373,129 +248,6 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class ResourceRequestWithCancellationSource : IUniTaskSource<UnityEngine.Object>, IPlayerLoopItem, ITaskPoolNode<ResourceRequestWithCancellationSource>
|
|
||||||
{
|
|
||||||
static TaskPool<ResourceRequestWithCancellationSource> pool;
|
|
||||||
ResourceRequestWithCancellationSource nextNode;
|
|
||||||
public ref ResourceRequestWithCancellationSource NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static ResourceRequestWithCancellationSource()
|
|
||||||
{
|
|
||||||
TaskPool.RegisterSizeGetter(typeof(ResourceRequestWithCancellationSource), () => pool.Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
readonly Action<AsyncOperation> continuationAction;
|
|
||||||
ResourceRequest asyncOperation;
|
|
||||||
CancellationToken cancellationToken;
|
|
||||||
bool completed;
|
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<UnityEngine.Object> core;
|
|
||||||
|
|
||||||
ResourceRequestWithCancellationSource()
|
|
||||||
{
|
|
||||||
continuationAction = Continuation;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IUniTaskSource<UnityEngine.Object> Create(ResourceRequest asyncOperation, CancellationToken cancellationToken, out short token)
|
|
||||||
{
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
return AutoResetUniTaskCompletionSource<UnityEngine.Object>.CreateFromCanceled(cancellationToken, out token);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pool.TryPop(out var result))
|
|
||||||
{
|
|
||||||
result = new ResourceRequestWithCancellationSource();
|
|
||||||
}
|
|
||||||
|
|
||||||
result.asyncOperation = asyncOperation;
|
|
||||||
result.cancellationToken = cancellationToken;
|
|
||||||
result.completed = false;
|
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
|
||||||
|
|
||||||
PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, result);
|
|
||||||
|
|
||||||
asyncOperation.completed += result.continuationAction;
|
|
||||||
|
|
||||||
token = result.core.Version;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Continuation(AsyncOperation _)
|
|
||||||
{
|
|
||||||
asyncOperation.completed -= continuationAction;
|
|
||||||
|
|
||||||
if (completed)
|
|
||||||
{
|
|
||||||
TryReturn();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
completed = true;
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
core.TrySetCanceled(cancellationToken);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
core.TrySetResult(asyncOperation.asset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public UnityEngine.Object GetResult(short token)
|
|
||||||
{
|
|
||||||
return core.GetResult(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
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()
|
|
||||||
{
|
|
||||||
if (completed)
|
|
||||||
{
|
|
||||||
TryReturn();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
completed = true;
|
|
||||||
core.TrySetCanceled(cancellationToken);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TryReturn()
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
core.Reset();
|
|
||||||
asyncOperation = default;
|
|
||||||
cancellationToken = default;
|
|
||||||
return pool.TryPush(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class ResourceRequestConfiguredSource : IUniTaskSource<UnityEngine.Object>, IPlayerLoopItem, ITaskPoolNode<ResourceRequestConfiguredSource>
|
sealed class ResourceRequestConfiguredSource : IUniTaskSource<UnityEngine.Object>, IPlayerLoopItem, ITaskPoolNode<ResourceRequestConfiguredSource>
|
||||||
{
|
{
|
||||||
static TaskPool<ResourceRequestConfiguredSource> pool;
|
static TaskPool<ResourceRequestConfiguredSource> pool;
|
||||||
@@ -620,10 +372,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
public static UniTask<UnityEngine.Object> WithCancellation(this AssetBundleRequest asyncOperation, CancellationToken cancellationToken)
|
public static UniTask<UnityEngine.Object> WithCancellation(this AssetBundleRequest asyncOperation, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
||||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<UnityEngine.Object>(cancellationToken);
|
|
||||||
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.asset);
|
|
||||||
return new UniTask<UnityEngine.Object>(AssetBundleRequestWithCancellationSource.Create(asyncOperation, cancellationToken, out var token), token);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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> ToUniTask(this AssetBundleRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
@@ -678,129 +427,6 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class AssetBundleRequestWithCancellationSource : IUniTaskSource<UnityEngine.Object>, IPlayerLoopItem, ITaskPoolNode<AssetBundleRequestWithCancellationSource>
|
|
||||||
{
|
|
||||||
static TaskPool<AssetBundleRequestWithCancellationSource> pool;
|
|
||||||
AssetBundleRequestWithCancellationSource nextNode;
|
|
||||||
public ref AssetBundleRequestWithCancellationSource NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static AssetBundleRequestWithCancellationSource()
|
|
||||||
{
|
|
||||||
TaskPool.RegisterSizeGetter(typeof(AssetBundleRequestWithCancellationSource), () => pool.Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
readonly Action<AsyncOperation> continuationAction;
|
|
||||||
AssetBundleRequest asyncOperation;
|
|
||||||
CancellationToken cancellationToken;
|
|
||||||
bool completed;
|
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<UnityEngine.Object> core;
|
|
||||||
|
|
||||||
AssetBundleRequestWithCancellationSource()
|
|
||||||
{
|
|
||||||
continuationAction = Continuation;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IUniTaskSource<UnityEngine.Object> Create(AssetBundleRequest asyncOperation, CancellationToken cancellationToken, out short token)
|
|
||||||
{
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
return AutoResetUniTaskCompletionSource<UnityEngine.Object>.CreateFromCanceled(cancellationToken, out token);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pool.TryPop(out var result))
|
|
||||||
{
|
|
||||||
result = new AssetBundleRequestWithCancellationSource();
|
|
||||||
}
|
|
||||||
|
|
||||||
result.asyncOperation = asyncOperation;
|
|
||||||
result.cancellationToken = cancellationToken;
|
|
||||||
result.completed = false;
|
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
|
||||||
|
|
||||||
PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, result);
|
|
||||||
|
|
||||||
asyncOperation.completed += result.continuationAction;
|
|
||||||
|
|
||||||
token = result.core.Version;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Continuation(AsyncOperation _)
|
|
||||||
{
|
|
||||||
asyncOperation.completed -= continuationAction;
|
|
||||||
|
|
||||||
if (completed)
|
|
||||||
{
|
|
||||||
TryReturn();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
completed = true;
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
core.TrySetCanceled(cancellationToken);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
core.TrySetResult(asyncOperation.asset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public UnityEngine.Object GetResult(short token)
|
|
||||||
{
|
|
||||||
return core.GetResult(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
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()
|
|
||||||
{
|
|
||||||
if (completed)
|
|
||||||
{
|
|
||||||
TryReturn();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
completed = true;
|
|
||||||
core.TrySetCanceled(cancellationToken);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TryReturn()
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
core.Reset();
|
|
||||||
asyncOperation = default;
|
|
||||||
cancellationToken = default;
|
|
||||||
return pool.TryPush(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class AssetBundleRequestConfiguredSource : IUniTaskSource<UnityEngine.Object>, IPlayerLoopItem, ITaskPoolNode<AssetBundleRequestConfiguredSource>
|
sealed class AssetBundleRequestConfiguredSource : IUniTaskSource<UnityEngine.Object>, IPlayerLoopItem, ITaskPoolNode<AssetBundleRequestConfiguredSource>
|
||||||
{
|
{
|
||||||
static TaskPool<AssetBundleRequestConfiguredSource> pool;
|
static TaskPool<AssetBundleRequestConfiguredSource> pool;
|
||||||
@@ -926,10 +552,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
public static UniTask<AssetBundle> WithCancellation(this AssetBundleCreateRequest asyncOperation, CancellationToken cancellationToken)
|
public static UniTask<AssetBundle> WithCancellation(this AssetBundleCreateRequest asyncOperation, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
||||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<AssetBundle>(cancellationToken);
|
|
||||||
if (asyncOperation.isDone) return UniTask.FromResult(asyncOperation.assetBundle);
|
|
||||||
return new UniTask<AssetBundle>(AssetBundleCreateRequestWithCancellationSource.Create(asyncOperation, cancellationToken, out var token), token);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask<AssetBundle> ToUniTask(this AssetBundleCreateRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask<AssetBundle> ToUniTask(this AssetBundleCreateRequest asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
@@ -984,129 +607,6 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class AssetBundleCreateRequestWithCancellationSource : IUniTaskSource<AssetBundle>, IPlayerLoopItem, ITaskPoolNode<AssetBundleCreateRequestWithCancellationSource>
|
|
||||||
{
|
|
||||||
static TaskPool<AssetBundleCreateRequestWithCancellationSource> pool;
|
|
||||||
AssetBundleCreateRequestWithCancellationSource nextNode;
|
|
||||||
public ref AssetBundleCreateRequestWithCancellationSource NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static AssetBundleCreateRequestWithCancellationSource()
|
|
||||||
{
|
|
||||||
TaskPool.RegisterSizeGetter(typeof(AssetBundleCreateRequestWithCancellationSource), () => pool.Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
readonly Action<AsyncOperation> continuationAction;
|
|
||||||
AssetBundleCreateRequest asyncOperation;
|
|
||||||
CancellationToken cancellationToken;
|
|
||||||
bool completed;
|
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<AssetBundle> core;
|
|
||||||
|
|
||||||
AssetBundleCreateRequestWithCancellationSource()
|
|
||||||
{
|
|
||||||
continuationAction = Continuation;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IUniTaskSource<AssetBundle> Create(AssetBundleCreateRequest asyncOperation, CancellationToken cancellationToken, out short token)
|
|
||||||
{
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
return AutoResetUniTaskCompletionSource<AssetBundle>.CreateFromCanceled(cancellationToken, out token);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pool.TryPop(out var result))
|
|
||||||
{
|
|
||||||
result = new AssetBundleCreateRequestWithCancellationSource();
|
|
||||||
}
|
|
||||||
|
|
||||||
result.asyncOperation = asyncOperation;
|
|
||||||
result.cancellationToken = cancellationToken;
|
|
||||||
result.completed = false;
|
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
|
||||||
|
|
||||||
PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, result);
|
|
||||||
|
|
||||||
asyncOperation.completed += result.continuationAction;
|
|
||||||
|
|
||||||
token = result.core.Version;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Continuation(AsyncOperation _)
|
|
||||||
{
|
|
||||||
asyncOperation.completed -= continuationAction;
|
|
||||||
|
|
||||||
if (completed)
|
|
||||||
{
|
|
||||||
TryReturn();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
completed = true;
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
core.TrySetCanceled(cancellationToken);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
core.TrySetResult(asyncOperation.assetBundle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public AssetBundle GetResult(short token)
|
|
||||||
{
|
|
||||||
return core.GetResult(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
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()
|
|
||||||
{
|
|
||||||
if (completed)
|
|
||||||
{
|
|
||||||
TryReturn();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
completed = true;
|
|
||||||
core.TrySetCanceled(cancellationToken);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TryReturn()
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
core.Reset();
|
|
||||||
asyncOperation = default;
|
|
||||||
cancellationToken = default;
|
|
||||||
return pool.TryPush(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class AssetBundleCreateRequestConfiguredSource : IUniTaskSource<AssetBundle>, IPlayerLoopItem, ITaskPoolNode<AssetBundleCreateRequestConfiguredSource>
|
sealed class AssetBundleCreateRequestConfiguredSource : IUniTaskSource<AssetBundle>, IPlayerLoopItem, ITaskPoolNode<AssetBundleCreateRequestConfiguredSource>
|
||||||
{
|
{
|
||||||
static TaskPool<AssetBundleCreateRequestConfiguredSource> pool;
|
static TaskPool<AssetBundleCreateRequestConfiguredSource> pool;
|
||||||
@@ -1221,7 +721,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
#endregion
|
#endregion
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ENABLE_UNITYWEBREQUEST
|
#if ENABLE_UNITYWEBREQUEST && (!UNITY_2019_1_OR_NEWER || UNITASK_WEBREQUEST_SUPPORT)
|
||||||
#region UnityWebRequestAsyncOperation
|
#region UnityWebRequestAsyncOperation
|
||||||
|
|
||||||
public static UnityWebRequestAsyncOperationAwaiter GetAwaiter(this UnityWebRequestAsyncOperation asyncOperation)
|
public static UnityWebRequestAsyncOperationAwaiter GetAwaiter(this UnityWebRequestAsyncOperation asyncOperation)
|
||||||
@@ -1232,17 +732,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
public static UniTask<UnityWebRequest> WithCancellation(this UnityWebRequestAsyncOperation asyncOperation, CancellationToken cancellationToken)
|
public static UniTask<UnityWebRequest> WithCancellation(this UnityWebRequestAsyncOperation asyncOperation, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
||||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<UnityWebRequest>(cancellationToken);
|
|
||||||
if (asyncOperation.isDone)
|
|
||||||
{
|
|
||||||
if (asyncOperation.webRequest.IsError())
|
|
||||||
{
|
|
||||||
return UniTask.FromException<UnityWebRequest>(new UnityWebRequestException(asyncOperation.webRequest));
|
|
||||||
}
|
|
||||||
return UniTask.FromResult(asyncOperation.webRequest);
|
|
||||||
}
|
|
||||||
return new UniTask<UnityWebRequest>(UnityWebRequestAsyncOperationWithCancellationSource.Create(asyncOperation, cancellationToken, out var token), token);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UniTask<UnityWebRequest> ToUniTask(this UnityWebRequestAsyncOperation asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
public static UniTask<UnityWebRequest> ToUniTask(this UnityWebRequestAsyncOperation asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
@@ -1312,138 +802,6 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class UnityWebRequestAsyncOperationWithCancellationSource : IUniTaskSource<UnityWebRequest>, IPlayerLoopItem, ITaskPoolNode<UnityWebRequestAsyncOperationWithCancellationSource>
|
|
||||||
{
|
|
||||||
static TaskPool<UnityWebRequestAsyncOperationWithCancellationSource> pool;
|
|
||||||
UnityWebRequestAsyncOperationWithCancellationSource nextNode;
|
|
||||||
public ref UnityWebRequestAsyncOperationWithCancellationSource NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static UnityWebRequestAsyncOperationWithCancellationSource()
|
|
||||||
{
|
|
||||||
TaskPool.RegisterSizeGetter(typeof(UnityWebRequestAsyncOperationWithCancellationSource), () => pool.Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
readonly Action<AsyncOperation> continuationAction;
|
|
||||||
UnityWebRequestAsyncOperation asyncOperation;
|
|
||||||
CancellationToken cancellationToken;
|
|
||||||
bool completed;
|
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<UnityWebRequest> core;
|
|
||||||
|
|
||||||
UnityWebRequestAsyncOperationWithCancellationSource()
|
|
||||||
{
|
|
||||||
continuationAction = Continuation;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IUniTaskSource<UnityWebRequest> Create(UnityWebRequestAsyncOperation asyncOperation, CancellationToken cancellationToken, out short token)
|
|
||||||
{
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
return AutoResetUniTaskCompletionSource<UnityWebRequest>.CreateFromCanceled(cancellationToken, out token);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pool.TryPop(out var result))
|
|
||||||
{
|
|
||||||
result = new UnityWebRequestAsyncOperationWithCancellationSource();
|
|
||||||
}
|
|
||||||
|
|
||||||
result.asyncOperation = asyncOperation;
|
|
||||||
result.cancellationToken = cancellationToken;
|
|
||||||
result.completed = false;
|
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
|
||||||
|
|
||||||
PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, result);
|
|
||||||
|
|
||||||
asyncOperation.completed += result.continuationAction;
|
|
||||||
|
|
||||||
token = result.core.Version;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Continuation(AsyncOperation _)
|
|
||||||
{
|
|
||||||
asyncOperation.completed -= continuationAction;
|
|
||||||
|
|
||||||
if (completed)
|
|
||||||
{
|
|
||||||
TryReturn();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
completed = true;
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
core.TrySetCanceled(cancellationToken);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = asyncOperation.webRequest;
|
|
||||||
if (result.IsError())
|
|
||||||
{
|
|
||||||
core.TrySetException(new UnityWebRequestException(result));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
core.TrySetResult(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public UnityWebRequest GetResult(short token)
|
|
||||||
{
|
|
||||||
return core.GetResult(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
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()
|
|
||||||
{
|
|
||||||
if (completed)
|
|
||||||
{
|
|
||||||
TryReturn();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
completed = true;
|
|
||||||
asyncOperation.webRequest.Abort();
|
|
||||||
core.TrySetCanceled(cancellationToken);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TryReturn()
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
core.Reset();
|
|
||||||
asyncOperation = default;
|
|
||||||
cancellationToken = default;
|
|
||||||
return pool.TryPush(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class UnityWebRequestAsyncOperationConfiguredSource : IUniTaskSource<UnityWebRequest>, IPlayerLoopItem, ITaskPoolNode<UnityWebRequestAsyncOperationConfiguredSource>
|
sealed class UnityWebRequestAsyncOperationConfiguredSource : IUniTaskSource<UnityWebRequest>, IPlayerLoopItem, ITaskPoolNode<UnityWebRequestAsyncOperationConfiguredSource>
|
||||||
{
|
{
|
||||||
static TaskPool<UnityWebRequestAsyncOperationConfiguredSource> pool;
|
static TaskPool<UnityWebRequestAsyncOperationConfiguredSource> pool;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
("ResourceRequest", "UnityEngine.Object", "asset"),
|
("ResourceRequest", "UnityEngine.Object", "asset"),
|
||||||
("AssetBundleRequest", "UnityEngine.Object", "asset"), // allAssets?
|
("AssetBundleRequest", "UnityEngine.Object", "asset"), // allAssets?
|
||||||
("AssetBundleCreateRequest", "AssetBundle", "assetBundle"),
|
("AssetBundleCreateRequest", "AssetBundle", "assetBundle"),
|
||||||
("UnityWebRequestAsyncOperation", "UnityWebRequest", "webRequest") // -> #if ENABLE_UNITYWEBREQUEST
|
("UnityWebRequestAsyncOperation", "UnityWebRequest", "webRequest") // -> #if ENABLE_UNITYWEBREQUEST && (!UNITY_2019_1_OR_NEWER || UNITASK_WEBREQUEST_SUPPORT)
|
||||||
};
|
};
|
||||||
|
|
||||||
Func<string, string> ToUniTaskReturnType = x => (x == "void") ? "UniTask" : $"UniTask<{x}>";
|
Func<string, string> ToUniTaskReturnType = x => (x == "void") ? "UniTask" : $"UniTask<{x}>";
|
||||||
@@ -27,7 +27,7 @@ using System.Runtime.CompilerServices;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using Cysharp.Threading.Tasks.Internal;
|
using Cysharp.Threading.Tasks.Internal;
|
||||||
#if ENABLE_UNITYWEBREQUEST
|
#if ENABLE_UNITYWEBREQUEST && (!UNITY_2019_1_OR_NEWER || UNITASK_WEBREQUEST_SUPPORT)
|
||||||
using UnityEngine.Networking;
|
using UnityEngine.Networking;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
{
|
{
|
||||||
<# foreach(var t in types) { #>
|
<# foreach(var t in types) { #>
|
||||||
<# if(IsUnityWebRequest(t)) { #>
|
<# if(IsUnityWebRequest(t)) { #>
|
||||||
#if ENABLE_UNITYWEBREQUEST
|
#if ENABLE_UNITYWEBREQUEST && (!UNITY_2019_1_OR_NEWER || UNITASK_WEBREQUEST_SUPPORT)
|
||||||
<# } else if(IsAssetBundleModule(t)) { #>
|
<# } else if(IsAssetBundleModule(t)) { #>
|
||||||
#if UNITASK_ASSETBUNDLE_SUPPORT
|
#if UNITASK_ASSETBUNDLE_SUPPORT
|
||||||
<# } #>
|
<# } #>
|
||||||
@@ -51,21 +51,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
public static <#= ToUniTaskReturnType(t.returnType) #> WithCancellation(this <#= t.typeName #> asyncOperation, CancellationToken cancellationToken)
|
public static <#= ToUniTaskReturnType(t.returnType) #> WithCancellation(this <#= t.typeName #> asyncOperation, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
Error.ThrowArgumentNullException(asyncOperation, nameof(asyncOperation));
|
return ToUniTask(asyncOperation, cancellationToken: cancellationToken);
|
||||||
if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<#= IsVoid(t) ? "" : "<" + t.returnType + ">" #>(cancellationToken);
|
|
||||||
<# if(IsUnityWebRequest(t)) { #>
|
|
||||||
if (asyncOperation.isDone)
|
|
||||||
{
|
|
||||||
if (asyncOperation.webRequest.IsError())
|
|
||||||
{
|
|
||||||
return UniTask.FromException<UnityWebRequest>(new UnityWebRequestException(asyncOperation.webRequest));
|
|
||||||
}
|
|
||||||
return UniTask.FromResult(asyncOperation.webRequest);
|
|
||||||
}
|
|
||||||
<# } else { #>
|
|
||||||
if (asyncOperation.isDone) return <#= IsVoid(t) ? "UniTask.CompletedTask" : $"UniTask.FromResult(asyncOperation.{t.returnField})" #>;
|
|
||||||
<# } #>
|
|
||||||
return new <#= ToUniTaskReturnType(t.returnType) #>(<#= t.typeName #>WithCancellationSource.Create(asyncOperation, cancellationToken, out var token), token);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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) #> ToUniTask(this <#= t.typeName #> asyncOperation, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
@@ -151,150 +137,6 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class <#= t.typeName #>WithCancellationSource : <#= ToIUniTaskSourceReturnType(t.returnType) #>, IPlayerLoopItem, ITaskPoolNode<<#= t.typeName #>WithCancellationSource>
|
|
||||||
{
|
|
||||||
static TaskPool<<#= t.typeName #>WithCancellationSource> pool;
|
|
||||||
<#= t.typeName #>WithCancellationSource nextNode;
|
|
||||||
public ref <#= t.typeName #>WithCancellationSource NextNode => ref nextNode;
|
|
||||||
|
|
||||||
static <#= t.typeName #>WithCancellationSource()
|
|
||||||
{
|
|
||||||
TaskPool.RegisterSizeGetter(typeof(<#= t.typeName #>WithCancellationSource), () => pool.Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
readonly Action<AsyncOperation> continuationAction;
|
|
||||||
<#= t.typeName #> asyncOperation;
|
|
||||||
CancellationToken cancellationToken;
|
|
||||||
bool completed;
|
|
||||||
|
|
||||||
UniTaskCompletionSourceCore<<#= IsVoid(t) ? "AsyncUnit" : t.returnType #>> core;
|
|
||||||
|
|
||||||
<#= t.typeName #>WithCancellationSource()
|
|
||||||
{
|
|
||||||
continuationAction = Continuation;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <#= ToIUniTaskSourceReturnType(t.returnType) #> Create(<#= t.typeName #> asyncOperation, CancellationToken cancellationToken, out short token)
|
|
||||||
{
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
return AutoResetUniTaskCompletionSource<#= IsVoid(t) ? "" : $"<{t.returnType}>" #>.CreateFromCanceled(cancellationToken, out token);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pool.TryPop(out var result))
|
|
||||||
{
|
|
||||||
result = new <#= t.typeName #>WithCancellationSource();
|
|
||||||
}
|
|
||||||
|
|
||||||
result.asyncOperation = asyncOperation;
|
|
||||||
result.cancellationToken = cancellationToken;
|
|
||||||
result.completed = false;
|
|
||||||
|
|
||||||
TaskTracker.TrackActiveTask(result, 3);
|
|
||||||
|
|
||||||
PlayerLoopHelper.AddAction(PlayerLoopTiming.Update, result);
|
|
||||||
|
|
||||||
asyncOperation.completed += result.continuationAction;
|
|
||||||
|
|
||||||
token = result.core.Version;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Continuation(AsyncOperation _)
|
|
||||||
{
|
|
||||||
asyncOperation.completed -= continuationAction;
|
|
||||||
|
|
||||||
if (completed)
|
|
||||||
{
|
|
||||||
TryReturn();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
completed = true;
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
core.TrySetCanceled(cancellationToken);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
<# if(IsUnityWebRequest(t)) { #>
|
|
||||||
var result = asyncOperation.webRequest;
|
|
||||||
if (result.IsError())
|
|
||||||
{
|
|
||||||
core.TrySetException(new UnityWebRequestException(result));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
core.TrySetResult(result);
|
|
||||||
}
|
|
||||||
<# } else { #>
|
|
||||||
core.TrySetResult(<#= IsVoid(t) ? "AsyncUnit.Default" : $"asyncOperation.{t.returnField}" #>);
|
|
||||||
<# } #>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public <#= t.returnType #> GetResult(short token)
|
|
||||||
{
|
|
||||||
<# if (!IsVoid(t)) { #>
|
|
||||||
return core.GetResult(token);
|
|
||||||
<# } else { #>
|
|
||||||
core.GetResult(token);
|
|
||||||
<# } #>
|
|
||||||
}
|
|
||||||
|
|
||||||
<# if (!IsVoid(t)) { #>
|
|
||||||
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()
|
|
||||||
{
|
|
||||||
if (completed)
|
|
||||||
{
|
|
||||||
TryReturn();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
completed = true;
|
|
||||||
<# if(IsUnityWebRequest(t)) { #>
|
|
||||||
asyncOperation.webRequest.Abort();
|
|
||||||
<# } #>
|
|
||||||
core.TrySetCanceled(cancellationToken);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TryReturn()
|
|
||||||
{
|
|
||||||
TaskTracker.RemoveTracking(this);
|
|
||||||
core.Reset();
|
|
||||||
asyncOperation = default;
|
|
||||||
cancellationToken = default;
|
|
||||||
return pool.TryPush(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class <#= t.typeName #>ConfiguredSource : <#= ToIUniTaskSourceReturnType(t.returnType) #>, IPlayerLoopItem, ITaskPoolNode<<#= t.typeName #>ConfiguredSource>
|
sealed class <#= t.typeName #>ConfiguredSource : <#= ToIUniTaskSourceReturnType(t.returnType) #>, IPlayerLoopItem, ITaskPoolNode<<#= t.typeName #>ConfiguredSource>
|
||||||
{
|
{
|
||||||
static TaskPool<<#= t.typeName #>ConfiguredSource> pool;
|
static TaskPool<<#= t.typeName #>ConfiguredSource> pool;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#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
|
||||||
|
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
@@ -364,6 +364,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
public AsyncUnityEventHandler(UnityEvent unityEvent, CancellationToken cancellationToken, bool callOnce)
|
public AsyncUnityEventHandler(UnityEvent unityEvent, CancellationToken cancellationToken, bool callOnce)
|
||||||
{
|
{
|
||||||
|
this.cancellationToken = cancellationToken;
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
isDisposed = true;
|
isDisposed = true;
|
||||||
@@ -372,7 +373,6 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
this.action = Invoke;
|
this.action = Invoke;
|
||||||
this.unityEvent = unityEvent;
|
this.unityEvent = unityEvent;
|
||||||
this.cancellationToken = cancellationToken;
|
|
||||||
this.callOnce = callOnce;
|
this.callOnce = callOnce;
|
||||||
|
|
||||||
unityEvent.AddListener(action);
|
unityEvent.AddListener(action);
|
||||||
@@ -388,6 +388,10 @@ namespace Cysharp.Threading.Tasks
|
|||||||
public UniTask OnInvokeAsync()
|
public UniTask OnInvokeAsync()
|
||||||
{
|
{
|
||||||
core.Reset();
|
core.Reset();
|
||||||
|
if (isDisposed)
|
||||||
|
{
|
||||||
|
core.TrySetCanceled(this.cancellationToken);
|
||||||
|
}
|
||||||
return new UniTask(this, core.Version);
|
return new UniTask(this, core.Version);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -470,6 +474,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
public AsyncUnityEventHandler(UnityEvent<T> unityEvent, CancellationToken cancellationToken, bool callOnce)
|
public AsyncUnityEventHandler(UnityEvent<T> unityEvent, CancellationToken cancellationToken, bool callOnce)
|
||||||
{
|
{
|
||||||
|
this.cancellationToken = cancellationToken;
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
isDisposed = true;
|
isDisposed = true;
|
||||||
@@ -478,7 +483,6 @@ namespace Cysharp.Threading.Tasks
|
|||||||
|
|
||||||
this.action = Invoke;
|
this.action = Invoke;
|
||||||
this.unityEvent = unityEvent;
|
this.unityEvent = unityEvent;
|
||||||
this.cancellationToken = cancellationToken;
|
|
||||||
this.callOnce = callOnce;
|
this.callOnce = callOnce;
|
||||||
|
|
||||||
unityEvent.AddListener(action);
|
unityEvent.AddListener(action);
|
||||||
@@ -494,6 +498,10 @@ namespace Cysharp.Threading.Tasks
|
|||||||
public UniTask<T> OnInvokeAsync()
|
public UniTask<T> OnInvokeAsync()
|
||||||
{
|
{
|
||||||
core.Reset();
|
core.Reset();
|
||||||
|
if (isDisposed)
|
||||||
|
{
|
||||||
|
core.TrySetCanceled(this.cancellationToken);
|
||||||
|
}
|
||||||
return new UniTask<T>(this, core.Version);
|
return new UniTask<T>(this, core.Version);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -813,4 +821,6 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,12 +1,15 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
#if !UNITY_2019_1_OR_NEWER || UNITASK_UGUI_SUPPORT
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Cysharp.Threading.Tasks
|
namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
public static class UnityBindingExtensions
|
public static class UnityBindingExtensions
|
||||||
{
|
{
|
||||||
|
#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, Text text, bool rebindOnError = true)
|
||||||
@@ -180,6 +183,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// <T> -> Action
|
// <T> -> Action
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#if ENABLE_UNITYWEBREQUEST
|
#if ENABLE_UNITYWEBREQUEST && (!UNITY_2019_1_OR_NEWER || UNITASK_WEBREQUEST_SUPPORT)
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using UnityEngine.Networking;
|
using UnityEngine.Networking;
|
||||||
|
|
||||||
namespace Cysharp.Threading.Tasks
|
namespace Cysharp.Threading.Tasks
|
||||||
@@ -17,6 +18,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
public string Error { get; }
|
public string Error { get; }
|
||||||
public string Text { get; }
|
public string Text { get; }
|
||||||
public long ResponseCode { get; }
|
public long ResponseCode { get; }
|
||||||
|
public Dictionary<string, string> ResponseHeaders { get; }
|
||||||
|
|
||||||
string msg;
|
string msg;
|
||||||
|
|
||||||
@@ -38,6 +40,7 @@ namespace Cysharp.Threading.Tasks
|
|||||||
this.Text = dhb.text;
|
this.Text = dhb.text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.ResponseHeaders = unityWebRequest.GetResponseHeaders();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Message
|
public override string Message
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "com.cysharp.unitask",
|
"name": "com.cysharp.unitask",
|
||||||
"displayName": "UniTask",
|
"displayName": "UniTask",
|
||||||
"version": "2.0.35",
|
"version": "2.2.2",
|
||||||
"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" ],
|
||||||
|
|||||||
44
src/UniTask/Assets/Scenes/EditorTest1.cs
Normal file
44
src/UniTask/Assets/Scenes/EditorTest1.cs
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
#if UNITY_EDITOR
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
public class Test1
|
||||||
|
{
|
||||||
|
[MenuItem("Test/Test1")]
|
||||||
|
public static async UniTaskVoid TestFunc()
|
||||||
|
{
|
||||||
|
await DoSomeThing();
|
||||||
|
//string[] scenes = new string[]
|
||||||
|
//{
|
||||||
|
// "Assets/Scenes/SandboxMain.unity",
|
||||||
|
//};
|
||||||
|
|
||||||
|
//try
|
||||||
|
//{
|
||||||
|
// Debug.Log("Build Begin");
|
||||||
|
// BuildPipeline.BuildPlayer(scenes, Application.dataPath + "../target", BuildTarget.StandaloneWindows, BuildOptions.CompressWithLz4);
|
||||||
|
// Debug.Log("Build After");
|
||||||
|
//}
|
||||||
|
//catch (Exception e)
|
||||||
|
//{
|
||||||
|
// Debug.LogError(e.Message);
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async UniTask DoSomeThing()
|
||||||
|
{
|
||||||
|
Debug.Log("Dosomething");
|
||||||
|
await UniTask.Delay(1500, DelayType.DeltaTime);
|
||||||
|
Debug.Log("Dosomething 2");
|
||||||
|
await UniTask.Delay(1000, DelayType.DeltaTime);
|
||||||
|
Debug.Log("Dosomething 3");
|
||||||
|
Debug.Log("and Quit.");
|
||||||
|
|
||||||
|
Environment.Exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
11
src/UniTask/Assets/Scenes/EditorTest1.cs.meta
Normal file
11
src/UniTask/Assets/Scenes/EditorTest1.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 48003021292963e48b2493e915dca5ac
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -1,471 +1,471 @@
|
|||||||
using Cysharp.Threading.Tasks;
|
//using Cysharp.Threading.Tasks;
|
||||||
using System;
|
//using System;
|
||||||
using System.Collections.Generic;
|
//using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
//using System.Diagnostics;
|
||||||
using System.Linq;
|
//using System.Linq;
|
||||||
using System.Text;
|
//using System.Text;
|
||||||
using System.Threading;
|
//using System.Threading;
|
||||||
using System.Threading.Tasks;
|
//using System.Threading.Tasks;
|
||||||
using UnityEngine;
|
//using UnityEngine;
|
||||||
using UnityEngine.Networking;
|
//using UnityEngine.Networking;
|
||||||
using UnityEngine.SceneManagement;
|
//using UnityEngine.SceneManagement;
|
||||||
using UnityEngine.UI;
|
//using UnityEngine.UI;
|
||||||
|
|
||||||
namespace Cysharp.Threading.Tasks.Sample
|
//namespace Cysharp.Threading.Tasks.Sample
|
||||||
{
|
//{
|
||||||
//public class Sample2
|
// //public class Sample2
|
||||||
//{
|
// //{
|
||||||
// public Sample2()
|
// // public Sample2()
|
||||||
// {
|
// // {
|
||||||
// // デコレーターの詰まったClientを生成(これは一度作ったらフィールドに保存可)
|
// // // デコレーターの詰まったClientを生成(これは一度作ったらフィールドに保存可)
|
||||||
// var client = new NetworkClient("http://localhost", TimeSpan.FromSeconds(10),
|
// // var client = new NetworkClient("http://localhost", TimeSpan.FromSeconds(10),
|
||||||
// new QueueRequestDecorator(),
|
// // new QueueRequestDecorator(),
|
||||||
// new LoggingDecorator(),
|
// // new LoggingDecorator(),
|
||||||
// new AppendTokenDecorator(),
|
// // new AppendTokenDecorator(),
|
||||||
// new SetupHeaderDecorator());
|
// // new SetupHeaderDecorator());
|
||||||
|
|
||||||
|
|
||||||
// await client.PostAsync("/User/Register", new { Id = 100 });
|
// // await client.PostAsync("/User/Register", new { Id = 100 });
|
||||||
|
|
||||||
|
|
||||||
// }
|
// // }
|
||||||
//}
|
// //}
|
||||||
|
|
||||||
|
|
||||||
public class ReturnToTitleDecorator : IAsyncDecorator
|
// public class ReturnToTitleDecorator : IAsyncDecorator
|
||||||
{
|
// {
|
||||||
public async UniTask<ResponseContext> SendAsync(RequestContext context, CancellationToken cancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>> next)
|
// public async UniTask<ResponseContext> SendAsync(RequestContext context, CancellationToken cancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>> next)
|
||||||
{
|
// {
|
||||||
try
|
// try
|
||||||
{
|
// {
|
||||||
return await next(context, cancellationToken);
|
// return await next(context, cancellationToken);
|
||||||
}
|
// }
|
||||||
catch (Exception ex)
|
// catch (Exception ex)
|
||||||
{
|
// {
|
||||||
if (ex is OperationCanceledException)
|
// if (ex is OperationCanceledException)
|
||||||
{
|
// {
|
||||||
// キャンセルはきっと想定されている処理なのでそのまんまスルー(呼び出し側でOperationCanceledExceptionとして飛んでいく)
|
// // キャンセルはきっと想定されている処理なのでそのまんまスルー(呼び出し側でOperationCanceledExceptionとして飛んでいく)
|
||||||
throw;
|
// throw;
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (ex is UnityWebRequestException uwe)
|
// if (ex is UnityWebRequestException uwe)
|
||||||
{
|
// {
|
||||||
// ステータスコードを使って、タイトルに戻す例外です、とかリトライさせる例外です、とかハンドリングさせると便利
|
// // ステータスコードを使って、タイトルに戻す例外です、とかリトライさせる例外です、とかハンドリングさせると便利
|
||||||
// if (uwe.ResponseCode) { }...
|
// // if (uwe.ResponseCode) { }...
|
||||||
}
|
// }
|
||||||
|
|
||||||
// サーバー例外のMessageを直接出すなんて乱暴なことはデバッグ時だけですよ勿論。
|
// // サーバー例外のMessageを直接出すなんて乱暴なことはデバッグ時だけですよ勿論。
|
||||||
var result = await MessageDialog.ShowAsync(ex.Message);
|
// var result = await MessageDialog.ShowAsync(ex.Message);
|
||||||
|
|
||||||
// OK か Cancelかで分岐するなら。今回はボタン一個、OKのみの想定なので無視
|
// // OK か Cancelかで分岐するなら。今回はボタン一個、OKのみの想定なので無視
|
||||||
// if (result == DialogResult.Ok) { }...
|
// // if (result == DialogResult.Ok) { }...
|
||||||
|
|
||||||
// シーン呼び出しはawaitしないこと!awaitして正常終了しちゃうと、この通信の呼び出し元に処理が戻って続行してしまいます
|
// // シーン呼び出しはawaitしないこと!awaitして正常終了しちゃうと、この通信の呼び出し元に処理が戻って続行してしまいます
|
||||||
// のでForget。
|
// // のでForget。
|
||||||
SceneManager.LoadSceneAsync("TitleScene").ToUniTask().Forget();
|
// SceneManager.LoadSceneAsync("TitleScene").ToUniTask().Forget();
|
||||||
|
|
||||||
|
|
||||||
// そしてOperationCanceledExceptionを投げて、この通信の呼び出し元の処理はキャンセル扱いにして終了させる
|
// // そしてOperationCanceledExceptionを投げて、この通信の呼び出し元の処理はキャンセル扱いにして終了させる
|
||||||
throw new OperationCanceledException();
|
// throw new OperationCanceledException();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
public enum DialogResult
|
// public enum DialogResult
|
||||||
{
|
// {
|
||||||
Ok,
|
// Ok,
|
||||||
Cancel
|
// Cancel
|
||||||
}
|
// }
|
||||||
|
|
||||||
public static class MessageDialog
|
// public static class MessageDialog
|
||||||
{
|
// {
|
||||||
public static async UniTask<DialogResult> ShowAsync(string message)
|
// public static async UniTask<DialogResult> ShowAsync(string message)
|
||||||
{
|
// {
|
||||||
// (例えば)Prefabで作っておいたダイアログを生成する
|
// // (例えば)Prefabで作っておいたダイアログを生成する
|
||||||
var view = await Resources.LoadAsync("Prefabs/Dialog");
|
// var view = await Resources.LoadAsync("Prefabs/Dialog");
|
||||||
|
|
||||||
// Ok, Cancelボタンのどちらかが押されるのを待機
|
// // Ok, Cancelボタンのどちらかが押されるのを待機
|
||||||
return await (view as GameObject).GetComponent<MessageDialogView>().ClickResult;
|
// return await (view as GameObject).GetComponent<MessageDialogView>().ClickResult;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
public class MessageDialogView : MonoBehaviour
|
// public class MessageDialogView : MonoBehaviour
|
||||||
{
|
// {
|
||||||
[SerializeField] Button okButton = default;
|
// [SerializeField] Button okButton = default;
|
||||||
[SerializeField] Button closeButton = default;
|
// [SerializeField] Button closeButton = default;
|
||||||
|
|
||||||
UniTaskCompletionSource<DialogResult> taskCompletion;
|
// UniTaskCompletionSource<DialogResult> taskCompletion;
|
||||||
|
|
||||||
// これでどちらかが押されるまで無限に待つを表現
|
// // これでどちらかが押されるまで無限に待つを表現
|
||||||
public UniTask<DialogResult> ClickResult => taskCompletion.Task;
|
// public UniTask<DialogResult> ClickResult => taskCompletion.Task;
|
||||||
|
|
||||||
private void Start()
|
// private void Start()
|
||||||
{
|
// {
|
||||||
taskCompletion = new UniTaskCompletionSource<DialogResult>();
|
// taskCompletion = new UniTaskCompletionSource<DialogResult>();
|
||||||
|
|
||||||
okButton.onClick.AddListener(() =>
|
// okButton.onClick.AddListener(() =>
|
||||||
{
|
// {
|
||||||
taskCompletion.TrySetResult(DialogResult.Ok);
|
// taskCompletion.TrySetResult(DialogResult.Ok);
|
||||||
});
|
// });
|
||||||
|
|
||||||
closeButton.onClick.AddListener(() =>
|
// closeButton.onClick.AddListener(() =>
|
||||||
{
|
// {
|
||||||
taskCompletion.TrySetResult(DialogResult.Cancel);
|
// taskCompletion.TrySetResult(DialogResult.Cancel);
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
|
|
||||||
// もしボタンが押されずに消滅した場合にネンノタメ。
|
// // もしボタンが押されずに消滅した場合にネンノタメ。
|
||||||
private void OnDestroy()
|
// private void OnDestroy()
|
||||||
{
|
// {
|
||||||
taskCompletion.TrySetResult(DialogResult.Cancel);
|
// taskCompletion.TrySetResult(DialogResult.Cancel);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
public class MockDecorator : IAsyncDecorator
|
// public class MockDecorator : IAsyncDecorator
|
||||||
{
|
// {
|
||||||
Dictionary<string, object> mock;
|
// Dictionary<string, object> mock;
|
||||||
|
|
||||||
// Pathと型を1:1にして事前定義したオブジェクトを返す辞書を渡す
|
// // Pathと型を1:1にして事前定義したオブジェクトを返す辞書を渡す
|
||||||
public MockDecorator(Dictionary<string, object> mock)
|
// public MockDecorator(Dictionary<string, object> mock)
|
||||||
{
|
// {
|
||||||
this.mock = mock;
|
// this.mock = mock;
|
||||||
}
|
// }
|
||||||
|
|
||||||
public UniTask<ResponseContext> SendAsync(RequestContext context, CancellationToken cancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>> next)
|
// public UniTask<ResponseContext> SendAsync(RequestContext context, CancellationToken cancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>> next)
|
||||||
{
|
// {
|
||||||
if (mock.TryGetValue(context.Path, out var value))
|
// if (mock.TryGetValue(context.Path, out var value))
|
||||||
{
|
// {
|
||||||
// 一致したものがあればそれを返す(実際の通信は行わない)
|
// // 一致したものがあればそれを返す(実際の通信は行わない)
|
||||||
return new UniTask<ResponseContext>(new ResponseContext(value));
|
// return new UniTask<ResponseContext>(new ResponseContext(value));
|
||||||
}
|
// }
|
||||||
else
|
// else
|
||||||
{
|
// {
|
||||||
return next(context, cancellationToken);
|
// return next(context, cancellationToken);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
public class LoggingDecorator : IAsyncDecorator
|
// //public class LoggingDecorator : IAsyncDecorator
|
||||||
{
|
// //{
|
||||||
public async UniTask<ResponseContext> SendAsync(RequestContext context, CancellationToken cancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>> next)
|
// // public async UniTask<ResponseContext> SendAsync(RequestContext context, CancellationToken cancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>> next)
|
||||||
{
|
// // {
|
||||||
var sw = Stopwatch.StartNew();
|
// // var sw = Stopwatch.StartNew();
|
||||||
try
|
// // try
|
||||||
{
|
// // {
|
||||||
UnityEngine.Debug.Log("Start Network Request:" + context.Path);
|
// // UnityEngine.Debug.Log("Start Network Request:" + context.Path);
|
||||||
|
|
||||||
var response = await next(context, cancellationToken);
|
// // var response = await next(context, cancellationToken);
|
||||||
|
|
||||||
UnityEngine.Debug.Log($"Complete Network Request: {context.Path} , Elapsed: {sw.Elapsed}, Size: {response.GetRawData().Length}");
|
// // UnityEngine.Debug.Log($"Complete Network Request: {context.Path} , Elapsed: {sw.Elapsed}, Size: {response.GetRawData().Length}");
|
||||||
|
|
||||||
return response;
|
// // return response;
|
||||||
}
|
// // }
|
||||||
catch (Exception ex)
|
// // catch (Exception ex)
|
||||||
{
|
// // {
|
||||||
if (ex is OperationCanceledException)
|
// // if (ex is OperationCanceledException)
|
||||||
{
|
// // {
|
||||||
UnityEngine.Debug.Log("Request Canceled:" + context.Path);
|
// // UnityEngine.Debug.Log("Request Canceled:" + context.Path);
|
||||||
}
|
// // }
|
||||||
else if (ex is TimeoutException)
|
// // else if (ex is TimeoutException)
|
||||||
{
|
// // {
|
||||||
UnityEngine.Debug.Log("Request Timeout:" + context.Path);
|
// // UnityEngine.Debug.Log("Request Timeout:" + context.Path);
|
||||||
}
|
// // }
|
||||||
else if (ex is UnityWebRequestException webex)
|
// // else if (ex is UnityWebRequestException webex)
|
||||||
{
|
// // {
|
||||||
if (webex.IsHttpError)
|
// // if (webex.IsHttpError)
|
||||||
{
|
// // {
|
||||||
UnityEngine.Debug.Log($"Request HttpError: {context.Path} Code:{webex.ResponseCode} Message:{webex.Message}");
|
// // UnityEngine.Debug.Log($"Request HttpError: {context.Path} Code:{webex.ResponseCode} Message:{webex.Message}");
|
||||||
}
|
// // }
|
||||||
else if (webex.IsNetworkError)
|
// // else if (webex.IsNetworkError)
|
||||||
{
|
// // {
|
||||||
UnityEngine.Debug.Log($"Request NetworkError: {context.Path} Code:{webex.ResponseCode} Message:{webex.Message}");
|
// // UnityEngine.Debug.Log($"Request NetworkError: {context.Path} Code:{webex.ResponseCode} Message:{webex.Message}");
|
||||||
}
|
// // }
|
||||||
}
|
// // }
|
||||||
throw;
|
// // throw;
|
||||||
}
|
// // }
|
||||||
finally
|
// // finally
|
||||||
{
|
// // {
|
||||||
/* log other */
|
// // /* log other */
|
||||||
}
|
// // }
|
||||||
}
|
// // }
|
||||||
}
|
// //}
|
||||||
|
|
||||||
public class SetupHeaderDecorator : IAsyncDecorator
|
// public class SetupHeaderDecorator : IAsyncDecorator
|
||||||
{
|
// {
|
||||||
public async UniTask<ResponseContext> SendAsync(RequestContext context, CancellationToken cancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>> next)
|
// public async UniTask<ResponseContext> SendAsync(RequestContext context, CancellationToken cancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>> next)
|
||||||
{
|
// {
|
||||||
context.RequestHeaders["x-app-timestamp"] = context.Timestamp.ToString();
|
// context.RequestHeaders["x-app-timestamp"] = context.Timestamp.ToString();
|
||||||
context.RequestHeaders["x-user-id"] = "132141411"; // どこかから持ってくる
|
// context.RequestHeaders["x-user-id"] = "132141411"; // どこかから持ってくる
|
||||||
context.RequestHeaders["x-access-token"] = "fafafawfafewaea"; // どこかから持ってくる2
|
// context.RequestHeaders["x-access-token"] = "fafafawfafewaea"; // どこかから持ってくる2
|
||||||
|
|
||||||
var respsonse = await next(context, cancellationToken);
|
// var respsonse = await next(context, cancellationToken);
|
||||||
|
|
||||||
var nextToken = respsonse.ResponseHeaders["token"];
|
// var nextToken = respsonse.ResponseHeaders["token"];
|
||||||
// UserProfile.Token = nextToken; // どこかにセットするということにする
|
// // UserProfile.Token = nextToken; // どこかにセットするということにする
|
||||||
|
|
||||||
return respsonse;
|
// return respsonse;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
public class AppendTokenDecorator : IAsyncDecorator
|
// public class AppendTokenDecorator : IAsyncDecorator
|
||||||
{
|
// {
|
||||||
public async UniTask<ResponseContext> SendAsync(RequestContext context, CancellationToken cancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>> next)
|
// public async UniTask<ResponseContext> SendAsync(RequestContext context, CancellationToken cancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>> next)
|
||||||
{
|
// {
|
||||||
string token = "token"; // どっかから取ってくるということにする
|
// string token = "token"; // どっかから取ってくるということにする
|
||||||
RETRY:
|
// RETRY:
|
||||||
try
|
// try
|
||||||
{
|
// {
|
||||||
context.RequestHeaders["x-accesss-token"] = token;
|
// context.RequestHeaders["x-accesss-token"] = token;
|
||||||
return await next(context, cancellationToken);
|
// return await next(context, cancellationToken);
|
||||||
}
|
// }
|
||||||
catch (UnityWebRequestException ex)
|
// catch (UnityWebRequestException ex)
|
||||||
{
|
// {
|
||||||
// 例えば700はTokenを再取得してください的な意味だったとする
|
// // 例えば700はTokenを再取得してください的な意味だったとする
|
||||||
if (ex.ResponseCode == 700)
|
// if (ex.ResponseCode == 700)
|
||||||
{
|
// {
|
||||||
// 別口でTokenを取得します的な処理
|
// // 別口でTokenを取得します的な処理
|
||||||
var newToken = await new NetworkClient(context.BasePath, context.Timeout).PostAsync<string>("/Auth/GetToken", "access_token", cancellationToken);
|
// var newToken = await new NetworkClient(context.BasePath, context.Timeout).PostAsync<string>("/Auth/GetToken", "access_token", cancellationToken);
|
||||||
context.Reset(this);
|
// context.Reset(this);
|
||||||
goto RETRY;
|
// goto RETRY;
|
||||||
}
|
// }
|
||||||
|
|
||||||
goto RETRY;
|
// goto RETRY;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
public class QueueRequestDecorator : IAsyncDecorator
|
// public class QueueRequestDecorator : IAsyncDecorator
|
||||||
{
|
// {
|
||||||
readonly Queue<(UniTaskCompletionSource<ResponseContext>, RequestContext, CancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>>)> q = new Queue<(UniTaskCompletionSource<ResponseContext>, RequestContext, CancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>>)>();
|
// readonly Queue<(UniTaskCompletionSource<ResponseContext>, RequestContext, CancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>>)> q = new Queue<(UniTaskCompletionSource<ResponseContext>, RequestContext, CancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>>)>();
|
||||||
bool running;
|
// bool running;
|
||||||
|
|
||||||
public async UniTask<ResponseContext> SendAsync(RequestContext context, CancellationToken cancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>> next)
|
// public async UniTask<ResponseContext> SendAsync(RequestContext context, CancellationToken cancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>> next)
|
||||||
{
|
// {
|
||||||
if (q.Count == 0)
|
// if (q.Count == 0)
|
||||||
{
|
// {
|
||||||
return await next(context, cancellationToken);
|
// return await next(context, cancellationToken);
|
||||||
}
|
// }
|
||||||
else
|
// else
|
||||||
{
|
// {
|
||||||
var completionSource = new UniTaskCompletionSource<ResponseContext>();
|
// var completionSource = new UniTaskCompletionSource<ResponseContext>();
|
||||||
q.Enqueue((completionSource, context, cancellationToken, next));
|
// q.Enqueue((completionSource, context, cancellationToken, next));
|
||||||
if (!running)
|
// if (!running)
|
||||||
{
|
// {
|
||||||
Run().Forget();
|
// Run().Forget();
|
||||||
}
|
// }
|
||||||
return await completionSource.Task;
|
// return await completionSource.Task;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
async UniTaskVoid Run()
|
// async UniTaskVoid Run()
|
||||||
{
|
// {
|
||||||
running = true;
|
// running = true;
|
||||||
try
|
// try
|
||||||
{
|
// {
|
||||||
while (q.Count != 0)
|
// while (q.Count != 0)
|
||||||
{
|
// {
|
||||||
var (tcs, context, cancellationToken, next) = q.Dequeue();
|
// var (tcs, context, cancellationToken, next) = q.Dequeue();
|
||||||
try
|
// try
|
||||||
{
|
// {
|
||||||
var response = await next(context, cancellationToken);
|
// var response = await next(context, cancellationToken);
|
||||||
tcs.TrySetResult(response);
|
// tcs.TrySetResult(response);
|
||||||
}
|
// }
|
||||||
catch (Exception ex)
|
// catch (Exception ex)
|
||||||
{
|
// {
|
||||||
tcs.TrySetException(ex);
|
// tcs.TrySetException(ex);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
finally
|
// finally
|
||||||
{
|
// {
|
||||||
running = false;
|
// running = false;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
public class RequestContext
|
// public class RequestContext
|
||||||
{
|
// {
|
||||||
int decoratorIndex;
|
// int decoratorIndex;
|
||||||
readonly IAsyncDecorator[] decorators;
|
// readonly IAsyncDecorator[] decorators;
|
||||||
Dictionary<string, string> headers;
|
// Dictionary<string, string> headers;
|
||||||
|
|
||||||
public string BasePath { get; }
|
// public string BasePath { get; }
|
||||||
public string Path { get; }
|
// public string Path { get; }
|
||||||
public object Value { get; }
|
// public object Value { get; }
|
||||||
public TimeSpan Timeout { get; }
|
// public TimeSpan Timeout { get; }
|
||||||
public DateTimeOffset Timestamp { get; private set; }
|
// public DateTimeOffset Timestamp { get; private set; }
|
||||||
|
|
||||||
public IDictionary<string, string> RequestHeaders
|
// public IDictionary<string, string> RequestHeaders
|
||||||
{
|
// {
|
||||||
get
|
// get
|
||||||
{
|
// {
|
||||||
if (headers == null)
|
// if (headers == null)
|
||||||
{
|
// {
|
||||||
headers = new Dictionary<string, string>();
|
// headers = new Dictionary<string, string>();
|
||||||
}
|
// }
|
||||||
return headers;
|
// return headers;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
public RequestContext(string basePath, string path, object value, TimeSpan timeout, IAsyncDecorator[] filters)
|
// public RequestContext(string basePath, string path, object value, TimeSpan timeout, IAsyncDecorator[] filters)
|
||||||
{
|
// {
|
||||||
this.decoratorIndex = -1;
|
// this.decoratorIndex = -1;
|
||||||
this.decorators = filters;
|
// this.decorators = filters;
|
||||||
this.BasePath = basePath;
|
// this.BasePath = basePath;
|
||||||
this.Path = path;
|
// this.Path = path;
|
||||||
this.Value = value;
|
// this.Value = value;
|
||||||
this.Timeout = timeout;
|
// this.Timeout = timeout;
|
||||||
this.Timestamp = DateTimeOffset.UtcNow;
|
// this.Timestamp = DateTimeOffset.UtcNow;
|
||||||
}
|
// }
|
||||||
|
|
||||||
internal Dictionary<string, string> GetRawHeaders() => headers;
|
// internal Dictionary<string, string> GetRawHeaders() => headers;
|
||||||
internal IAsyncDecorator GetNextDecorator() => decorators[++decoratorIndex];
|
// internal IAsyncDecorator GetNextDecorator() => decorators[++decoratorIndex];
|
||||||
|
|
||||||
public void Reset(IAsyncDecorator currentFilter)
|
// public void Reset(IAsyncDecorator currentFilter)
|
||||||
{
|
// {
|
||||||
decoratorIndex = Array.IndexOf(decorators, currentFilter);
|
// decoratorIndex = Array.IndexOf(decorators, currentFilter);
|
||||||
if (headers != null)
|
// if (headers != null)
|
||||||
{
|
// {
|
||||||
headers.Clear();
|
// headers.Clear();
|
||||||
}
|
// }
|
||||||
Timestamp = DateTimeOffset.UtcNow;
|
// Timestamp = DateTimeOffset.UtcNow;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
public class ResponseContext
|
// public class ResponseContext
|
||||||
{
|
// {
|
||||||
bool hasValue;
|
// bool hasValue;
|
||||||
object value;
|
// object value;
|
||||||
readonly byte[] bytes;
|
// readonly byte[] bytes;
|
||||||
|
|
||||||
public long StatusCode { get; }
|
// public long StatusCode { get; }
|
||||||
public Dictionary<string, string> ResponseHeaders { get; }
|
// public Dictionary<string, string> ResponseHeaders { get; }
|
||||||
|
|
||||||
public ResponseContext(object value, Dictionary<string, string> header = null)
|
// public ResponseContext(object value, Dictionary<string, string> header = null)
|
||||||
{
|
// {
|
||||||
this.hasValue = true;
|
// this.hasValue = true;
|
||||||
this.value = value;
|
// this.value = value;
|
||||||
this.StatusCode = 200;
|
// this.StatusCode = 200;
|
||||||
this.ResponseHeaders = (header ?? new Dictionary<string, string>());
|
// this.ResponseHeaders = (header ?? new Dictionary<string, string>());
|
||||||
}
|
// }
|
||||||
|
|
||||||
public ResponseContext(byte[] bytes, long statusCode, Dictionary<string, string> responseHeaders)
|
// public ResponseContext(byte[] bytes, long statusCode, Dictionary<string, string> responseHeaders)
|
||||||
{
|
// {
|
||||||
this.hasValue = false;
|
// this.hasValue = false;
|
||||||
this.bytes = bytes;
|
// this.bytes = bytes;
|
||||||
this.StatusCode = statusCode;
|
// this.StatusCode = statusCode;
|
||||||
this.ResponseHeaders = responseHeaders;
|
// this.ResponseHeaders = responseHeaders;
|
||||||
}
|
// }
|
||||||
|
|
||||||
public byte[] GetRawData() => bytes;
|
// public byte[] GetRawData() => bytes;
|
||||||
|
|
||||||
public T GetResponseAs<T>()
|
// public T GetResponseAs<T>()
|
||||||
{
|
// {
|
||||||
if (hasValue)
|
// if (hasValue)
|
||||||
{
|
// {
|
||||||
return (T)value;
|
// return (T)value;
|
||||||
}
|
// }
|
||||||
|
|
||||||
value = JsonUtility.FromJson<T>(Encoding.UTF8.GetString(bytes));
|
// value = JsonUtility.FromJson<T>(Encoding.UTF8.GetString(bytes));
|
||||||
hasValue = true;
|
// hasValue = true;
|
||||||
return (T)value;
|
// return (T)value;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
public interface IAsyncDecorator
|
// public interface IAsyncDecorator
|
||||||
{
|
// {
|
||||||
UniTask<ResponseContext> SendAsync(RequestContext context, CancellationToken cancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>> next);
|
// UniTask<ResponseContext> SendAsync(RequestContext context, CancellationToken cancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>> next);
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
public class NetworkClient : IAsyncDecorator
|
// public class NetworkClient : IAsyncDecorator
|
||||||
{
|
// {
|
||||||
readonly Func<RequestContext, CancellationToken, UniTask<ResponseContext>> next;
|
// readonly Func<RequestContext, CancellationToken, UniTask<ResponseContext>> next;
|
||||||
readonly IAsyncDecorator[] decorators;
|
// readonly IAsyncDecorator[] decorators;
|
||||||
readonly TimeSpan timeout;
|
// readonly TimeSpan timeout;
|
||||||
readonly IProgress<float> progress;
|
// readonly IProgress<float> progress;
|
||||||
readonly string basePath;
|
// readonly string basePath;
|
||||||
|
|
||||||
public NetworkClient(string basePath, TimeSpan timeout, params IAsyncDecorator[] decorators)
|
// public NetworkClient(string basePath, TimeSpan timeout, params IAsyncDecorator[] decorators)
|
||||||
: this(basePath, timeout, null, decorators)
|
// : this(basePath, timeout, null, decorators)
|
||||||
{
|
// {
|
||||||
}
|
// }
|
||||||
|
|
||||||
public NetworkClient(string basePath, TimeSpan timeout, IProgress<float> progress, params IAsyncDecorator[] decorators)
|
// public NetworkClient(string basePath, TimeSpan timeout, IProgress<float> progress, params IAsyncDecorator[] decorators)
|
||||||
{
|
// {
|
||||||
this.next = InvokeRecursive; // setup delegate
|
// this.next = InvokeRecursive; // setup delegate
|
||||||
|
|
||||||
this.basePath = basePath;
|
// this.basePath = basePath;
|
||||||
this.timeout = timeout;
|
// this.timeout = timeout;
|
||||||
this.progress = progress;
|
// this.progress = progress;
|
||||||
this.decorators = new IAsyncDecorator[decorators.Length + 1];
|
// this.decorators = new IAsyncDecorator[decorators.Length + 1];
|
||||||
Array.Copy(decorators, this.decorators, decorators.Length);
|
// Array.Copy(decorators, this.decorators, decorators.Length);
|
||||||
this.decorators[this.decorators.Length - 1] = this;
|
// this.decorators[this.decorators.Length - 1] = this;
|
||||||
}
|
// }
|
||||||
|
|
||||||
public async UniTask<T> PostAsync<T>(string path, T value, CancellationToken cancellationToken = default)
|
// public async UniTask<T> PostAsync<T>(string path, T value, CancellationToken cancellationToken = default)
|
||||||
{
|
// {
|
||||||
var request = new RequestContext(basePath, path, value, timeout, decorators);
|
// var request = new RequestContext(basePath, path, value, timeout, decorators);
|
||||||
var response = await InvokeRecursive(request, cancellationToken);
|
// var response = await InvokeRecursive(request, cancellationToken);
|
||||||
return response.GetResponseAs<T>();
|
// return response.GetResponseAs<T>();
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
UniTask<ResponseContext> InvokeRecursive(RequestContext context, CancellationToken cancellationToken)
|
// UniTask<ResponseContext> InvokeRecursive(RequestContext context, CancellationToken cancellationToken)
|
||||||
{
|
// {
|
||||||
return context.GetNextDecorator().SendAsync(context, cancellationToken, next); // マジカル再帰処理
|
// return context.GetNextDecorator().SendAsync(context, cancellationToken, next); // マジカル再帰処理
|
||||||
}
|
// }
|
||||||
|
|
||||||
async UniTask<ResponseContext> IAsyncDecorator.SendAsync(RequestContext context, CancellationToken cancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>> _)
|
// async UniTask<ResponseContext> IAsyncDecorator.SendAsync(RequestContext context, CancellationToken cancellationToken, Func<RequestContext, CancellationToken, UniTask<ResponseContext>> _)
|
||||||
{
|
// {
|
||||||
// Postしか興味ないからPostにしかしないよ!
|
// // Postしか興味ないからPostにしかしないよ!
|
||||||
// パフォーマンスを最大限にしたい場合はuploadHandler, downloadHandlerをカスタマイズすること
|
// // パフォーマンスを最大限にしたい場合はuploadHandler, downloadHandlerをカスタマイズすること
|
||||||
|
|
||||||
// JSONでbodyに送るというパラメータで送るという雑設定。
|
// // JSONでbodyに送るというパラメータで送るという雑設定。
|
||||||
var data = JsonUtility.ToJson(context.Value);
|
// var data = JsonUtility.ToJson(context.Value);
|
||||||
var formData = new Dictionary<string, string> { { "body", data } };
|
// var formData = new Dictionary<string, string> { { "body", data } };
|
||||||
|
|
||||||
using (var req = UnityWebRequest.Post(basePath + context.Path, formData))
|
// using (var req = UnityWebRequest.Post(basePath + context.Path, formData))
|
||||||
{
|
// {
|
||||||
var header = context.GetRawHeaders();
|
// var header = context.GetRawHeaders();
|
||||||
if (header != null)
|
// if (header != null)
|
||||||
{
|
// {
|
||||||
foreach (var item in header)
|
// foreach (var item in header)
|
||||||
{
|
// {
|
||||||
req.SetRequestHeader(item.Key, item.Value);
|
// req.SetRequestHeader(item.Key, item.Value);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Timeout処理はCancellationTokenSourceのCancelAfterSlim(UniTask拡張)を使ってサクッと処理
|
// // Timeout処理はCancellationTokenSourceのCancelAfterSlim(UniTask拡張)を使ってサクッと処理
|
||||||
var linkToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
|
// var linkToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
|
||||||
linkToken.CancelAfterSlim(timeout);
|
// linkToken.CancelAfterSlim(timeout);
|
||||||
try
|
// try
|
||||||
{
|
// {
|
||||||
// 完了待ちや終了処理はUniTaskの拡張自体に丸投げ
|
// // 完了待ちや終了処理はUniTaskの拡張自体に丸投げ
|
||||||
await req.SendWebRequest().ToUniTask(progress: progress, cancellationToken: linkToken.Token);
|
// await req.SendWebRequest().ToUniTask(progress: progress, cancellationToken: linkToken.Token);
|
||||||
}
|
// }
|
||||||
catch (OperationCanceledException)
|
// catch (OperationCanceledException)
|
||||||
{
|
// {
|
||||||
// 元キャンセレーションソースがキャンセルしてなければTimeoutによるものと判定
|
// // 元キャンセレーションソースがキャンセルしてなければTimeoutによるものと判定
|
||||||
if (!cancellationToken.IsCancellationRequested)
|
// if (!cancellationToken.IsCancellationRequested)
|
||||||
{
|
// {
|
||||||
throw new TimeoutException();
|
// throw new TimeoutException();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
finally
|
// finally
|
||||||
{
|
// {
|
||||||
// Timeoutに引っかからなかった場合にてるのでCancelAfterSlimの裏で回ってるループをこれで終わらせとく
|
// // Timeoutに引っかからなかった場合にてるのでCancelAfterSlimの裏で回ってるループをこれで終わらせとく
|
||||||
if (!linkToken.IsCancellationRequested)
|
// if (!linkToken.IsCancellationRequested)
|
||||||
{
|
// {
|
||||||
linkToken.Cancel();
|
// linkToken.Cancel();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
// UnityWebRequestを先にDisposeしちゃうので先に必要なものを取得しておく(性能的には無駄なのでパフォーマンスを最大限にしたい場合は更に一工夫を)
|
// // UnityWebRequestを先にDisposeしちゃうので先に必要なものを取得しておく(性能的には無駄なのでパフォーマンスを最大限にしたい場合は更に一工夫を)
|
||||||
return new ResponseContext(req.downloadHandler.data, req.responseCode, req.GetResponseHeaders());
|
// return new ResponseContext(req.downloadHandler.data, req.responseCode, req.GetResponseHeaders());
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
@@ -18,7 +18,6 @@ using UnityEngine.SceneManagement;
|
|||||||
using UnityEngine.Rendering;
|
using UnityEngine.Rendering;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using Cysharp.Threading.Tasks.Sample;
|
|
||||||
|
|
||||||
|
|
||||||
// using DG.Tweening;
|
// using DG.Tweening;
|
||||||
@@ -269,32 +268,33 @@ public class SandboxMain : MonoBehaviour
|
|||||||
|
|
||||||
async Task Test1()
|
async Task Test1()
|
||||||
{
|
{
|
||||||
var r = await TcsAsync("https://bing.com/");
|
// var r = await TcsAsync("https://bing.com/");
|
||||||
|
await Task.Yield();
|
||||||
Debug.Log("TASKASYNC");
|
Debug.Log("TASKASYNC");
|
||||||
}
|
}
|
||||||
|
|
||||||
async UniTaskVoid Test2()
|
//async UniTaskVoid Test2()
|
||||||
{
|
//{
|
||||||
try
|
// try
|
||||||
{
|
// {
|
||||||
//var cts = new CancellationTokenSource();
|
// //var cts = new CancellationTokenSource();
|
||||||
//var r = UniAsync("https://bing.com/", cts.Token);
|
// //var r = UniAsync("https://bing.com/", cts.Token);
|
||||||
//cts.Cancel();
|
// //cts.Cancel();
|
||||||
//await r;
|
// //await r;
|
||||||
Debug.Log("SendWebRequestDone:" + PlayerLoopInfo.CurrentLoopType);
|
// Debug.Log("SendWebRequestDone:" + PlayerLoopInfo.CurrentLoopType);
|
||||||
|
|
||||||
|
|
||||||
// var foo = await UnityWebRequest.Get("https://bing.com/").SendWebRequest();
|
// // var foo = await UnityWebRequest.Get("https://bing.com/").SendWebRequest();
|
||||||
// foo.downloadHandler.text;
|
// // foo.downloadHandler.text;
|
||||||
//
|
// //
|
||||||
_ = await UnityWebRequest.Get("https://bing.com/").SendWebRequest().WithCancellation(CancellationToken.None);
|
// _ = await UnityWebRequest.Get("https://bing.com/").SendWebRequest().WithCancellation(CancellationToken.None);
|
||||||
Debug.Log("SendWebRequestWithCancellationDone:" + PlayerLoopInfo.CurrentLoopType);
|
// Debug.Log("SendWebRequestWithCancellationDone:" + PlayerLoopInfo.CurrentLoopType);
|
||||||
}
|
// }
|
||||||
catch
|
// catch
|
||||||
{
|
// {
|
||||||
Debug.Log("Canceled");
|
// Debug.Log("Canceled");
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
||||||
IEnumerator Test3(string url)
|
IEnumerator Test3(string url)
|
||||||
{
|
{
|
||||||
@@ -303,17 +303,17 @@ public class SandboxMain : MonoBehaviour
|
|||||||
Debug.Log("COROUTINE");
|
Debug.Log("COROUTINE");
|
||||||
}
|
}
|
||||||
|
|
||||||
static async Task<UnityWebRequest> TcsAsync(string url)
|
//static async Task<UnityWebRequest> TcsAsync(string url)
|
||||||
{
|
//{
|
||||||
var req = await UnityWebRequest.Get(url).SendWebRequest();
|
// var req = await UnityWebRequest.Get(url).SendWebRequest();
|
||||||
return req;
|
// return req;
|
||||||
}
|
//}
|
||||||
|
|
||||||
static async UniTask<UnityWebRequest> UniAsync(string url, CancellationToken cancellationToken)
|
//static async UniTask<UnityWebRequest> UniAsync(string url, CancellationToken cancellationToken)
|
||||||
{
|
//{
|
||||||
var req = await UnityWebRequest.Get(url).SendWebRequest().WithCancellation(cancellationToken);
|
// var req = await UnityWebRequest.Get(url).SendWebRequest().WithCancellation(cancellationToken);
|
||||||
return req;
|
// return req;
|
||||||
}
|
//}
|
||||||
|
|
||||||
async Task<int> Test()
|
async Task<int> Test()
|
||||||
{
|
{
|
||||||
@@ -428,15 +428,15 @@ public class SandboxMain : MonoBehaviour
|
|||||||
Debug.Log("after");
|
Debug.Log("after");
|
||||||
}
|
}
|
||||||
|
|
||||||
private async UniTaskVoid ExecuteAsync()
|
//private async UniTaskVoid ExecuteAsync()
|
||||||
{
|
//{
|
||||||
var req = UnityWebRequest.Get("https://google.com/");
|
// var req = UnityWebRequest.Get("https://google.com/");
|
||||||
|
|
||||||
var v = await req.SendWebRequest().ToUniTask();
|
// var v = await req.SendWebRequest().ToUniTask();
|
||||||
// req.Dispose();
|
// // req.Dispose();
|
||||||
Debug.Log($"{v.isDone} {v.isHttpError} {v.isNetworkError}");
|
// Debug.Log($"{v.isDone} {v.isHttpError} {v.isNetworkError}");
|
||||||
Debug.Log(v.downloadHandler.text);
|
// Debug.Log(v.downloadHandler.text);
|
||||||
}
|
//}
|
||||||
private async void Go()
|
private async void Go()
|
||||||
{
|
{
|
||||||
await UniTask.DelayFrame(0);
|
await UniTask.DelayFrame(0);
|
||||||
@@ -507,258 +507,149 @@ public class SandboxMain : MonoBehaviour
|
|||||||
|
|
||||||
CancellationTokenSource quitSource = new CancellationTokenSource();
|
CancellationTokenSource quitSource = new CancellationTokenSource();
|
||||||
|
|
||||||
|
|
||||||
|
IEnumerator TestCor()
|
||||||
|
{
|
||||||
|
Debug.Log("start cor");
|
||||||
|
yield return null;
|
||||||
|
yield return new WaitForEndOfFrame();
|
||||||
|
Debug.Log("end cor");
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator LastYieldCore()
|
||||||
|
{
|
||||||
|
Debug.Log("YieldBegin:" + Time.frameCount);
|
||||||
|
yield return new WaitForEndOfFrame();
|
||||||
|
Debug.Log("YieldEnd:" + Time.frameCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async UniTask TestAsync(CancellationToken ct)
|
||||||
|
{
|
||||||
|
Debug.Log("TestAsync Start.");
|
||||||
|
var count = 0;
|
||||||
|
while (!ct.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Debug.Log($"TestAsync try count:{++count}");
|
||||||
|
var task1 = new WaitUntil(() => UnityEngine.Random.Range(0, 10) == 0).ToUniTask();
|
||||||
|
var task2 = new WaitUntil(() => UnityEngine.Random.Range(0, 10) == 0).ToUniTask();
|
||||||
|
var task3 = new WaitUntil(() => UnityEngine.Random.Range(0, 10) == 0).ToUniTask();
|
||||||
|
|
||||||
|
await UniTask.WhenAny(task1, task2, task3);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogError(e);
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Debug.Log("TestAsync Finished.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async UniTaskVoid Start()
|
async UniTaskVoid Start()
|
||||||
{
|
{
|
||||||
Debug.Log("App Start");
|
|
||||||
|
|
||||||
Application.quitting += () =>
|
// UniTask.Delay(TimeSpan.FromSeconds(1)).TimeoutWithoutException
|
||||||
|
|
||||||
|
|
||||||
|
var currentLoop = PlayerLoop.GetDefaultPlayerLoop();
|
||||||
|
PlayerLoopHelper.Initialize(ref currentLoop, InjectPlayerLoopTimings.Minimum); // minimum is Update | FixedUpdate | LastPostLateUpdate
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var cancelToken = new CancellationTokenSource();
|
||||||
|
cancelButton.onClick.AddListener(()=>
|
||||||
{
|
{
|
||||||
Debug.Log("called quitting");
|
cancelToken.Cancel(); // cancel from button click.
|
||||||
quitSource.Cancel();
|
});
|
||||||
};
|
|
||||||
|
|
||||||
QuitCheck().Forget();
|
var timeoutToken = new CancellationTokenSource();
|
||||||
|
timeoutToken.CancelAfterSlim(TimeSpan.FromSeconds(5)); // 5sec timeout.
|
||||||
|
|
||||||
//Expression.Lambda<Func<int>>(null).Compile(true);
|
try
|
||||||
|
{
|
||||||
|
// combine token
|
||||||
|
var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancelToken.Token, timeoutToken.Token);
|
||||||
|
|
||||||
//RunStandardTaskAsync();
|
await UnityWebRequest.Get("http://foo").SendWebRequest().WithCancellation(linkedTokenSource.Token);
|
||||||
|
}
|
||||||
//UnityEngine.Debug.Log("UniTaskPlayerLoop ready? " + PlayerLoopHelper.IsInjectedUniTaskPlayerLoop());
|
catch (OperationCanceledException ex)
|
||||||
|
{
|
||||||
//var url = "http://google.com/404";
|
if (timeoutToken.IsCancellationRequested)
|
||||||
//var webRequestAsyncOperation = UnityWebRequest.Get(url).SendWebRequest();
|
{
|
||||||
//await webRequestAsyncOperation.ToUniTask();
|
UnityEngine.Debug.Log("Timeout.");
|
||||||
|
}
|
||||||
//PlayerLoopInfo.Inject();
|
else if (cancelToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
//_ = AsyncFixedUpdate();
|
UnityEngine.Debug.Log("Cancel clicked.");
|
||||||
//StartCoroutine(CoroutineFixedUpdate());
|
}
|
||||||
|
_ = ex;
|
||||||
//StartCoroutine(TestCoroutine().ToCoroutine());
|
}
|
||||||
|
|
||||||
// Application.logMessageReceived += Application_logMessageReceived;
|
|
||||||
|
|
||||||
// var rp = new AsyncReactiveProperty<int>();
|
|
||||||
|
|
||||||
|
|
||||||
// rp.AddTo(this.GetCancellationTokenOnDestroy());
|
|
||||||
//var cts = new CancellationTokenSource();
|
|
||||||
|
|
||||||
|
|
||||||
// UniTask.Post(
|
|
||||||
|
|
||||||
// CancellationToken.
|
|
||||||
|
|
||||||
//UniTask.Delay(TimeSpan.FromSeconds(3)).
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// TestAsync(cts.Token).Forget();
|
||||||
|
|
||||||
okButton.onClick.AddListener(UniTask.UnityAction(async () =>
|
okButton.onClick.AddListener(UniTask.UnityAction(async () =>
|
||||||
{
|
{
|
||||||
|
// try timeout
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//await UniTask.Delay(TimeSpan.FromSeconds(2), cancellationToken: timeoutController.Timeout(TimeSpan.FromSeconds(3)));
|
||||||
|
UnityEngine.Debug.Log("Delay Complete, Reset(and reuse).");
|
||||||
|
//timeoutController.Reset();
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException ex)
|
||||||
|
{
|
||||||
|
//UnityEngine.Debug.Log("Timeout! FromTimeout?:" + timeoutController.IsTimeout());
|
||||||
|
_ = ex;
|
||||||
|
}
|
||||||
|
|
||||||
var client = new NetworkClient("http://localhost:5000", TimeSpan.FromSeconds(2),
|
await UniTask.Yield();
|
||||||
new QueueRequestDecorator(),
|
|
||||||
new LoggingDecorator());
|
|
||||||
//new AppendTokenDecorator(),
|
|
||||||
//new SetupHeaderDecorator());
|
|
||||||
|
|
||||||
|
|
||||||
await client.PostAsync("", new { Id = 100 });
|
|
||||||
|
|
||||||
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// _ = ExecuteAsync();
|
cancelButton.onClick.AddListener(UniTask.UnityAction(async () =>
|
||||||
|
{
|
||||||
// await UniTask.Yield();
|
//clickCancelSource.Cancel();
|
||||||
|
|
||||||
// //await DelayCheck();
|
//RunCheck(PlayerLoopTiming.Initialization).Forget();
|
||||||
// /*
|
//RunCheck(PlayerLoopTiming.LastInitialization).Forget();
|
||||||
// UnityEngine.Debug.Log("click:" + PlayerLoopInfo.CurrentLoopType);
|
//RunCheck(PlayerLoopTiming.EarlyUpdate).Forget();
|
||||||
// StartCoroutine(CoroutineRun());
|
//RunCheck(PlayerLoopTiming.LastEarlyUpdate).Forget();
|
||||||
// StartCoroutine(CoroutineRun2());
|
//RunCheck(PlayerLoopTiming.FixedUpdate).Forget();
|
||||||
// _ = AsyncRun();
|
//RunCheck(PlayerLoopTiming.LastFixedUpdate).Forget();
|
||||||
// _ = AsyncLastUpdate();
|
//RunCheck(PlayerLoopTiming.PreUpdate).Forget();
|
||||||
// _ = AsyncLastLast();
|
//RunCheck(PlayerLoopTiming.LastPreUpdate).Forget();
|
||||||
// */
|
//RunCheck(PlayerLoopTiming.Update).Forget();
|
||||||
// //await UniTask.Yield();
|
//RunCheck(PlayerLoopTiming.LastUpdate).Forget();
|
||||||
// //_ = Test2();
|
//RunCheck(PlayerLoopTiming.PreLateUpdate).Forget();
|
||||||
// // EarlyUpdate.ExecuteMainThreadJobs
|
//RunCheck(PlayerLoopTiming.LastPreLateUpdate).Forget();
|
||||||
// // _ = Test2();
|
//RunCheck(PlayerLoopTiming.PostLateUpdate).Forget();
|
||||||
|
//RunCheck(PlayerLoopTiming.LastPostLateUpdate).Forget();
|
||||||
// //var t = await Resources.LoadAsync<TextAsset>(Application.streamingAssetsPath + "test.txt");
|
|
||||||
// //Debug.Log("LoadEnd" + PlayerLoopInfo.CurrentLoopType + ", " + (t != null));
|
await UniTask.Yield();
|
||||||
// //Debug.Log("LoadEnd" + PlayerLoopInfo.CurrentLoopType + ", " + ((TextAsset)t).text);
|
}));
|
||||||
|
|
||||||
|
await UniTask.Yield();
|
||||||
// //await UniTask.Yield(PlayerLoopTiming.LastUpdate);
|
}
|
||||||
// //UnityEngine.Debug.Log("after update:" + Time.frameCount);
|
|
||||||
// ////await UniTask.NextFrame();
|
async UniTaskVoid RunCheck(PlayerLoopTiming timing)
|
||||||
// ////await UniTask.Yield();
|
{
|
||||||
// ////UnityEngine.Debug.Log("after update nextframe:" + Time.frameCount);
|
//await UniTask.Yield(timing);
|
||||||
|
//UnityEngine.Debug.Log("Yield:" + timing);
|
||||||
// //StartCoroutine(CoroutineRun2());
|
await UniTask.DelayFrame(1, timing);
|
||||||
// ////StartCoroutine(CoroutineRun());
|
UnityEngine.Debug.Log("Delay:" + timing);
|
||||||
// //UnityEngine.Debug.Log("FOO?");
|
|
||||||
|
|
||||||
// //_ = DelayFrame3_Pre();
|
|
||||||
// //await UniTask.Yield();
|
|
||||||
|
|
||||||
//}));
|
|
||||||
|
|
||||||
//cancelButton.onClick.AddListener(UniTask.UnityAction(async () =>
|
|
||||||
//{
|
|
||||||
// _ = DelayFrame3_Post();
|
|
||||||
// await UniTask.Yield();
|
|
||||||
|
|
||||||
// //await UniTask.Yield(PlayerLoopTiming.LastPreUpdate);
|
|
||||||
// //UnityEngine.Debug.Log("before update:" + Time.frameCount);
|
|
||||||
// //await UniTask.NextFrame();
|
|
||||||
// //await UniTask.Yield();
|
|
||||||
// //UnityEngine.Debug.Log("before update nextframe:" + Time.frameCount);
|
|
||||||
|
|
||||||
// //StartCoroutine(CoroutineRun());
|
|
||||||
|
|
||||||
// //UnityEngine.Debug.Log("click:" + PlayerLoopInfo.CurrentLoopType);
|
|
||||||
// //_ = Yieldding();
|
|
||||||
|
|
||||||
// //var cts = new CancellationTokenSource();
|
|
||||||
|
|
||||||
// //UnityEngine.Debug.Log("click:" + PlayerLoopInfo.CurrentLoopType + ":" + Time.frameCount);
|
|
||||||
// //var la = SceneManager.LoadSceneAsync("Scenes/ExceptionExamples").WithCancellation(cts.Token);
|
|
||||||
// ////cts.Cancel();
|
|
||||||
// //await la;
|
|
||||||
// //UnityEngine.Debug.Log("End LoadSceneAsync" + PlayerLoopInfo.CurrentLoopType + ":" + Time.frameCount);
|
|
||||||
//}));
|
|
||||||
|
|
||||||
//return;
|
|
||||||
//await UniTask.SwitchToMainThread();
|
|
||||||
|
|
||||||
//UniTaskAsyncEnumerable.EveryValueChanged(mcc, x => x.MyProperty)
|
|
||||||
// .Do(_ => { }, () => Debug.Log("COMPLETED"))
|
|
||||||
// .ForEachAsync(x =>
|
|
||||||
// {
|
|
||||||
// Debug.Log("VALUE_CHANGED:" + x);
|
|
||||||
// })
|
|
||||||
// .Forget();
|
|
||||||
|
|
||||||
//_ = Test1();
|
|
||||||
//Test2().Forget();
|
|
||||||
//StartCoroutine(Test3("https://bing.com/"));
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//bool flip = false;
|
|
||||||
//var rect = cancelButton.GetComponent<RectTransform>();
|
|
||||||
//var cts = new CancellationTokenSource();
|
|
||||||
//var ct = cts.Token;
|
|
||||||
//okButton.onClick.AddListener(UniTask.UnityAction(async () =>
|
|
||||||
//{
|
|
||||||
// await rect.DOMoveX(10f * (flip ? -1 : 1), 3).OnUpdate(() => { Debug.Log("UPDATE YEAH"); }).WithCancellation(ct);
|
|
||||||
// flip = !flip;
|
|
||||||
// // ok.
|
|
||||||
//}));
|
|
||||||
//cancelButton.onClick.AddListener(() =>
|
|
||||||
//{
|
|
||||||
// cts.Cancel();
|
|
||||||
//});
|
|
||||||
|
|
||||||
|
|
||||||
// DG.Tweening.Core.TweenerCore<int>
|
|
||||||
//Debug.Log("GO MOVEX");
|
|
||||||
//await okButton.GetComponent<RectTransform>().DOMoveX(-10.2f, 3).WithCancellation(CancellationToken.None);
|
|
||||||
//Debug.Log("END MOVEX");
|
|
||||||
|
|
||||||
|
|
||||||
//Debug.Log("AGAIN MOVE");
|
|
||||||
//await okButton.GetComponent<RectTransform>().DOMoveY(10.2f, 3).WithCancellation(CancellationToken.None);
|
|
||||||
//Debug.Log("AGAIN END MOVE");
|
|
||||||
|
|
||||||
//Debug.Log(Test().GetType().FullName);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// check stacktrace
|
|
||||||
// await UniTaskAsyncEnumerable.EveryUpdate().Where((x, i) => i % 2 == 0).Select(x => x).DistinctUntilChanged().ForEachAsync(x =>
|
|
||||||
//{
|
|
||||||
// Debug.Log("test");
|
|
||||||
//});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//// DOTween.To(
|
|
||||||
|
|
||||||
//var cts = new CancellationTokenSource();
|
|
||||||
|
|
||||||
////var tween = okButton.GetComponent<RectTransform>().DOLocalMoveX(100, 5.0f);
|
|
||||||
|
|
||||||
//cancelButton.OnClickAsAsyncEnumerable().ForEachAsync(_ =>
|
|
||||||
//{
|
|
||||||
// cts.Cancel();
|
|
||||||
//}).Forget();
|
|
||||||
|
|
||||||
|
|
||||||
//// await tween.ToUniTask(TweenCancelBehaviour.KillAndCancelAwait, cts.Token);
|
|
||||||
|
|
||||||
////tween.SetRecyclable(true);
|
|
||||||
|
|
||||||
//Debug.Log("END");
|
|
||||||
|
|
||||||
//// tween.Play();
|
|
||||||
|
|
||||||
//// DOTween.
|
|
||||||
|
|
||||||
//// DOVirtual.Float(0, 1, 1, x => { }).ToUniTask();
|
|
||||||
|
|
||||||
|
|
||||||
//await foreach (var _ in UniTaskAsyncEnumerable.EveryUpdate())
|
|
||||||
//{
|
|
||||||
// Debug.Log("Update() " + Time.frameCount);
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//await okButton.OnClickAsAsyncEnumerable().Where((x, i) => i % 2 == 0).ForEachAsync(_ =>
|
|
||||||
//{
|
|
||||||
//});
|
|
||||||
|
|
||||||
|
|
||||||
//okButton.OnClickAsAsyncEnumerable().ForEachAsync(_ =>
|
|
||||||
//{
|
|
||||||
|
|
||||||
|
|
||||||
//foreach (var (type, size) in TaskPool.GetCacheSizeInfo())
|
|
||||||
//{
|
|
||||||
// Debug.Log(type + ":" + size);
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
//}).Forget();
|
|
||||||
|
|
||||||
//CloseAsync(this.GetCancellationTokenOnDestroy()).Forget();
|
|
||||||
|
|
||||||
//okButton.onClick.AddListener(UniTask.UnityAction(async () => await UniTask.Yield()));
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//UpdateUniTask().Forget();
|
|
||||||
|
|
||||||
//StartCoroutine(Coroutine());
|
|
||||||
|
|
||||||
// PlayerLoopInfo.Inject();
|
|
||||||
await UniTask.Delay(TimeSpan.FromSeconds(1));
|
|
||||||
PlayerLoopInfo.DumpPlayerLoop("current", PlayerLoop.GetCurrentPlayerLoop());
|
|
||||||
|
|
||||||
|
|
||||||
// _ = ReturnToMainThreadTest();
|
|
||||||
|
|
||||||
//GameObject.Destroy(this.gameObject);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Application_logMessageReceived2(string condition, string stackTrace, LogType type)
|
private void Application_logMessageReceived2(string condition, string stackTrace, LogType type)
|
||||||
|
|||||||
@@ -12,16 +12,16 @@ public class FooMonoBehaviour : MonoBehaviour
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async UniTask Download(UnityWebRequest req, string filePath)
|
//private async UniTask Download(UnityWebRequest req, string filePath)
|
||||||
{
|
//{
|
||||||
var foo = req.SendWebRequest();
|
// _ = req.SendWebRequest();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var aaa = await foo;
|
|
||||||
Debug.Log(aaa);
|
|
||||||
|
|
||||||
//File.WriteAllText(filePath, req.downloadHandler.text ?? string.Empty);
|
// // var aaa = await foo;
|
||||||
}
|
// // Debug.Log(aaa);
|
||||||
|
// await UniTask.Yield();
|
||||||
|
// //File.WriteAllText(filePath, req.downloadHandler.text ?? string.Empty);
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,6 +55,8 @@ namespace Cysharp.Threading.TasksTests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !UNITY_WEBGL
|
||||||
|
|
||||||
[UnityTest]
|
[UnityTest]
|
||||||
public IEnumerator DelayAnd() => UniTask.ToCoroutine(async () =>
|
public IEnumerator DelayAnd() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
{
|
||||||
@@ -76,6 +78,8 @@ namespace Cysharp.Threading.TasksTests
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
[UnityTest]
|
[UnityTest]
|
||||||
public IEnumerator DelayIgnore() => UniTask.ToCoroutine(async () =>
|
public IEnumerator DelayIgnore() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
{
|
||||||
@@ -183,6 +187,8 @@ namespace Cysharp.Threading.TasksTests
|
|||||||
diff.Should().Be(11);
|
diff.Should().Be(11);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
#if !UNITY_WEBGL
|
||||||
|
|
||||||
[UnityTest]
|
[UnityTest]
|
||||||
public IEnumerator SwitchTo() => UniTask.ToCoroutine(async () =>
|
public IEnumerator SwitchTo() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
{
|
||||||
@@ -215,6 +221,8 @@ namespace Cysharp.Threading.TasksTests
|
|||||||
currentThreadId.Should().Be(switchedThreadId2);
|
currentThreadId.Should().Be(switchedThreadId2);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
//[UnityTest]
|
//[UnityTest]
|
||||||
//public IEnumerator ObservableConversion() => UniTask.ToCoroutine(async () =>
|
//public IEnumerator ObservableConversion() => UniTask.ToCoroutine(async () =>
|
||||||
//{
|
//{
|
||||||
|
|||||||
@@ -135,6 +135,8 @@ namespace Cysharp.Threading.TasksTests
|
|||||||
l.Add(30);
|
l.Add(30);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !UNITY_WEBGL
|
||||||
|
|
||||||
[UnityTest]
|
[UnityTest]
|
||||||
public IEnumerator WaitForSecondsTest() => UniTask.ToCoroutine(async () =>
|
public IEnumerator WaitForSecondsTest() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
{
|
||||||
@@ -162,6 +164,8 @@ namespace Cysharp.Threading.TasksTests
|
|||||||
yield return new WaitForSeconds(3.0f);
|
yield return new WaitForSeconds(3.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
IEnumerator Worker(List<(int, int)> l)
|
IEnumerator Worker(List<(int, int)> l)
|
||||||
{
|
{
|
||||||
l.Add((0, Time.frameCount));
|
l.Add((0, Time.frameCount));
|
||||||
|
|||||||
@@ -175,6 +175,7 @@ namespace Cysharp.Threading.TasksTests
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
#if !UNITY_WEBGL
|
||||||
|
|
||||||
[UnityTest]
|
[UnityTest]
|
||||||
public IEnumerator DelayInThreadPool() => UniTask.ToCoroutine(async () =>
|
public IEnumerator DelayInThreadPool() => UniTask.ToCoroutine(async () =>
|
||||||
@@ -185,6 +186,8 @@ namespace Cysharp.Threading.TasksTests
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
[UnityTest]
|
[UnityTest]
|
||||||
public IEnumerator DelayRealtime() => UniTask.ToCoroutine(async () =>
|
public IEnumerator DelayRealtime() => UniTask.ToCoroutine(async () =>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ namespace Cysharp.Threading.TasksTests
|
|||||||
{
|
{
|
||||||
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
|
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
|
||||||
#if !UNITY_WSA
|
#if !UNITY_WSA
|
||||||
|
#if !UNITY_WEBGL
|
||||||
|
|
||||||
//[UnityTest]
|
//[UnityTest]
|
||||||
//public IEnumerator RunThread() => UniTask.ToCoroutine(async () =>
|
//public IEnumerator RunThread() => UniTask.ToCoroutine(async () =>
|
||||||
@@ -88,7 +89,7 @@ namespace Cysharp.Threading.TasksTests
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
43
src/UniTask/ProjectSettings/PackageManagerSettings.asset
Normal file
43
src/UniTask/ProjectSettings/PackageManagerSettings.asset
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!114 &1
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 61
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 13964, guid: 0000000000000000e000000000000000, type: 0}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
m_EnablePreviewPackages: 0
|
||||||
|
m_EnablePackageDependencies: 0
|
||||||
|
m_AdvancedSettingsExpanded: 1
|
||||||
|
m_ScopedRegistriesSettingsExpanded: 1
|
||||||
|
oneTimeWarningShown: 0
|
||||||
|
m_Registries:
|
||||||
|
- m_Id: main
|
||||||
|
m_Name:
|
||||||
|
m_Url: https://packages.unity.com
|
||||||
|
m_Scopes: []
|
||||||
|
m_IsDefault: 1
|
||||||
|
m_Capabilities: 7
|
||||||
|
m_UserSelectedRegistryName:
|
||||||
|
m_UserAddingNewScopedRegistry: 0
|
||||||
|
m_RegistryInfoDraft:
|
||||||
|
m_ErrorMessage:
|
||||||
|
m_Original:
|
||||||
|
m_Id:
|
||||||
|
m_Name:
|
||||||
|
m_Url:
|
||||||
|
m_Scopes: []
|
||||||
|
m_IsDefault: 0
|
||||||
|
m_Capabilities: 0
|
||||||
|
m_Modified: 0
|
||||||
|
m_Name:
|
||||||
|
m_Url:
|
||||||
|
m_Scopes:
|
||||||
|
-
|
||||||
|
m_SelectedScopeIndex: 0
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
m_EditorVersion: 2019.4.5f1
|
m_EditorVersion: 2020.2.1f1
|
||||||
m_EditorVersionWithRevision: 2019.4.5f1 (81610f64359c)
|
m_EditorVersionWithRevision: 2020.2.1f1 (270dd8c3da1c)
|
||||||
|
|||||||
8
src/UniTask/ProjectSettings/VersionControlSettings.asset
Normal file
8
src/UniTask/ProjectSettings/VersionControlSettings.asset
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!890905787 &1
|
||||||
|
VersionControlSettings:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_Mode: Visible Meta Files
|
||||||
|
m_CollabEditorSettings:
|
||||||
|
inProgressEnabled: 1
|
||||||
24
src/UniTask/UserSettings/EditorUserSettings.asset
Normal file
24
src/UniTask/UserSettings/EditorUserSettings.asset
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
%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
|
||||||
Reference in New Issue
Block a user