Void_F 1 giorno fa
parent
commit
cc15ff229d
100 ha cambiato i file con 8154 aggiunte e 0 eliminazioni
  1. 8 0
      Assets/Plugins/UniTask.meta
  2. 8 0
      Assets/Plugins/UniTask/Editor.meta
  3. 62 0
      Assets/Plugins/UniTask/Editor/SplitterGUILayout.cs
  4. 11 0
      Assets/Plugins/UniTask/Editor/SplitterGUILayout.cs.meta
  5. 17 0
      Assets/Plugins/UniTask/Editor/UniTask.Editor.asmdef
  6. 7 0
      Assets/Plugins/UniTask/Editor/UniTask.Editor.asmdef.meta
  7. 182 0
      Assets/Plugins/UniTask/Editor/UniTaskTrackerTreeView.cs
  8. 11 0
      Assets/Plugins/UniTask/Editor/UniTaskTrackerTreeView.cs.meta
  9. 209 0
      Assets/Plugins/UniTask/Editor/UniTaskTrackerWindow.cs
  10. 11 0
      Assets/Plugins/UniTask/Editor/UniTaskTrackerWindow.cs.meta
  11. 8 0
      Assets/Plugins/UniTask/Runtime.meta
  12. 245 0
      Assets/Plugins/UniTask/Runtime/AsyncLazy.cs
  13. 11 0
      Assets/Plugins/UniTask/Runtime/AsyncLazy.cs.meta
  14. 644 0
      Assets/Plugins/UniTask/Runtime/AsyncReactiveProperty.cs
  15. 11 0
      Assets/Plugins/UniTask/Runtime/AsyncReactiveProperty.cs.meta
  16. 26 0
      Assets/Plugins/UniTask/Runtime/AsyncUnit.cs
  17. 11 0
      Assets/Plugins/UniTask/Runtime/AsyncUnit.cs.meta
  18. 23 0
      Assets/Plugins/UniTask/Runtime/CancellationTokenEqualityComparer.cs
  19. 11 0
      Assets/Plugins/UniTask/Runtime/CancellationTokenEqualityComparer.cs.meta
  20. 182 0
      Assets/Plugins/UniTask/Runtime/CancellationTokenExtensions.cs
  21. 11 0
      Assets/Plugins/UniTask/Runtime/CancellationTokenExtensions.cs.meta
  22. 44 0
      Assets/Plugins/UniTask/Runtime/CancellationTokenSourceExtensions.cs
  23. 11 0
      Assets/Plugins/UniTask/Runtime/CancellationTokenSourceExtensions.cs.meta
  24. 450 0
      Assets/Plugins/UniTask/Runtime/Channel.cs
  25. 11 0
      Assets/Plugins/UniTask/Runtime/Channel.cs.meta
  26. 8 0
      Assets/Plugins/UniTask/Runtime/CompilerServices.meta
  27. 17 0
      Assets/Plugins/UniTask/Runtime/CompilerServices/AsyncMethodBuilderAttribute.cs
  28. 11 0
      Assets/Plugins/UniTask/Runtime/CompilerServices/AsyncMethodBuilderAttribute.cs.meta
  29. 269 0
      Assets/Plugins/UniTask/Runtime/CompilerServices/AsyncUniTaskMethodBuilder.cs
  30. 11 0
      Assets/Plugins/UniTask/Runtime/CompilerServices/AsyncUniTaskMethodBuilder.cs.meta
  31. 137 0
      Assets/Plugins/UniTask/Runtime/CompilerServices/AsyncUniTaskVoidMethodBuilder.cs
  32. 11 0
      Assets/Plugins/UniTask/Runtime/CompilerServices/AsyncUniTaskVoidMethodBuilder.cs.meta
  33. 380 0
      Assets/Plugins/UniTask/Runtime/CompilerServices/StateMachineRunner.cs
  34. 11 0
      Assets/Plugins/UniTask/Runtime/CompilerServices/StateMachineRunner.cs.meta
  35. 34 0
      Assets/Plugins/UniTask/Runtime/EnumerableAsyncExtensions.cs
  36. 11 0
      Assets/Plugins/UniTask/Runtime/EnumerableAsyncExtensions.cs.meta
  37. 287 0
      Assets/Plugins/UniTask/Runtime/EnumeratorAsyncExtensions.cs
  38. 11 0
      Assets/Plugins/UniTask/Runtime/EnumeratorAsyncExtensions.cs.meta
  39. 14 0
      Assets/Plugins/UniTask/Runtime/ExceptionExtensions.cs
  40. 11 0
      Assets/Plugins/UniTask/Runtime/ExceptionExtensions.cs.meta
  41. 8 0
      Assets/Plugins/UniTask/Runtime/External.meta
  42. 8 0
      Assets/Plugins/UniTask/Runtime/External/Addressables.meta
  43. 483 0
      Assets/Plugins/UniTask/Runtime/External/Addressables/AddressablesAsyncExtensions.cs
  44. 11 0
      Assets/Plugins/UniTask/Runtime/External/Addressables/AddressablesAsyncExtensions.cs.meta
  45. 28 0
      Assets/Plugins/UniTask/Runtime/External/Addressables/UniTask.Addressables.asmdef
  46. 7 0
      Assets/Plugins/UniTask/Runtime/External/Addressables/UniTask.Addressables.asmdef.meta
  47. 8 0
      Assets/Plugins/UniTask/Runtime/External/DOTween.meta
  48. 436 0
      Assets/Plugins/UniTask/Runtime/External/DOTween/DOTweenAsyncExtensions.cs
  49. 11 0
      Assets/Plugins/UniTask/Runtime/External/DOTween/DOTweenAsyncExtensions.cs.meta
  50. 22 0
      Assets/Plugins/UniTask/Runtime/External/DOTween/UniTask.DOTween.asmdef
  51. 7 0
      Assets/Plugins/UniTask/Runtime/External/DOTween/UniTask.DOTween.asmdef.meta
  52. 8 0
      Assets/Plugins/UniTask/Runtime/External/TextMeshPro.meta
  53. 224 0
      Assets/Plugins/UniTask/Runtime/External/TextMeshPro/TextMeshProAsyncExtensions.InputField.cs
  54. 11 0
      Assets/Plugins/UniTask/Runtime/External/TextMeshPro/TextMeshProAsyncExtensions.InputField.cs.meta
  55. 130 0
      Assets/Plugins/UniTask/Runtime/External/TextMeshPro/TextMeshProAsyncExtensions.cs
  56. 11 0
      Assets/Plugins/UniTask/Runtime/External/TextMeshPro/TextMeshProAsyncExtensions.cs.meta
  57. 27 0
      Assets/Plugins/UniTask/Runtime/External/TextMeshPro/UniTask.TextMeshPro.asmdef
  58. 7 0
      Assets/Plugins/UniTask/Runtime/External/TextMeshPro/UniTask.TextMeshPro.asmdef.meta
  59. 91 0
      Assets/Plugins/UniTask/Runtime/IUniTaskAsyncEnumerable.cs
  60. 11 0
      Assets/Plugins/UniTask/Runtime/IUniTaskAsyncEnumerable.cs.meta
  61. 127 0
      Assets/Plugins/UniTask/Runtime/IUniTaskSource.cs
  62. 11 0
      Assets/Plugins/UniTask/Runtime/IUniTaskSource.cs.meta
  63. 8 0
      Assets/Plugins/UniTask/Runtime/Internal.meta
  64. 150 0
      Assets/Plugins/UniTask/Runtime/Internal/ArrayPool.cs
  65. 12 0
      Assets/Plugins/UniTask/Runtime/Internal/ArrayPool.cs.meta
  66. 115 0
      Assets/Plugins/UniTask/Runtime/Internal/ArrayPoolUtil.cs
  67. 12 0
      Assets/Plugins/UniTask/Runtime/Internal/ArrayPoolUtil.cs.meta
  68. 73 0
      Assets/Plugins/UniTask/Runtime/Internal/ArrayUtil.cs
  69. 12 0
      Assets/Plugins/UniTask/Runtime/Internal/ArrayUtil.cs.meta
  70. 225 0
      Assets/Plugins/UniTask/Runtime/Internal/ContinuationQueue.cs
  71. 11 0
      Assets/Plugins/UniTask/Runtime/Internal/ContinuationQueue.cs.meta
  72. 249 0
      Assets/Plugins/UniTask/Runtime/Internal/DiagnosticsExtensions.cs
  73. 11 0
      Assets/Plugins/UniTask/Runtime/Internal/DiagnosticsExtensions.cs.meta
  74. 79 0
      Assets/Plugins/UniTask/Runtime/Internal/Error.cs
  75. 12 0
      Assets/Plugins/UniTask/Runtime/Internal/Error.cs.meta
  76. 112 0
      Assets/Plugins/UniTask/Runtime/Internal/MinimumQueue.cs
  77. 11 0
      Assets/Plugins/UniTask/Runtime/Internal/MinimumQueue.cs.meta
  78. 260 0
      Assets/Plugins/UniTask/Runtime/Internal/PlayerLoopRunner.cs
  79. 11 0
      Assets/Plugins/UniTask/Runtime/Internal/PlayerLoopRunner.cs.meta
  80. 50 0
      Assets/Plugins/UniTask/Runtime/Internal/PooledDelegate.cs
  81. 11 0
      Assets/Plugins/UniTask/Runtime/Internal/PooledDelegate.cs.meta
  82. 64 0
      Assets/Plugins/UniTask/Runtime/Internal/RuntimeHelpersAbstraction.cs
  83. 12 0
      Assets/Plugins/UniTask/Runtime/Internal/RuntimeHelpersAbstraction.cs.meta
  84. 153 0
      Assets/Plugins/UniTask/Runtime/Internal/StatePool.cs
  85. 11 0
      Assets/Plugins/UniTask/Runtime/Internal/StatePool.cs.meta
  86. 178 0
      Assets/Plugins/UniTask/Runtime/Internal/TaskTracker.cs
  87. 11 0
      Assets/Plugins/UniTask/Runtime/Internal/TaskTracker.cs.meta
  88. 267 0
      Assets/Plugins/UniTask/Runtime/Internal/UnityEqualityComparer.cs
  89. 11 0
      Assets/Plugins/UniTask/Runtime/Internal/UnityEqualityComparer.cs.meta
  90. 28 0
      Assets/Plugins/UniTask/Runtime/Internal/UnityWebRequestExtensions.cs
  91. 11 0
      Assets/Plugins/UniTask/Runtime/Internal/UnityWebRequestExtensions.cs.meta
  92. 37 0
      Assets/Plugins/UniTask/Runtime/Internal/ValueStopwatch.cs
  93. 11 0
      Assets/Plugins/UniTask/Runtime/Internal/ValueStopwatch.cs.meta
  94. 334 0
      Assets/Plugins/UniTask/Runtime/Internal/WeakDictionary.cs
  95. 11 0
      Assets/Plugins/UniTask/Runtime/Internal/WeakDictionary.cs.meta
  96. 8 0
      Assets/Plugins/UniTask/Runtime/Linq.meta
  97. 318 0
      Assets/Plugins/UniTask/Runtime/Linq/Aggregate.cs
  98. 11 0
      Assets/Plugins/UniTask/Runtime/Linq/Aggregate.cs.meta
  99. 108 0
      Assets/Plugins/UniTask/Runtime/Linq/All.cs
  100. 11 0
      Assets/Plugins/UniTask/Runtime/Linq/All.cs.meta

+ 8 - 0
Assets/Plugins/UniTask.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 6c46fc6b3e49ea54089efeb1107bef47
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
Assets/Plugins/UniTask/Editor.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 219ed7fc3c65d094bb7ef9775e83aefd
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 62 - 0
Assets/Plugins/UniTask/Editor/SplitterGUILayout.cs

@@ -0,0 +1,62 @@
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+
+using System;
+using System.Linq;
+using System.Reflection;
+using UnityEditor;
+using UnityEngine;
+
+namespace Cysharp.Threading.Tasks.Editor
+{
+    // reflection call of UnityEditor.SplitterGUILayout
+    internal static class SplitterGUILayout
+    {
+        static BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;
+
+        static Lazy<Type> splitterStateType = new Lazy<Type>(() =>
+        {
+            var type = typeof(EditorWindow).Assembly.GetTypes().First(x => x.FullName == "UnityEditor.SplitterState");
+            return type;
+        });
+
+        static Lazy<ConstructorInfo> splitterStateCtor = new Lazy<ConstructorInfo>(() =>
+        {
+            var type = splitterStateType.Value;
+            return type.GetConstructor(flags, null, new Type[] { typeof(float[]), typeof(int[]), typeof(int[]) }, null);
+        });
+
+        static Lazy<Type> splitterGUILayoutType = new Lazy<Type>(() =>
+        {
+            var type = typeof(EditorWindow).Assembly.GetTypes().First(x => x.FullName == "UnityEditor.SplitterGUILayout");
+            return type;
+        });
+
+        static Lazy<MethodInfo> beginVerticalSplit = new Lazy<MethodInfo>(() =>
+        {
+            var type = splitterGUILayoutType.Value;
+            return type.GetMethod("BeginVerticalSplit", flags, null, new Type[] { splitterStateType.Value, typeof(GUILayoutOption[]) }, null);
+        });
+
+        static Lazy<MethodInfo> endVerticalSplit = new Lazy<MethodInfo>(() =>
+        {
+            var type = splitterGUILayoutType.Value;
+            return type.GetMethod("EndVerticalSplit", flags, null, Type.EmptyTypes, null);
+        });
+
+        public static object CreateSplitterState(float[] relativeSizes, int[] minSizes, int[] maxSizes)
+        {
+            return splitterStateCtor.Value.Invoke(new object[] { relativeSizes, minSizes, maxSizes });
+        }
+
+        public static void BeginVerticalSplit(object splitterState, params GUILayoutOption[] options)
+        {
+            beginVerticalSplit.Value.Invoke(null, new object[] { splitterState, options });
+        }
+
+        public static void EndVerticalSplit()
+        {
+            endVerticalSplit.Value.Invoke(null, Type.EmptyTypes);
+        }
+    }
+}
+

+ 11 - 0
Assets/Plugins/UniTask/Editor/SplitterGUILayout.cs.meta

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

+ 17 - 0
Assets/Plugins/UniTask/Editor/UniTask.Editor.asmdef

@@ -0,0 +1,17 @@
+{
+    "name": "UniTask.Editor",
+    "references": [
+        "UniTask"
+    ],
+    "includePlatforms": [
+        "Editor"
+    ],
+    "excludePlatforms": [],
+    "allowUnsafeCode": false,
+    "overrideReferences": false,
+    "precompiledReferences": [],
+    "autoReferenced": false,
+    "defineConstraints": [],
+    "versionDefines": [],
+    "noEngineReferences": false
+}

+ 7 - 0
Assets/Plugins/UniTask/Editor/UniTask.Editor.asmdef.meta

@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 4129704b5a1a13841ba16f230bf24a57
+AssemblyDefinitionImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 182 - 0
Assets/Plugins/UniTask/Editor/UniTaskTrackerTreeView.cs

@@ -0,0 +1,182 @@
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+
+using UnityEngine;
+using UnityEditor;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System;
+using UnityEditor.IMGUI.Controls;
+using Cysharp.Threading.Tasks.Internal;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace Cysharp.Threading.Tasks.Editor
+{
+    public class UniTaskTrackerViewItem : TreeViewItem
+    {
+        static Regex removeHref = new Regex("<a href.+>(.+)</a>", RegexOptions.Compiled);
+
+        public string TaskType { get; set; }
+        public string Elapsed { get; set; }
+        public string Status { get; set; }
+
+        string position;
+        public string Position
+        {
+            get { return position; }
+            set
+            {
+                position = value;
+                PositionFirstLine = GetFirstLine(position);
+            }
+        }
+
+        public string PositionFirstLine { get; private set; }
+
+        static string GetFirstLine(string str)
+        {
+            var sb = new StringBuilder();
+            for (int i = 0; i < str.Length; i++)
+            {
+                if (str[i] == '\r' || str[i] == '\n')
+                {
+                    break;
+                }
+                sb.Append(str[i]);
+            }
+
+            return removeHref.Replace(sb.ToString(), "$1");
+        }
+
+        public UniTaskTrackerViewItem(int id) : base(id)
+        {
+
+        }
+    }
+
+    public class UniTaskTrackerTreeView : TreeView
+    {
+        const string sortedColumnIndexStateKey = "UniTaskTrackerTreeView_sortedColumnIndex";
+
+        public IReadOnlyList<TreeViewItem> CurrentBindingItems;
+
+        public UniTaskTrackerTreeView()
+            : this(new TreeViewState(), new MultiColumnHeader(new MultiColumnHeaderState(new[]
+            {
+                new MultiColumnHeaderState.Column() { headerContent = new GUIContent("TaskType"), width = 20},
+                new MultiColumnHeaderState.Column() { headerContent = new GUIContent("Elapsed"), width = 10},
+                new MultiColumnHeaderState.Column() { headerContent = new GUIContent("Status"), width = 10},
+                new MultiColumnHeaderState.Column() { headerContent = new GUIContent("Position")},
+            })))
+        {
+        }
+
+        UniTaskTrackerTreeView(TreeViewState state, MultiColumnHeader header)
+            : base(state, header)
+        {
+            rowHeight = 20;
+            showAlternatingRowBackgrounds = true;
+            showBorder = true;
+            header.sortingChanged += Header_sortingChanged;
+
+            header.ResizeToFit();
+            Reload();
+
+            header.sortedColumnIndex = SessionState.GetInt(sortedColumnIndexStateKey, 1);
+        }
+
+        public void ReloadAndSort()
+        {
+            var currentSelected = this.state.selectedIDs;
+            Reload();
+            Header_sortingChanged(this.multiColumnHeader);
+            this.state.selectedIDs = currentSelected;
+        }
+
+        private void Header_sortingChanged(MultiColumnHeader multiColumnHeader)
+        {
+            SessionState.SetInt(sortedColumnIndexStateKey, multiColumnHeader.sortedColumnIndex);
+            var index = multiColumnHeader.sortedColumnIndex;
+            var ascending = multiColumnHeader.IsSortedAscending(multiColumnHeader.sortedColumnIndex);
+
+            var items = rootItem.children.Cast<UniTaskTrackerViewItem>();
+
+            IOrderedEnumerable<UniTaskTrackerViewItem> orderedEnumerable;
+            switch (index)
+            {
+                case 0:
+                    orderedEnumerable = ascending ? items.OrderBy(item => item.TaskType) : items.OrderByDescending(item => item.TaskType);
+                    break;
+                case 1:
+                    orderedEnumerable = ascending ? items.OrderBy(item => double.Parse(item.Elapsed)) : items.OrderByDescending(item => double.Parse(item.Elapsed));
+                    break;
+                case 2:
+                    orderedEnumerable = ascending ? items.OrderBy(item => item.Status) : items.OrderByDescending(item => item.Elapsed);
+                    break;
+                case 3:
+                    orderedEnumerable = ascending ? items.OrderBy(item => item.Position) : items.OrderByDescending(item => item.PositionFirstLine);
+                    break;
+                default:
+                    throw new ArgumentOutOfRangeException(nameof(index), index, null);
+            }
+
+            CurrentBindingItems = rootItem.children = orderedEnumerable.Cast<TreeViewItem>().ToList();
+            BuildRows(rootItem);
+        }
+
+        protected override TreeViewItem BuildRoot()
+        {
+            var root = new TreeViewItem { depth = -1 };
+
+            var children = new List<TreeViewItem>();
+
+            TaskTracker.ForEachActiveTask((trackingId, awaiterType, status, created, stackTrace) =>
+            {
+                children.Add(new UniTaskTrackerViewItem(trackingId) { TaskType = awaiterType, Status = status.ToString(), Elapsed = (DateTime.UtcNow - created).TotalSeconds.ToString("00.00"), Position = stackTrace });
+            });
+
+            CurrentBindingItems = children;
+            root.children = CurrentBindingItems as List<TreeViewItem>;
+            return root;
+        }
+
+        protected override bool CanMultiSelect(TreeViewItem item)
+        {
+            return false;
+        }
+
+        protected override void RowGUI(RowGUIArgs args)
+        {
+            var item = args.item as UniTaskTrackerViewItem;
+
+            for (var visibleColumnIndex = 0; visibleColumnIndex < args.GetNumVisibleColumns(); visibleColumnIndex++)
+            {
+                var rect = args.GetCellRect(visibleColumnIndex);
+                var columnIndex = args.GetColumn(visibleColumnIndex);
+
+                var labelStyle = args.selected ? EditorStyles.whiteLabel : EditorStyles.label;
+                labelStyle.alignment = TextAnchor.MiddleLeft;
+                switch (columnIndex)
+                {
+                    case 0:
+                        EditorGUI.LabelField(rect, item.TaskType, labelStyle);
+                        break;
+                    case 1:
+                        EditorGUI.LabelField(rect, item.Elapsed, labelStyle);
+                        break;
+                    case 2:
+                        EditorGUI.LabelField(rect, item.Status, labelStyle);
+                        break;
+                    case 3:
+                        EditorGUI.LabelField(rect, item.PositionFirstLine, labelStyle);
+                        break;
+                    default:
+                        throw new ArgumentOutOfRangeException(nameof(columnIndex), columnIndex, null);
+                }
+            }
+        }
+    }
+
+}
+

+ 11 - 0
Assets/Plugins/UniTask/Editor/UniTaskTrackerTreeView.cs.meta

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

+ 209 - 0
Assets/Plugins/UniTask/Editor/UniTaskTrackerWindow.cs

@@ -0,0 +1,209 @@
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+
+using UnityEngine;
+using UnityEditor;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System;
+using UnityEditor.IMGUI.Controls;
+using Cysharp.Threading.Tasks.Internal;
+
+namespace Cysharp.Threading.Tasks.Editor
+{
+    public class UniTaskTrackerWindow : EditorWindow
+    {
+        static int interval;
+
+        static UniTaskTrackerWindow window;
+
+        [MenuItem("Window/UniTask Tracker")]
+        public static void OpenWindow()
+        {
+            if (window != null)
+            {
+                window.Close();
+            }
+
+            // will called OnEnable(singleton instance will be set).
+            GetWindow<UniTaskTrackerWindow>("UniTask Tracker").Show();
+        }
+
+        static readonly GUILayoutOption[] EmptyLayoutOption = new GUILayoutOption[0];
+
+        UniTaskTrackerTreeView treeView;
+        object splitterState;
+
+        void OnEnable()
+        {
+            window = this; // set singleton.
+            splitterState = SplitterGUILayout.CreateSplitterState(new float[] { 75f, 25f }, new int[] { 32, 32 }, null);
+            treeView = new UniTaskTrackerTreeView();
+            TaskTracker.EditorEnableState.EnableAutoReload = EditorPrefs.GetBool(TaskTracker.EnableAutoReloadKey, false);
+            TaskTracker.EditorEnableState.EnableTracking = EditorPrefs.GetBool(TaskTracker.EnableTrackingKey, false);
+            TaskTracker.EditorEnableState.EnableStackTrace = EditorPrefs.GetBool(TaskTracker.EnableStackTraceKey, false);
+        }
+
+        void OnGUI()
+        {
+            // Head
+            RenderHeadPanel();
+
+            // Splittable
+            SplitterGUILayout.BeginVerticalSplit(this.splitterState, EmptyLayoutOption);
+            {
+                // Column Tabble
+                RenderTable();
+
+                // StackTrace details
+                RenderDetailsPanel();
+            }
+            SplitterGUILayout.EndVerticalSplit();
+        }
+
+        #region HeadPanel
+
+        public static bool EnableAutoReload => TaskTracker.EditorEnableState.EnableAutoReload;
+        public static bool EnableTracking => TaskTracker.EditorEnableState.EnableTracking;
+        public static bool EnableStackTrace => TaskTracker.EditorEnableState.EnableStackTrace;
+        static readonly GUIContent EnableAutoReloadHeadContent = EditorGUIUtility.TrTextContent("Enable AutoReload", "Reload automatically.", (Texture)null);
+        static readonly GUIContent ReloadHeadContent = EditorGUIUtility.TrTextContent("Reload", "Reload View.", (Texture)null);
+        static readonly GUIContent GCHeadContent = EditorGUIUtility.TrTextContent("GC.Collect", "Invoke GC.Collect.", (Texture)null);
+        static readonly GUIContent EnableTrackingHeadContent = EditorGUIUtility.TrTextContent("Enable Tracking", "Start to track async/await UniTask. Performance impact: low", (Texture)null);
+        static readonly GUIContent EnableStackTraceHeadContent = EditorGUIUtility.TrTextContent("Enable StackTrace", "Capture StackTrace when task is started. Performance impact: high", (Texture)null);
+
+        // [Enable Tracking] | [Enable StackTrace]
+        void RenderHeadPanel()
+        {
+            EditorGUILayout.BeginVertical(EmptyLayoutOption);
+            EditorGUILayout.BeginHorizontal(EditorStyles.toolbar, EmptyLayoutOption);
+
+            if (GUILayout.Toggle(EnableAutoReload, EnableAutoReloadHeadContent, EditorStyles.toolbarButton, EmptyLayoutOption) != EnableAutoReload)
+            {
+                TaskTracker.EditorEnableState.EnableAutoReload = !EnableAutoReload;
+            }
+
+            if (GUILayout.Toggle(EnableTracking, EnableTrackingHeadContent, EditorStyles.toolbarButton, EmptyLayoutOption) != EnableTracking)
+            {
+                TaskTracker.EditorEnableState.EnableTracking = !EnableTracking;
+            }
+
+            if (GUILayout.Toggle(EnableStackTrace, EnableStackTraceHeadContent, EditorStyles.toolbarButton, EmptyLayoutOption) != EnableStackTrace)
+            {
+                TaskTracker.EditorEnableState.EnableStackTrace = !EnableStackTrace;
+            }
+
+            GUILayout.FlexibleSpace();
+
+            if (GUILayout.Button(ReloadHeadContent, EditorStyles.toolbarButton, EmptyLayoutOption))
+            {
+                TaskTracker.CheckAndResetDirty();
+                treeView.ReloadAndSort();
+                Repaint();
+            }
+
+            if (GUILayout.Button(GCHeadContent, EditorStyles.toolbarButton, EmptyLayoutOption))
+            {
+                GC.Collect(0);
+            }
+
+            EditorGUILayout.EndHorizontal();
+            EditorGUILayout.EndVertical();
+        }
+
+        #endregion
+
+        #region TableColumn
+
+        Vector2 tableScroll;
+        GUIStyle tableListStyle;
+
+        void RenderTable()
+        {
+            if (tableListStyle == null)
+            {
+                tableListStyle = new GUIStyle("CN Box");
+                tableListStyle.margin.top = 0;
+                tableListStyle.padding.left = 3;
+            }
+
+            EditorGUILayout.BeginVertical(tableListStyle, EmptyLayoutOption);
+
+            this.tableScroll = EditorGUILayout.BeginScrollView(this.tableScroll, new GUILayoutOption[]
+            {
+                GUILayout.ExpandWidth(true),
+                GUILayout.MaxWidth(2000f)
+            });
+            var controlRect = EditorGUILayout.GetControlRect(new GUILayoutOption[]
+            {
+                GUILayout.ExpandHeight(true),
+                GUILayout.ExpandWidth(true)
+            });
+
+
+            treeView?.OnGUI(controlRect);
+
+            EditorGUILayout.EndScrollView();
+            EditorGUILayout.EndVertical();
+        }
+
+        private void Update()
+        {
+            if (EnableAutoReload)
+            {
+                if (interval++ % 120 == 0)
+                {
+                    if (TaskTracker.CheckAndResetDirty())
+                    {
+                        treeView.ReloadAndSort();
+                        Repaint();
+                    }
+                }
+            }
+        }
+
+        #endregion
+
+        #region Details
+
+        static GUIStyle detailsStyle;
+        Vector2 detailsScroll;
+
+        void RenderDetailsPanel()
+        {
+            if (detailsStyle == null)
+            {
+                detailsStyle = new GUIStyle("CN Message");
+                detailsStyle.wordWrap = false;
+                detailsStyle.stretchHeight = true;
+                detailsStyle.margin.right = 15;
+            }
+
+            string message = "";
+            var selected = treeView.state.selectedIDs;
+            if (selected.Count > 0)
+            {
+                var first = selected[0];
+                var item = treeView.CurrentBindingItems.FirstOrDefault(x => x.id == first) as UniTaskTrackerViewItem;
+                if (item != null)
+                {
+                    message = item.Position;
+                }
+            }
+
+            detailsScroll = EditorGUILayout.BeginScrollView(this.detailsScroll, EmptyLayoutOption);
+            var vector = detailsStyle.CalcSize(new GUIContent(message));
+            EditorGUILayout.SelectableLabel(message, detailsStyle, new GUILayoutOption[]
+            {
+                GUILayout.ExpandHeight(true),
+                GUILayout.ExpandWidth(true),
+                GUILayout.MinWidth(vector.x),
+                GUILayout.MinHeight(vector.y)
+            });
+            EditorGUILayout.EndScrollView();
+        }
+
+        #endregion
+    }
+}
+

+ 11 - 0
Assets/Plugins/UniTask/Editor/UniTaskTrackerWindow.cs.meta

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

+ 8 - 0
Assets/Plugins/UniTask/Runtime.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: add20dbd20dc0104fa73a0d49aa5d1d5
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 245 - 0
Assets/Plugins/UniTask/Runtime/AsyncLazy.cs

@@ -0,0 +1,245 @@
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+
+using System;
+using System.Threading;
+
+namespace Cysharp.Threading.Tasks
+{
+    public class AsyncLazy
+    {
+        static Action<object> continuation = SetCompletionSource;
+
+        Func<UniTask> taskFactory;
+        UniTaskCompletionSource completionSource;
+        UniTask.Awaiter awaiter;
+
+        object syncLock;
+        bool initialized;
+
+        public AsyncLazy(Func<UniTask> taskFactory)
+        {
+            this.taskFactory = taskFactory;
+            this.completionSource = new UniTaskCompletionSource();
+            this.syncLock = new object();
+            this.initialized = false;
+        }
+
+        internal AsyncLazy(UniTask task)
+        {
+            this.taskFactory = null;
+            this.completionSource = new UniTaskCompletionSource();
+            this.syncLock = null;
+            this.initialized = true;
+
+            var awaiter = task.GetAwaiter();
+            if (awaiter.IsCompleted)
+            {
+                SetCompletionSource(awaiter);
+            }
+            else
+            {
+                this.awaiter = awaiter;
+                awaiter.SourceOnCompleted(continuation, this);
+            }
+        }
+
+        public UniTask Task
+        {
+            get
+            {
+                EnsureInitialized();
+                return completionSource.Task;
+            }
+        }
+
+
+        public UniTask.Awaiter GetAwaiter() => Task.GetAwaiter();
+
+        void EnsureInitialized()
+        {
+            if (Volatile.Read(ref initialized))
+            {
+                return;
+            }
+
+            EnsureInitializedCore();
+        }
+
+        void EnsureInitializedCore()
+        {
+            lock (syncLock)
+            {
+                if (!Volatile.Read(ref initialized))
+                {
+                    var f = Interlocked.Exchange(ref taskFactory, null);
+                    if (f != null)
+                    {
+                        var task = f();
+                        var awaiter = task.GetAwaiter();
+                        if (awaiter.IsCompleted)
+                        {
+                            SetCompletionSource(awaiter);
+                        }
+                        else
+                        {
+                            this.awaiter = awaiter;
+                            awaiter.SourceOnCompleted(continuation, this);
+                        }
+
+                        Volatile.Write(ref initialized, true);
+                    }
+                }
+            }
+        }
+
+        void SetCompletionSource(in UniTask.Awaiter awaiter)
+        {
+            try
+            {
+                awaiter.GetResult();
+                completionSource.TrySetResult();
+            }
+            catch (Exception ex)
+            {
+                completionSource.TrySetException(ex);
+            }
+        }
+
+        static void SetCompletionSource(object state)
+        {
+            var self = (AsyncLazy)state;
+            try
+            {
+                self.awaiter.GetResult();
+                self.completionSource.TrySetResult();
+            }
+            catch (Exception ex)
+            {
+                self.completionSource.TrySetException(ex);
+            }
+            finally
+            {
+                self.awaiter = default;
+            }
+        }
+    }
+
+    public class AsyncLazy<T>
+    {
+        static Action<object> continuation = SetCompletionSource;
+
+        Func<UniTask<T>> taskFactory;
+        UniTaskCompletionSource<T> completionSource;
+        UniTask<T>.Awaiter awaiter;
+
+        object syncLock;
+        bool initialized;
+
+        public AsyncLazy(Func<UniTask<T>> taskFactory)
+        {
+            this.taskFactory = taskFactory;
+            this.completionSource = new UniTaskCompletionSource<T>();
+            this.syncLock = new object();
+            this.initialized = false;
+        }
+
+        internal AsyncLazy(UniTask<T> task)
+        {
+            this.taskFactory = null;
+            this.completionSource = new UniTaskCompletionSource<T>();
+            this.syncLock = null;
+            this.initialized = true;
+
+            var awaiter = task.GetAwaiter();
+            if (awaiter.IsCompleted)
+            {
+                SetCompletionSource(awaiter);
+            }
+            else
+            {
+                this.awaiter = awaiter;
+                awaiter.SourceOnCompleted(continuation, this);
+            }
+        }
+
+        public UniTask<T> Task
+        {
+            get
+            {
+                EnsureInitialized();
+                return completionSource.Task;
+            }
+        }
+
+
+        public UniTask<T>.Awaiter GetAwaiter() => Task.GetAwaiter();
+
+        void EnsureInitialized()
+        {
+            if (Volatile.Read(ref initialized))
+            {
+                return;
+            }
+
+            EnsureInitializedCore();
+        }
+
+        void EnsureInitializedCore()
+        {
+            lock (syncLock)
+            {
+                if (!Volatile.Read(ref initialized))
+                {
+                    var f = Interlocked.Exchange(ref taskFactory, null);
+                    if (f != null)
+                    {
+                        var task = f();
+                        var awaiter = task.GetAwaiter();
+                        if (awaiter.IsCompleted)
+                        {
+                            SetCompletionSource(awaiter);
+                        }
+                        else
+                        {
+                            this.awaiter = awaiter;
+                            awaiter.SourceOnCompleted(continuation, this);
+                        }
+
+                        Volatile.Write(ref initialized, true);
+                    }
+                }
+            }
+        }
+
+        void SetCompletionSource(in UniTask<T>.Awaiter awaiter)
+        {
+            try
+            {
+                var result = awaiter.GetResult();
+                completionSource.TrySetResult(result);
+            }
+            catch (Exception ex)
+            {
+                completionSource.TrySetException(ex);
+            }
+        }
+
+        static void SetCompletionSource(object state)
+        {
+            var self = (AsyncLazy<T>)state;
+            try
+            {
+                var result = self.awaiter.GetResult();
+                self.completionSource.TrySetResult(result);
+            }
+            catch (Exception ex)
+            {
+                self.completionSource.TrySetException(ex);
+            }
+            finally
+            {
+                self.awaiter = default;
+            }
+        }
+    }
+}

+ 11 - 0
Assets/Plugins/UniTask/Runtime/AsyncLazy.cs.meta

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

+ 644 - 0
Assets/Plugins/UniTask/Runtime/AsyncReactiveProperty.cs

@@ -0,0 +1,644 @@
+using System;
+using System.Threading;
+
+namespace Cysharp.Threading.Tasks
+{
+    public interface IReadOnlyAsyncReactiveProperty<T> : IUniTaskAsyncEnumerable<T>
+    {
+        T Value { get; }
+        IUniTaskAsyncEnumerable<T> WithoutCurrent();
+        UniTask<T> WaitAsync(CancellationToken cancellationToken = default);
+    }
+
+    public interface IAsyncReactiveProperty<T> : IReadOnlyAsyncReactiveProperty<T>
+    {
+        new T Value { get; set; }
+    }
+
+    [Serializable]
+    public class AsyncReactiveProperty<T> : IAsyncReactiveProperty<T>, IDisposable
+    {
+        TriggerEvent<T> triggerEvent;
+
+#if UNITY_2018_3_OR_NEWER
+        [UnityEngine.SerializeField]
+#endif
+        T latestValue;
+
+        public T Value
+        {
+            get
+            {
+                return latestValue;
+            }
+            set
+            {
+                this.latestValue = value;
+                triggerEvent.SetResult(value);
+            }
+        }
+
+        public AsyncReactiveProperty(T value)
+        {
+            this.latestValue = value;
+            this.triggerEvent = default;
+        }
+
+        public IUniTaskAsyncEnumerable<T> WithoutCurrent()
+        {
+            return new WithoutCurrentEnumerable(this);
+        }
+
+        public IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken)
+        {
+            return new Enumerator(this, cancellationToken, true);
+        }
+
+        public void Dispose()
+        {
+            triggerEvent.SetCompleted();
+        }
+
+        public static implicit operator T(AsyncReactiveProperty<T> value)
+        {
+            return value.Value;
+        }
+
+        public override string ToString()
+        {
+            if (isValueType) return latestValue.ToString();
+            return latestValue?.ToString();
+        }
+
+        public UniTask<T> WaitAsync(CancellationToken cancellationToken = default)
+        {
+            return new UniTask<T>(WaitAsyncSource.Create(this, cancellationToken, out var token), token);
+        }
+
+        static bool isValueType;
+
+        static AsyncReactiveProperty()
+        {
+            isValueType = typeof(T).IsValueType;
+        }
+
+        sealed class WaitAsyncSource : IUniTaskSource<T>, ITriggerHandler<T>, ITaskPoolNode<WaitAsyncSource>
+        {
+            static Action<object> cancellationCallback = CancellationCallback;
+
+            static TaskPool<WaitAsyncSource> pool;
+            WaitAsyncSource nextNode;
+            ref WaitAsyncSource ITaskPoolNode<WaitAsyncSource>.NextNode => ref nextNode;
+
+            static WaitAsyncSource()
+            {
+                TaskPool.RegisterSizeGetter(typeof(WaitAsyncSource), () => pool.Size);
+            }
+
+            AsyncReactiveProperty<T> parent;
+            CancellationToken cancellationToken;
+            CancellationTokenRegistration cancellationTokenRegistration;
+            UniTaskCompletionSourceCore<T> core;
+
+            WaitAsyncSource()
+            {
+            }
+
+            public static IUniTaskSource<T> Create(AsyncReactiveProperty<T> parent, CancellationToken cancellationToken, out short token)
+            {
+                if (cancellationToken.IsCancellationRequested)
+                {
+                    return AutoResetUniTaskCompletionSource<T>.CreateFromCanceled(cancellationToken, out token);
+                }
+
+                if (!pool.TryPop(out var result))
+                {
+                    result = new WaitAsyncSource();
+                }
+
+                result.parent = parent;
+                result.cancellationToken = cancellationToken;
+
+                if (cancellationToken.CanBeCanceled)
+                {
+                    result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationCallback, result);
+                }
+
+                result.parent.triggerEvent.Add(result);
+
+                TaskTracker.TrackActiveTask(result, 3);
+
+                token = result.core.Version;
+                return result;
+            }
+
+            bool TryReturn()
+            {
+                TaskTracker.RemoveTracking(this);
+                core.Reset();
+                cancellationTokenRegistration.Dispose();
+                cancellationTokenRegistration = default;
+                parent.triggerEvent.Remove(this);
+                parent = null;
+                cancellationToken = default;
+                return pool.TryPush(this);
+            }
+
+            static void CancellationCallback(object state)
+            {
+                var self = (WaitAsyncSource)state;
+                self.OnCanceled(self.cancellationToken);
+            }
+
+            // IUniTaskSource
+
+            public T GetResult(short token)
+            {
+                try
+                {
+                    return core.GetResult(token);
+                }
+                finally
+                {
+                    TryReturn();
+                }
+            }
+
+            void IUniTaskSource.GetResult(short token)
+            {
+                GetResult(token);
+            }
+
+            public void OnCompleted(Action<object> continuation, object state, short token)
+            {
+                core.OnCompleted(continuation, state, token);
+            }
+
+            public UniTaskStatus GetStatus(short token)
+            {
+                return core.GetStatus(token);
+            }
+
+            public UniTaskStatus UnsafeGetStatus()
+            {
+                return core.UnsafeGetStatus();
+            }
+
+            // ITriggerHandler
+
+            ITriggerHandler<T> ITriggerHandler<T>.Prev { get; set; }
+            ITriggerHandler<T> ITriggerHandler<T>.Next { get; set; }
+
+            public void OnCanceled(CancellationToken cancellationToken)
+            {
+                core.TrySetCanceled(cancellationToken);
+            }
+
+            public void OnCompleted()
+            {
+                // Complete as Cancel.
+                core.TrySetCanceled(CancellationToken.None);
+            }
+
+            public void OnError(Exception ex)
+            {
+                core.TrySetException(ex);
+            }
+
+            public void OnNext(T value)
+            {
+                core.TrySetResult(value);
+            }
+        }
+
+        sealed class WithoutCurrentEnumerable : IUniTaskAsyncEnumerable<T>
+        {
+            readonly AsyncReactiveProperty<T> parent;
+
+            public WithoutCurrentEnumerable(AsyncReactiveProperty<T> parent)
+            {
+                this.parent = parent;
+            }
+
+            public IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default)
+            {
+                return new Enumerator(parent, cancellationToken, false);
+            }
+        }
+
+        sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<T>, ITriggerHandler<T>
+        {
+            static Action<object> cancellationCallback = CancellationCallback;
+
+            readonly AsyncReactiveProperty<T> parent;
+            readonly CancellationToken cancellationToken;
+            readonly CancellationTokenRegistration cancellationTokenRegistration;
+            T value;
+            bool isDisposed;
+            bool firstCall;
+
+            public Enumerator(AsyncReactiveProperty<T> parent, CancellationToken cancellationToken, bool publishCurrentValue)
+            {
+                this.parent = parent;
+                this.cancellationToken = cancellationToken;
+                this.firstCall = publishCurrentValue;
+
+                parent.triggerEvent.Add(this);
+                TaskTracker.TrackActiveTask(this, 3);
+
+                if (cancellationToken.CanBeCanceled)
+                {
+                    cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationCallback, this);
+                }
+            }
+
+            public T Current => value;
+
+            ITriggerHandler<T> ITriggerHandler<T>.Prev { get; set; }
+            ITriggerHandler<T> ITriggerHandler<T>.Next { get; set; }
+
+            public UniTask<bool> MoveNextAsync()
+            {
+                // raise latest value on first call.
+                if (firstCall)
+                {
+                    firstCall = false;
+                    value = parent.Value;
+                    return CompletedTasks.True;
+                }
+
+                completionSource.Reset();
+                return new UniTask<bool>(this, completionSource.Version);
+            }
+
+            public UniTask DisposeAsync()
+            {
+                if (!isDisposed)
+                {
+                    isDisposed = true;
+                    TaskTracker.RemoveTracking(this);
+                    completionSource.TrySetCanceled(cancellationToken);
+                    parent.triggerEvent.Remove(this);
+                }
+                return default;
+            }
+
+            public void OnNext(T value)
+            {
+                this.value = value;
+                completionSource.TrySetResult(true);
+            }
+
+            public void OnCanceled(CancellationToken cancellationToken)
+            {
+                DisposeAsync().Forget();
+            }
+
+            public void OnCompleted()
+            {
+                completionSource.TrySetResult(false);
+            }
+
+            public void OnError(Exception ex)
+            {
+                completionSource.TrySetException(ex);
+            }
+
+            static void CancellationCallback(object state)
+            {
+                var self = (Enumerator)state;
+                self.DisposeAsync().Forget();
+            }
+        }
+    }
+
+    public class ReadOnlyAsyncReactiveProperty<T> : IReadOnlyAsyncReactiveProperty<T>, IDisposable
+    {
+        TriggerEvent<T> triggerEvent;
+
+        T latestValue;
+        IUniTaskAsyncEnumerator<T> enumerator;
+
+        public T Value
+        {
+            get
+            {
+                return latestValue;
+            }
+        }
+
+        public ReadOnlyAsyncReactiveProperty(T initialValue, IUniTaskAsyncEnumerable<T> source, CancellationToken cancellationToken)
+        {
+            latestValue = initialValue;
+            ConsumeEnumerator(source, cancellationToken).Forget();
+        }
+
+        public ReadOnlyAsyncReactiveProperty(IUniTaskAsyncEnumerable<T> source, CancellationToken cancellationToken)
+        {
+            ConsumeEnumerator(source, cancellationToken).Forget();
+        }
+
+        async UniTaskVoid ConsumeEnumerator(IUniTaskAsyncEnumerable<T> source, CancellationToken cancellationToken)
+        {
+            enumerator = source.GetAsyncEnumerator(cancellationToken);
+            try
+            {
+                while (await enumerator.MoveNextAsync())
+                {
+                    var value = enumerator.Current;
+                    this.latestValue = value;
+                    triggerEvent.SetResult(value);
+                }
+            }
+            finally
+            {
+                await enumerator.DisposeAsync();
+                enumerator = null;
+            }
+        }
+
+        public IUniTaskAsyncEnumerable<T> WithoutCurrent()
+        {
+            return new WithoutCurrentEnumerable(this);
+        }
+
+        public IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken)
+        {
+            return new Enumerator(this, cancellationToken, true);
+        }
+
+        public void Dispose()
+        {
+            if (enumerator != null)
+            {
+                enumerator.DisposeAsync().Forget();
+            }
+
+            triggerEvent.SetCompleted();
+        }
+
+        public static implicit operator T(ReadOnlyAsyncReactiveProperty<T> value)
+        {
+            return value.Value;
+        }
+
+        public override string ToString()
+        {
+            if (isValueType) return latestValue.ToString();
+            return latestValue?.ToString();
+        }
+
+        public UniTask<T> WaitAsync(CancellationToken cancellationToken = default)
+        {
+            return new UniTask<T>(WaitAsyncSource.Create(this, cancellationToken, out var token), token);
+        }
+
+        static bool isValueType;
+
+        static ReadOnlyAsyncReactiveProperty()
+        {
+            isValueType = typeof(T).IsValueType;
+        }
+
+        sealed class WaitAsyncSource : IUniTaskSource<T>, ITriggerHandler<T>, ITaskPoolNode<WaitAsyncSource>
+        {
+            static Action<object> cancellationCallback = CancellationCallback;
+
+            static TaskPool<WaitAsyncSource> pool;
+            WaitAsyncSource nextNode;
+            ref WaitAsyncSource ITaskPoolNode<WaitAsyncSource>.NextNode => ref nextNode;
+
+            static WaitAsyncSource()
+            {
+                TaskPool.RegisterSizeGetter(typeof(WaitAsyncSource), () => pool.Size);
+            }
+
+            ReadOnlyAsyncReactiveProperty<T> parent;
+            CancellationToken cancellationToken;
+            CancellationTokenRegistration cancellationTokenRegistration;
+            UniTaskCompletionSourceCore<T> core;
+
+            WaitAsyncSource()
+            {
+            }
+
+            public static IUniTaskSource<T> Create(ReadOnlyAsyncReactiveProperty<T> parent, CancellationToken cancellationToken, out short token)
+            {
+                if (cancellationToken.IsCancellationRequested)
+                {
+                    return AutoResetUniTaskCompletionSource<T>.CreateFromCanceled(cancellationToken, out token);
+                }
+
+                if (!pool.TryPop(out var result))
+                {
+                    result = new WaitAsyncSource();
+                }
+
+                result.parent = parent;
+                result.cancellationToken = cancellationToken;
+
+                if (cancellationToken.CanBeCanceled)
+                {
+                    result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationCallback, result);
+                }
+
+                result.parent.triggerEvent.Add(result);
+
+                TaskTracker.TrackActiveTask(result, 3);
+
+                token = result.core.Version;
+                return result;
+            }
+
+            bool TryReturn()
+            {
+                TaskTracker.RemoveTracking(this);
+                core.Reset();
+                cancellationTokenRegistration.Dispose();
+                cancellationTokenRegistration = default;
+                parent.triggerEvent.Remove(this);
+                parent = null;
+                cancellationToken = default;
+                return pool.TryPush(this);
+            }
+
+            static void CancellationCallback(object state)
+            {
+                var self = (WaitAsyncSource)state;
+                self.OnCanceled(self.cancellationToken);
+            }
+
+            // IUniTaskSource
+
+            public T GetResult(short token)
+            {
+                try
+                {
+                    return core.GetResult(token);
+                }
+                finally
+                {
+                    TryReturn();
+                }
+            }
+
+            void IUniTaskSource.GetResult(short token)
+            {
+                GetResult(token);
+            }
+
+            public void OnCompleted(Action<object> continuation, object state, short token)
+            {
+                core.OnCompleted(continuation, state, token);
+            }
+
+            public UniTaskStatus GetStatus(short token)
+            {
+                return core.GetStatus(token);
+            }
+
+            public UniTaskStatus UnsafeGetStatus()
+            {
+                return core.UnsafeGetStatus();
+            }
+
+            // ITriggerHandler
+
+            ITriggerHandler<T> ITriggerHandler<T>.Prev { get; set; }
+            ITriggerHandler<T> ITriggerHandler<T>.Next { get; set; }
+
+            public void OnCanceled(CancellationToken cancellationToken)
+            {
+                core.TrySetCanceled(cancellationToken);
+            }
+
+            public void OnCompleted()
+            {
+                // Complete as Cancel.
+                core.TrySetCanceled(CancellationToken.None);
+            }
+
+            public void OnError(Exception ex)
+            {
+                core.TrySetException(ex);
+            }
+
+            public void OnNext(T value)
+            {
+                core.TrySetResult(value);
+            }
+        }
+
+        sealed class WithoutCurrentEnumerable : IUniTaskAsyncEnumerable<T>
+        {
+            readonly ReadOnlyAsyncReactiveProperty<T> parent;
+
+            public WithoutCurrentEnumerable(ReadOnlyAsyncReactiveProperty<T> parent)
+            {
+                this.parent = parent;
+            }
+
+            public IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default)
+            {
+                return new Enumerator(parent, cancellationToken, false);
+            }
+        }
+
+        sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<T>, ITriggerHandler<T>
+        {
+            static Action<object> cancellationCallback = CancellationCallback;
+
+            readonly ReadOnlyAsyncReactiveProperty<T> parent;
+            readonly CancellationToken cancellationToken;
+            readonly CancellationTokenRegistration cancellationTokenRegistration;
+            T value;
+            bool isDisposed;
+            bool firstCall;
+
+            public Enumerator(ReadOnlyAsyncReactiveProperty<T> parent, CancellationToken cancellationToken, bool publishCurrentValue)
+            {
+                this.parent = parent;
+                this.cancellationToken = cancellationToken;
+                this.firstCall = publishCurrentValue;
+
+                parent.triggerEvent.Add(this);
+                TaskTracker.TrackActiveTask(this, 3);
+
+                if (cancellationToken.CanBeCanceled)
+                {
+                    cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationCallback, this);
+                }
+            }
+
+            public T Current => value;
+            ITriggerHandler<T> ITriggerHandler<T>.Prev { get; set; }
+            ITriggerHandler<T> ITriggerHandler<T>.Next { get; set; }
+
+            public UniTask<bool> MoveNextAsync()
+            {
+                // raise latest value on first call.
+                if (firstCall)
+                {
+                    firstCall = false;
+                    value = parent.Value;
+                    return CompletedTasks.True;
+                }
+
+                completionSource.Reset();
+                return new UniTask<bool>(this, completionSource.Version);
+            }
+
+            public UniTask DisposeAsync()
+            {
+                if (!isDisposed)
+                {
+                    isDisposed = true;
+                    TaskTracker.RemoveTracking(this);
+                    completionSource.TrySetCanceled(cancellationToken);
+                    parent.triggerEvent.Remove(this);
+                }
+                return default;
+            }
+
+            public void OnNext(T value)
+            {
+                this.value = value;
+                completionSource.TrySetResult(true);
+            }
+
+            public void OnCanceled(CancellationToken cancellationToken)
+            {
+                DisposeAsync().Forget();
+            }
+
+            public void OnCompleted()
+            {
+                completionSource.TrySetResult(false);
+            }
+
+            public void OnError(Exception ex)
+            {
+                completionSource.TrySetException(ex);
+            }
+
+            static void CancellationCallback(object state)
+            {
+                var self = (Enumerator)state;
+                self.DisposeAsync().Forget();
+            }
+        }
+    }
+
+    public static class StateExtensions
+    {
+        public static ReadOnlyAsyncReactiveProperty<T> ToReadOnlyAsyncReactiveProperty<T>(this IUniTaskAsyncEnumerable<T> source, CancellationToken cancellationToken)
+        {
+            return new ReadOnlyAsyncReactiveProperty<T>(source, cancellationToken);
+        }
+
+        public static ReadOnlyAsyncReactiveProperty<T> ToReadOnlyAsyncReactiveProperty<T>(this IUniTaskAsyncEnumerable<T> source, T initialValue, CancellationToken cancellationToken)
+        {
+            return new ReadOnlyAsyncReactiveProperty<T>(initialValue, source, cancellationToken);
+        }
+    }
+}

+ 11 - 0
Assets/Plugins/UniTask/Runtime/AsyncReactiveProperty.cs.meta

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

+ 26 - 0
Assets/Plugins/UniTask/Runtime/AsyncUnit.cs

@@ -0,0 +1,26 @@
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or 
+
+using System;
+
+namespace Cysharp.Threading.Tasks
+{
+    public readonly struct AsyncUnit : IEquatable<AsyncUnit>
+    {
+        public static readonly AsyncUnit Default = new AsyncUnit();
+
+        public override int GetHashCode()
+        {
+            return 0;
+        }
+
+        public bool Equals(AsyncUnit other)
+        {
+            return true;
+        }
+
+        public override string ToString()
+        {
+            return "()";
+        }
+    }
+}

+ 11 - 0
Assets/Plugins/UniTask/Runtime/AsyncUnit.cs.meta

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

+ 23 - 0
Assets/Plugins/UniTask/Runtime/CancellationTokenEqualityComparer.cs

@@ -0,0 +1,23 @@
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+
+using System.Collections.Generic;
+using System.Threading;
+
+namespace Cysharp.Threading.Tasks
+{
+    public class CancellationTokenEqualityComparer : IEqualityComparer<CancellationToken>
+    {
+        public static readonly IEqualityComparer<CancellationToken> Default = new CancellationTokenEqualityComparer();
+
+        public bool Equals(CancellationToken x, CancellationToken y)
+        {
+            return x.Equals(y);
+        }
+
+        public int GetHashCode(CancellationToken obj)
+        {
+            return obj.GetHashCode();
+        }
+    }
+}
+

+ 11 - 0
Assets/Plugins/UniTask/Runtime/CancellationTokenEqualityComparer.cs.meta

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

+ 182 - 0
Assets/Plugins/UniTask/Runtime/CancellationTokenExtensions.cs

@@ -0,0 +1,182 @@
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Threading;
+
+namespace Cysharp.Threading.Tasks
+{
+    public static class CancellationTokenExtensions
+    {
+        static readonly Action<object> cancellationTokenCallback = Callback;
+        static readonly Action<object> disposeCallback = DisposeCallback;
+
+        public static CancellationToken ToCancellationToken(this UniTask task)
+        {
+            var cts = new CancellationTokenSource();
+            ToCancellationTokenCore(task, cts).Forget();
+            return cts.Token;
+        }
+
+        public static CancellationToken ToCancellationToken(this UniTask task, CancellationToken linkToken)
+        {
+            if (linkToken.IsCancellationRequested)
+            {
+                return linkToken;
+            }
+
+            if (!linkToken.CanBeCanceled)
+            {
+                return ToCancellationToken(task);
+            }
+
+            var cts = CancellationTokenSource.CreateLinkedTokenSource(linkToken);
+            ToCancellationTokenCore(task, cts).Forget();
+
+            return cts.Token;
+        }
+
+        public static CancellationToken ToCancellationToken<T>(this UniTask<T> task)
+        {
+            return ToCancellationToken(task.AsUniTask());
+        }
+
+        public static CancellationToken ToCancellationToken<T>(this UniTask<T> task, CancellationToken linkToken)
+        {
+            return ToCancellationToken(task.AsUniTask(), linkToken);
+        }
+
+        static async UniTaskVoid ToCancellationTokenCore(UniTask task, CancellationTokenSource cts)
+        {
+            try
+            {
+                await task;
+            }
+            catch (Exception ex)
+            {
+                UniTaskScheduler.PublishUnobservedTaskException(ex);
+            }
+            cts.Cancel();
+            cts.Dispose();
+        }
+
+        public static (UniTask, CancellationTokenRegistration) ToUniTask(this CancellationToken cancellationToken)
+        {
+            if (cancellationToken.IsCancellationRequested)
+            {
+                return (UniTask.FromCanceled(cancellationToken), default(CancellationTokenRegistration));
+            }
+
+            var promise = new UniTaskCompletionSource();
+            return (promise.Task, cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationTokenCallback, promise));
+        }
+
+        static void Callback(object state)
+        {
+            var promise = (UniTaskCompletionSource)state;
+            promise.TrySetResult();
+        }
+
+        public static CancellationTokenAwaitable WaitUntilCanceled(this CancellationToken cancellationToken)
+        {
+            return new CancellationTokenAwaitable(cancellationToken);
+        }
+
+        public static CancellationTokenRegistration RegisterWithoutCaptureExecutionContext(this CancellationToken cancellationToken, Action callback)
+        {
+            var restoreFlow = false;
+            if (!ExecutionContext.IsFlowSuppressed())
+            {
+                ExecutionContext.SuppressFlow();
+                restoreFlow = true;
+            }
+
+            try
+            {
+                return cancellationToken.Register(callback, false);
+            }
+            finally
+            {
+                if (restoreFlow)
+                {
+                    ExecutionContext.RestoreFlow();
+                }
+            }
+        }
+
+        public static CancellationTokenRegistration RegisterWithoutCaptureExecutionContext(this CancellationToken cancellationToken, Action<object> callback, object state)
+        {
+            var restoreFlow = false;
+            if (!ExecutionContext.IsFlowSuppressed())
+            {
+                ExecutionContext.SuppressFlow();
+                restoreFlow = true;
+            }
+
+            try
+            {
+                return cancellationToken.Register(callback, state, false);
+            }
+            finally
+            {
+                if (restoreFlow)
+                {
+                    ExecutionContext.RestoreFlow();
+                }
+            }
+        }
+
+        public static CancellationTokenRegistration AddTo(this IDisposable disposable, CancellationToken cancellationToken)
+        {
+            return cancellationToken.RegisterWithoutCaptureExecutionContext(disposeCallback, disposable);
+        }
+
+        static void DisposeCallback(object state)
+        {
+            var d = (IDisposable)state;
+            d.Dispose();
+        }
+    }
+
+    public struct CancellationTokenAwaitable
+    {
+        CancellationToken cancellationToken;
+
+        public CancellationTokenAwaitable(CancellationToken cancellationToken)
+        {
+            this.cancellationToken = cancellationToken;
+        }
+
+        public Awaiter GetAwaiter()
+        {
+            return new Awaiter(cancellationToken);
+        }
+
+        public struct Awaiter : ICriticalNotifyCompletion
+        {
+            CancellationToken cancellationToken;
+
+            public Awaiter(CancellationToken cancellationToken)
+            {
+                this.cancellationToken = cancellationToken;
+            }
+
+            public bool IsCompleted => !cancellationToken.CanBeCanceled || cancellationToken.IsCancellationRequested;
+
+            public void GetResult()
+            {
+            }
+
+            public void OnCompleted(Action continuation)
+            {
+                UnsafeOnCompleted(continuation);
+            }
+
+            public void UnsafeOnCompleted(Action continuation)
+            {
+                cancellationToken.RegisterWithoutCaptureExecutionContext(continuation);
+            }
+        }
+    }
+}
+

+ 11 - 0
Assets/Plugins/UniTask/Runtime/CancellationTokenExtensions.cs.meta

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

+ 44 - 0
Assets/Plugins/UniTask/Runtime/CancellationTokenSourceExtensions.cs

@@ -0,0 +1,44 @@
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+
+using System.Threading;
+using UnityEngine;
+using Cysharp.Threading.Tasks.Triggers;
+using System;
+using Cysharp.Threading.Tasks.Internal;
+
+namespace Cysharp.Threading.Tasks
+{
+
+    public static partial class CancellationTokenSourceExtensions
+    {
+        readonly static Action<object> CancelCancellationTokenSourceStateDelegate = new Action<object>(CancelCancellationTokenSourceState);
+
+        static void CancelCancellationTokenSourceState(object state)
+        {
+            var cts = (CancellationTokenSource)state;
+            cts.Cancel();
+        }
+
+        public static IDisposable CancelAfterSlim(this CancellationTokenSource cts, int millisecondsDelay, DelayType delayType = DelayType.DeltaTime, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update)
+        {
+            return CancelAfterSlim(cts, TimeSpan.FromMilliseconds(millisecondsDelay), delayType, delayTiming);
+        }
+
+        public static IDisposable CancelAfterSlim(this CancellationTokenSource cts, TimeSpan delayTimeSpan, DelayType delayType = DelayType.DeltaTime, PlayerLoopTiming delayTiming = PlayerLoopTiming.Update)
+        {
+            return PlayerLoopTimer.StartNew(delayTimeSpan, false, delayType, delayTiming, cts.Token, CancelCancellationTokenSourceStateDelegate, cts);
+        }
+
+        public static void RegisterRaiseCancelOnDestroy(this CancellationTokenSource cts, Component component)
+        {
+            RegisterRaiseCancelOnDestroy(cts, component.gameObject);
+        }
+
+        public static void RegisterRaiseCancelOnDestroy(this CancellationTokenSource cts, GameObject gameObject)
+        {
+            var trigger = gameObject.GetAsyncDestroyTrigger();
+            trigger.CancellationToken.RegisterWithoutCaptureExecutionContext(CancelCancellationTokenSourceStateDelegate, cts);
+        }
+    }
+}
+

+ 11 - 0
Assets/Plugins/UniTask/Runtime/CancellationTokenSourceExtensions.cs.meta

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

+ 450 - 0
Assets/Plugins/UniTask/Runtime/Channel.cs

@@ -0,0 +1,450 @@
+using System;
+using System.Collections.Generic;
+using System.Threading;
+
+namespace Cysharp.Threading.Tasks
+{
+    public static class Channel
+    {
+        public static Channel<T> CreateSingleConsumerUnbounded<T>()
+        {
+            return new SingleConsumerUnboundedChannel<T>();
+        }
+    }
+
+    public abstract class Channel<TWrite, TRead>
+    {
+        public ChannelReader<TRead> Reader { get; protected set; }
+        public ChannelWriter<TWrite> Writer { get; protected set; }
+
+        public static implicit operator ChannelReader<TRead>(Channel<TWrite, TRead> channel) => channel.Reader;
+        public static implicit operator ChannelWriter<TWrite>(Channel<TWrite, TRead> channel) => channel.Writer;
+    }
+
+    public abstract class Channel<T> : Channel<T, T>
+    {
+    }
+
+    public abstract class ChannelReader<T>
+    {
+        public abstract bool TryRead(out T item);
+        public abstract UniTask<bool> WaitToReadAsync(CancellationToken cancellationToken = default(CancellationToken));
+
+        public abstract UniTask Completion { get; }
+
+        public virtual UniTask<T> ReadAsync(CancellationToken cancellationToken = default(CancellationToken))
+        {
+            if (this.TryRead(out var item))
+            {
+                return UniTask.FromResult(item);
+            }
+
+            return ReadAsyncCore(cancellationToken);
+        }
+
+        async UniTask<T> ReadAsyncCore(CancellationToken cancellationToken = default(CancellationToken))
+        {
+            if (await WaitToReadAsync(cancellationToken))
+            {
+                if (TryRead(out var item))
+                {
+                    return item;
+                }
+            }
+
+            throw new ChannelClosedException();
+        }
+
+        public abstract IUniTaskAsyncEnumerable<T> ReadAllAsync(CancellationToken cancellationToken = default(CancellationToken));
+    }
+
+    public abstract class ChannelWriter<T>
+    {
+        public abstract bool TryWrite(T item);
+        public abstract bool TryComplete(Exception error = null);
+
+        public void Complete(Exception error = null)
+        {
+            if (!TryComplete(error))
+            {
+                throw new ChannelClosedException();
+            }
+        }
+    }
+
+    public partial class ChannelClosedException : InvalidOperationException
+    {
+        public ChannelClosedException() :
+            base("Channel is already closed.")
+        { }
+
+        public ChannelClosedException(string message) : base(message) { }
+
+        public ChannelClosedException(Exception innerException) :
+            base("Channel is already closed", innerException)
+        { }
+
+        public ChannelClosedException(string message, Exception innerException) : base(message, innerException) { }
+    }
+
+    internal class SingleConsumerUnboundedChannel<T> : Channel<T>
+    {
+        readonly Queue<T> items;
+        readonly SingleConsumerUnboundedChannelReader readerSource;
+        UniTaskCompletionSource completedTaskSource;
+        UniTask completedTask;
+
+        Exception completionError;
+        bool closed;
+
+        public SingleConsumerUnboundedChannel()
+        {
+            items = new Queue<T>();
+            Writer = new SingleConsumerUnboundedChannelWriter(this);
+            readerSource = new SingleConsumerUnboundedChannelReader(this);
+            Reader = readerSource;
+        }
+
+        sealed class SingleConsumerUnboundedChannelWriter : ChannelWriter<T>
+        {
+            readonly SingleConsumerUnboundedChannel<T> parent;
+
+            public SingleConsumerUnboundedChannelWriter(SingleConsumerUnboundedChannel<T> parent)
+            {
+                this.parent = parent;
+            }
+
+            public override bool TryWrite(T item)
+            {
+                bool waiting;
+                lock (parent.items)
+                {
+                    if (parent.closed) return false;
+
+                    parent.items.Enqueue(item);
+                    waiting = parent.readerSource.isWaiting;
+                }
+
+                if (waiting)
+                {
+                    parent.readerSource.SingalContinuation();
+                }
+
+                return true;
+            }
+
+            public override bool TryComplete(Exception error = null)
+            {
+                bool waiting;
+                lock (parent.items)
+                {
+                    if (parent.closed) return false;
+                    parent.closed = true;
+                    waiting = parent.readerSource.isWaiting;
+
+                    if (parent.items.Count == 0)
+                    {
+                        if (error == null)
+                        {
+                            if (parent.completedTaskSource != null)
+                            {
+                                parent.completedTaskSource.TrySetResult();
+                            }
+                            else
+                            {
+                                parent.completedTask = UniTask.CompletedTask;
+                            }
+                        }
+                        else
+                        {
+                            if (parent.completedTaskSource != null)
+                            {
+                                parent.completedTaskSource.TrySetException(error);
+                            }
+                            else
+                            {
+                                parent.completedTask = UniTask.FromException(error);
+                            }
+                        }
+
+                        if (waiting)
+                        {
+                            parent.readerSource.SingalCompleted(error);
+                        }
+                    }
+
+                    parent.completionError = error;
+                }
+
+                return true;
+            }
+        }
+
+        sealed class SingleConsumerUnboundedChannelReader : ChannelReader<T>, IUniTaskSource<bool>
+        {
+            readonly Action<object> CancellationCallbackDelegate = CancellationCallback;
+            readonly SingleConsumerUnboundedChannel<T> parent;
+
+            CancellationToken cancellationToken;
+            CancellationTokenRegistration cancellationTokenRegistration;
+            UniTaskCompletionSourceCore<bool> core;
+            internal bool isWaiting;
+
+            public SingleConsumerUnboundedChannelReader(SingleConsumerUnboundedChannel<T> parent)
+            {
+                this.parent = parent;
+
+                TaskTracker.TrackActiveTask(this, 4);
+            }
+
+            public override UniTask Completion
+            {
+                get
+                {
+                    if (parent.completedTaskSource != null) return parent.completedTaskSource.Task;
+
+                    if (parent.closed)
+                    {
+                        return parent.completedTask;
+                    }
+
+                    parent.completedTaskSource = new UniTaskCompletionSource();
+                    return parent.completedTaskSource.Task;
+                }
+            }
+
+            public override bool TryRead(out T item)
+            {
+                lock (parent.items)
+                {
+                    if (parent.items.Count != 0)
+                    {
+                        item = parent.items.Dequeue();
+
+                        // complete when all value was consumed.
+                        if (parent.closed && parent.items.Count == 0)
+                        {
+                            if (parent.completionError != null)
+                            {
+                                if (parent.completedTaskSource != null)
+                                {
+                                    parent.completedTaskSource.TrySetException(parent.completionError);
+                                }
+                                else
+                                {
+                                    parent.completedTask = UniTask.FromException(parent.completionError);
+                                }
+                            }
+                            else
+                            {
+                                if (parent.completedTaskSource != null)
+                                {
+                                    parent.completedTaskSource.TrySetResult();
+                                }
+                                else
+                                {
+                                    parent.completedTask = UniTask.CompletedTask;
+                                }
+                            }
+                        }
+                    }
+                    else
+                    {
+                        item = default;
+                        return false;
+                    }
+                }
+
+                return true;
+            }
+
+            public override UniTask<bool> WaitToReadAsync(CancellationToken cancellationToken)
+            {
+                if (cancellationToken.IsCancellationRequested)
+                {
+                    return UniTask.FromCanceled<bool>(cancellationToken);
+                }
+
+                lock (parent.items)
+                {
+                    if (parent.items.Count != 0)
+                    {
+                        return CompletedTasks.True;
+                    }
+
+                    if (parent.closed)
+                    {
+                        if (parent.completionError == null)
+                        {
+                            return CompletedTasks.False;
+                        }
+                        else
+                        {
+                            return UniTask.FromException<bool>(parent.completionError);
+                        }
+                    }
+
+                    cancellationTokenRegistration.Dispose();
+
+                    core.Reset();
+                    isWaiting = true;
+
+                    this.cancellationToken = cancellationToken;
+                    if (this.cancellationToken.CanBeCanceled)
+                    {
+                        cancellationTokenRegistration = this.cancellationToken.RegisterWithoutCaptureExecutionContext(CancellationCallbackDelegate, this);
+                    }
+
+                    return new UniTask<bool>(this, core.Version);
+                }
+            }
+
+            public void SingalContinuation()
+            {
+                core.TrySetResult(true);
+            }
+
+            public void SingalCancellation(CancellationToken cancellationToken)
+            {
+                TaskTracker.RemoveTracking(this);
+                core.TrySetCanceled(cancellationToken);
+            }
+
+            public void SingalCompleted(Exception error)
+            {
+                if (error != null)
+                {
+                    TaskTracker.RemoveTracking(this);
+                    core.TrySetException(error);
+                }
+                else
+                {
+                    TaskTracker.RemoveTracking(this);
+                    core.TrySetResult(false);
+                }
+            }
+
+            public override IUniTaskAsyncEnumerable<T> ReadAllAsync(CancellationToken cancellationToken = default)
+            {
+                return new ReadAllAsyncEnumerable(this, cancellationToken);
+            }
+
+            bool IUniTaskSource<bool>.GetResult(short token)
+            {
+                return core.GetResult(token);
+            }
+
+            void IUniTaskSource.GetResult(short token)
+            {
+                core.GetResult(token);
+            }
+
+            UniTaskStatus IUniTaskSource.GetStatus(short token)
+            {
+                return core.GetStatus(token);
+            }
+
+            void IUniTaskSource.OnCompleted(Action<object> continuation, object state, short token)
+            {
+                core.OnCompleted(continuation, state, token);
+            }
+
+            UniTaskStatus IUniTaskSource.UnsafeGetStatus()
+            {
+                return core.UnsafeGetStatus();
+            }
+
+            static void CancellationCallback(object state)
+            {
+                var self = (SingleConsumerUnboundedChannelReader)state;
+                self.SingalCancellation(self.cancellationToken);
+            }
+
+            sealed class ReadAllAsyncEnumerable : IUniTaskAsyncEnumerable<T>, IUniTaskAsyncEnumerator<T>
+            {
+                readonly Action<object> CancellationCallback1Delegate = CancellationCallback1;
+                readonly Action<object> CancellationCallback2Delegate = CancellationCallback2;
+
+                readonly SingleConsumerUnboundedChannelReader parent;
+                CancellationToken cancellationToken1;
+                CancellationToken cancellationToken2;
+                CancellationTokenRegistration cancellationTokenRegistration1;
+                CancellationTokenRegistration cancellationTokenRegistration2;
+
+                T current;
+                bool cacheValue;
+                bool running;
+
+                public ReadAllAsyncEnumerable(SingleConsumerUnboundedChannelReader parent, CancellationToken cancellationToken)
+                {
+                    this.parent = parent;
+                    this.cancellationToken1 = cancellationToken;
+                }
+
+                public IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default)
+                {
+                    if (running)
+                    {
+                        throw new InvalidOperationException("Enumerator is already running, does not allow call GetAsyncEnumerator twice.");
+                    }
+
+                    if (this.cancellationToken1 != cancellationToken)
+                    {
+                        this.cancellationToken2 = cancellationToken;
+                    }
+
+                    if (this.cancellationToken1.CanBeCanceled)
+                    {
+                        this.cancellationTokenRegistration1 =  this.cancellationToken1.RegisterWithoutCaptureExecutionContext(CancellationCallback1Delegate, this);
+                    }
+
+                    if (this.cancellationToken2.CanBeCanceled)
+                    {
+                        this.cancellationTokenRegistration2 = this.cancellationToken2.RegisterWithoutCaptureExecutionContext(CancellationCallback2Delegate, this);
+                    }
+
+                    running = true;
+                    return this;
+                }
+
+                public T Current
+                {
+                    get
+                    {
+                        if (cacheValue)
+                        {
+                            return current;
+                        }
+                        parent.TryRead(out current);
+                        return current;
+                    }
+                }
+
+                public UniTask<bool> MoveNextAsync()
+                {
+                    cacheValue = false;
+                    return parent.WaitToReadAsync(CancellationToken.None); // ok to use None, registered in ctor.
+                }
+
+                public UniTask DisposeAsync()
+                {
+                    cancellationTokenRegistration1.Dispose();
+                    cancellationTokenRegistration2.Dispose();
+                    return default;
+                }
+
+                static void CancellationCallback1(object state)
+                {
+                    var self = (ReadAllAsyncEnumerable)state;
+                    self.parent.SingalCancellation(self.cancellationToken1);
+                }
+
+                static void CancellationCallback2(object state)
+                {
+                    var self = (ReadAllAsyncEnumerable)state;
+                    self.parent.SingalCancellation(self.cancellationToken2);
+                }
+            }
+        }
+    }
+}

+ 11 - 0
Assets/Plugins/UniTask/Runtime/Channel.cs.meta

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

+ 8 - 0
Assets/Plugins/UniTask/Runtime/CompilerServices.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: d97cd5f026475144a86ec9f697b5e676
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 17 - 0
Assets/Plugins/UniTask/Runtime/CompilerServices/AsyncMethodBuilderAttribute.cs

@@ -0,0 +1,17 @@
+
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+#pragma warning disable CS0436
+
+namespace System.Runtime.CompilerServices
+{
+    internal sealed class AsyncMethodBuilderAttribute : Attribute
+    {
+        public Type BuilderType { get; }
+
+        public AsyncMethodBuilderAttribute(Type builderType)
+        {
+            BuilderType = builderType;
+        }
+    }
+}
+

+ 11 - 0
Assets/Plugins/UniTask/Runtime/CompilerServices/AsyncMethodBuilderAttribute.cs.meta

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

+ 269 - 0
Assets/Plugins/UniTask/Runtime/CompilerServices/AsyncUniTaskMethodBuilder.cs

@@ -0,0 +1,269 @@
+
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+
+using System;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Security;
+
+namespace Cysharp.Threading.Tasks.CompilerServices
+{
+    [StructLayout(LayoutKind.Auto)]
+    public struct AsyncUniTaskMethodBuilder
+    {
+        IStateMachineRunnerPromise runnerPromise;
+        Exception ex;
+
+        // 1. Static Create method.
+        [DebuggerHidden]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static AsyncUniTaskMethodBuilder Create()
+        {
+            return default;
+        }
+
+        // 2. TaskLike Task property.
+        public UniTask Task
+        {
+            [DebuggerHidden]
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get
+            {
+                if (runnerPromise != null)
+                {
+                    return runnerPromise.Task;
+                }
+                else if (ex != null)
+                {
+                    return UniTask.FromException(ex);
+                }
+                else
+                {
+                    return UniTask.CompletedTask;
+                }
+            }
+        }
+
+        // 3. SetException
+        [DebuggerHidden]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void SetException(Exception exception)
+        {
+            if (runnerPromise == null)
+            {
+                ex = exception;
+            }
+            else
+            {
+                runnerPromise.SetException(exception);
+            }
+        }
+
+        // 4. SetResult
+        [DebuggerHidden]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void SetResult()
+        {
+            if (runnerPromise != null)
+            {
+                runnerPromise.SetResult();
+            }
+        }
+
+        // 5. AwaitOnCompleted
+        [DebuggerHidden]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
+            where TAwaiter : INotifyCompletion
+            where TStateMachine : IAsyncStateMachine
+        {
+            if (runnerPromise == null)
+            {
+                AsyncUniTask<TStateMachine>.SetStateMachine(ref stateMachine, ref runnerPromise);
+            }
+
+            awaiter.OnCompleted(runnerPromise.MoveNext);
+        }
+
+        // 6. AwaitUnsafeOnCompleted
+        [DebuggerHidden]
+        [SecuritySafeCritical]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
+            where TAwaiter : ICriticalNotifyCompletion
+            where TStateMachine : IAsyncStateMachine
+        {
+            if (runnerPromise == null)
+            {
+                AsyncUniTask<TStateMachine>.SetStateMachine(ref stateMachine, ref runnerPromise);
+            }
+
+            awaiter.UnsafeOnCompleted(runnerPromise.MoveNext);
+        }
+
+        // 7. Start
+        [DebuggerHidden]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void Start<TStateMachine>(ref TStateMachine stateMachine)
+            where TStateMachine : IAsyncStateMachine
+        {
+            stateMachine.MoveNext();
+        }
+
+        // 8. SetStateMachine
+        [DebuggerHidden]
+        public void SetStateMachine(IAsyncStateMachine stateMachine)
+        {
+            // don't use boxed stateMachine.
+        }
+
+#if DEBUG || !UNITY_2018_3_OR_NEWER
+        // Important for IDE debugger.
+        object debuggingId;
+        private object ObjectIdForDebugger
+        {
+            get
+            {
+                if (debuggingId == null)
+                {
+                    debuggingId = new object();
+                }
+                return debuggingId;
+            }
+        }
+#endif
+    }
+
+    [StructLayout(LayoutKind.Auto)]
+    public struct AsyncUniTaskMethodBuilder<T>
+    {
+        IStateMachineRunnerPromise<T> runnerPromise;
+        Exception ex;
+        T result;
+
+        // 1. Static Create method.
+        [DebuggerHidden]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static AsyncUniTaskMethodBuilder<T> Create()
+        {
+            return default;
+        }
+
+        // 2. TaskLike Task property.
+        public UniTask<T> Task
+        {
+            [DebuggerHidden]
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get
+            {
+                if (runnerPromise != null)
+                {
+                    return runnerPromise.Task;
+                }
+                else if (ex != null)
+                {
+                    return UniTask.FromException<T>(ex);
+                }
+                else
+                {
+                    return UniTask.FromResult(result);
+                }
+            }
+        }
+
+        // 3. SetException
+        [DebuggerHidden]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void SetException(Exception exception)
+        {
+            if (runnerPromise == null)
+            {
+                ex = exception;
+            }
+            else
+            {
+                runnerPromise.SetException(exception);
+            }
+        }
+
+        // 4. SetResult
+        [DebuggerHidden]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void SetResult(T result)
+        {
+            if (runnerPromise == null)
+            {
+                this.result = result;
+            }
+            else
+            {
+                runnerPromise.SetResult(result);
+            }
+        }
+
+        // 5. AwaitOnCompleted
+        [DebuggerHidden]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
+            where TAwaiter : INotifyCompletion
+            where TStateMachine : IAsyncStateMachine
+        {
+            if (runnerPromise == null)
+            {
+                AsyncUniTask<TStateMachine, T>.SetStateMachine(ref stateMachine, ref runnerPromise);
+            }
+
+            awaiter.OnCompleted(runnerPromise.MoveNext);
+        }
+
+        // 6. AwaitUnsafeOnCompleted
+        [DebuggerHidden]
+        [SecuritySafeCritical]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
+            where TAwaiter : ICriticalNotifyCompletion
+            where TStateMachine : IAsyncStateMachine
+        {
+            if (runnerPromise == null)
+            {
+                AsyncUniTask<TStateMachine, T>.SetStateMachine(ref stateMachine, ref runnerPromise);
+            }
+
+            awaiter.UnsafeOnCompleted(runnerPromise.MoveNext);
+        }
+
+        // 7. Start
+        [DebuggerHidden]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void Start<TStateMachine>(ref TStateMachine stateMachine)
+            where TStateMachine : IAsyncStateMachine
+        {
+            stateMachine.MoveNext();
+        }
+
+        // 8. SetStateMachine
+        [DebuggerHidden]
+        public void SetStateMachine(IAsyncStateMachine stateMachine)
+        {
+            // don't use boxed stateMachine.
+        }
+
+#if DEBUG || !UNITY_2018_3_OR_NEWER
+        // Important for IDE debugger.
+        object debuggingId;
+        private object ObjectIdForDebugger
+        {
+            get
+            {
+                if (debuggingId == null)
+                {
+                    debuggingId = new object();
+                }
+                return debuggingId;
+            }
+        }
+#endif
+
+    }
+}

+ 11 - 0
Assets/Plugins/UniTask/Runtime/CompilerServices/AsyncUniTaskMethodBuilder.cs.meta

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

+ 137 - 0
Assets/Plugins/UniTask/Runtime/CompilerServices/AsyncUniTaskVoidMethodBuilder.cs

@@ -0,0 +1,137 @@
+
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+
+using System;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Security;
+
+namespace Cysharp.Threading.Tasks.CompilerServices
+{
+    [StructLayout(LayoutKind.Auto)]
+    public struct AsyncUniTaskVoidMethodBuilder
+    {
+        IStateMachineRunner runner;
+
+        // 1. Static Create method.
+        [DebuggerHidden]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static AsyncUniTaskVoidMethodBuilder Create()
+        {
+            return default;
+        }
+
+        // 2. TaskLike Task property(void)
+        public UniTaskVoid Task
+        {
+            [DebuggerHidden]
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get
+            {
+                return default;
+            }
+        }
+
+        // 3. SetException
+        [DebuggerHidden]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void SetException(Exception exception)
+        {
+            // runner is finished, return first.
+            if (runner != null)
+            {
+#if ENABLE_IL2CPP
+                // workaround for IL2CPP bug.
+                PlayerLoopHelper.AddContinuation(PlayerLoopTiming.LastPostLateUpdate, runner.ReturnAction);
+#else
+                runner.Return();
+#endif
+                runner = null;
+            }
+
+            UniTaskScheduler.PublishUnobservedTaskException(exception);
+        }
+
+        // 4. SetResult
+        [DebuggerHidden]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void SetResult()
+        {
+            // runner is finished, return.
+            if (runner != null)
+            {
+#if ENABLE_IL2CPP
+                // workaround for IL2CPP bug.
+                PlayerLoopHelper.AddContinuation(PlayerLoopTiming.LastPostLateUpdate, runner.ReturnAction);
+#else
+                runner.Return();
+#endif
+                runner = null;
+            }
+        }
+
+        // 5. AwaitOnCompleted
+        [DebuggerHidden]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
+            where TAwaiter : INotifyCompletion
+            where TStateMachine : IAsyncStateMachine
+        {
+            if (runner == null)
+            {
+                AsyncUniTaskVoid<TStateMachine>.SetStateMachine(ref stateMachine, ref runner);
+            }
+
+            awaiter.OnCompleted(runner.MoveNext);
+        }
+
+        // 6. AwaitUnsafeOnCompleted
+        [DebuggerHidden]
+        [SecuritySafeCritical]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
+            where TAwaiter : ICriticalNotifyCompletion
+            where TStateMachine : IAsyncStateMachine
+        {
+            if (runner == null)
+            {
+                AsyncUniTaskVoid<TStateMachine>.SetStateMachine(ref stateMachine, ref runner);
+            }
+
+            awaiter.UnsafeOnCompleted(runner.MoveNext);
+        }
+
+        // 7. Start
+        [DebuggerHidden]
+        public void Start<TStateMachine>(ref TStateMachine stateMachine)
+            where TStateMachine : IAsyncStateMachine
+        {
+            stateMachine.MoveNext();
+        }
+
+        // 8. SetStateMachine
+        [DebuggerHidden]
+        public void SetStateMachine(IAsyncStateMachine stateMachine)
+        {
+            // don't use boxed stateMachine.
+        }
+
+#if DEBUG || !UNITY_2018_3_OR_NEWER
+        // Important for IDE debugger.
+        object debuggingId;
+        private object ObjectIdForDebugger
+        {
+            get
+            {
+                if (debuggingId == null)
+                {
+                    debuggingId = new object();
+                }
+                return debuggingId;
+            }
+        }
+#endif
+    }
+}
+

+ 11 - 0
Assets/Plugins/UniTask/Runtime/CompilerServices/AsyncUniTaskVoidMethodBuilder.cs.meta

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

+ 380 - 0
Assets/Plugins/UniTask/Runtime/CompilerServices/StateMachineRunner.cs

@@ -0,0 +1,380 @@
+#pragma warning disable CS1591
+
+using Cysharp.Threading.Tasks.Internal;
+using System;
+using System.Linq;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+
+namespace Cysharp.Threading.Tasks.CompilerServices
+{
+    // #ENABLE_IL2CPP in this file is to avoid bug of IL2CPP VM.
+    // Issue is tracked on https://issuetracker.unity3d.com/issues/il2cpp-incorrect-results-when-calling-a-method-from-outside-class-in-a-struct
+    // but currently it is labeled `Won't Fix`.
+
+    internal interface IStateMachineRunner
+    {
+        Action MoveNext { get; }
+        void Return();
+
+#if ENABLE_IL2CPP
+        Action ReturnAction { get; }
+#endif
+    }
+
+    internal interface IStateMachineRunnerPromise : IUniTaskSource
+    {
+        Action MoveNext { get; }
+        UniTask Task { get; }
+        void SetResult();
+        void SetException(Exception exception);
+    }
+
+    internal interface IStateMachineRunnerPromise<T> : IUniTaskSource<T>
+    {
+        Action MoveNext { get; }
+        UniTask<T> Task { get; }
+        void SetResult(T result);
+        void SetException(Exception exception);
+    }
+
+    internal static class StateMachineUtility
+    {
+        // Get AsyncStateMachine internal state to check IL2CPP bug
+        public static int GetState(IAsyncStateMachine stateMachine)
+        {
+            var info = stateMachine.GetType().GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)
+                .First(x => x.Name.EndsWith("__state"));
+            return (int)info.GetValue(stateMachine);
+        }
+    }
+
+    internal sealed class AsyncUniTaskVoid<TStateMachine> : IStateMachineRunner, ITaskPoolNode<AsyncUniTaskVoid<TStateMachine>>, IUniTaskSource
+        where TStateMachine : IAsyncStateMachine
+    {
+        static TaskPool<AsyncUniTaskVoid<TStateMachine>> pool;
+
+#if ENABLE_IL2CPP
+        public Action ReturnAction { get; }
+#endif
+
+        TStateMachine stateMachine;
+
+        public Action MoveNext { get; }
+
+        public AsyncUniTaskVoid()
+        {
+            MoveNext = Run;
+#if ENABLE_IL2CPP
+            ReturnAction = Return;
+#endif
+        }
+
+        public static void SetStateMachine(ref TStateMachine stateMachine, ref IStateMachineRunner runnerFieldRef)
+        {
+            if (!pool.TryPop(out var result))
+            {
+                result = new AsyncUniTaskVoid<TStateMachine>();
+            }
+            TaskTracker.TrackActiveTask(result, 3);
+
+            runnerFieldRef = result; // set runner before copied.
+            result.stateMachine = stateMachine; // copy struct StateMachine(in release build).
+        }
+
+        static AsyncUniTaskVoid()
+        {
+            TaskPool.RegisterSizeGetter(typeof(AsyncUniTaskVoid<TStateMachine>), () => pool.Size);
+        }
+
+        AsyncUniTaskVoid<TStateMachine> nextNode;
+        public ref AsyncUniTaskVoid<TStateMachine> NextNode => ref nextNode;
+
+        public void Return()
+        {
+            TaskTracker.RemoveTracking(this);
+            stateMachine = default;
+            pool.TryPush(this);
+        }
+
+        [DebuggerHidden]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        void Run()
+        {
+            stateMachine.MoveNext();
+        }
+
+        // dummy interface implementation for TaskTracker.
+
+        UniTaskStatus IUniTaskSource.GetStatus(short token)
+        {
+            return UniTaskStatus.Pending;
+        }
+
+        UniTaskStatus IUniTaskSource.UnsafeGetStatus()
+        {
+            return UniTaskStatus.Pending;
+        }
+
+        void IUniTaskSource.OnCompleted(Action<object> continuation, object state, short token)
+        {
+        }
+
+        void IUniTaskSource.GetResult(short token)
+        {
+        }
+    }
+
+    internal sealed class AsyncUniTask<TStateMachine> : IStateMachineRunnerPromise, IUniTaskSource, ITaskPoolNode<AsyncUniTask<TStateMachine>>
+        where TStateMachine : IAsyncStateMachine
+    {
+        static TaskPool<AsyncUniTask<TStateMachine>> pool;
+
+#if ENABLE_IL2CPP
+        readonly Action returnDelegate;  
+#endif
+        public Action MoveNext { get; }
+
+        TStateMachine stateMachine;
+        UniTaskCompletionSourceCore<AsyncUnit> core;
+
+        AsyncUniTask()
+        {
+            MoveNext = Run;
+#if ENABLE_IL2CPP
+            returnDelegate = Return;
+#endif
+        }
+
+        public static void SetStateMachine(ref TStateMachine stateMachine, ref IStateMachineRunnerPromise runnerPromiseFieldRef)
+        {
+            if (!pool.TryPop(out var result))
+            {
+                result = new AsyncUniTask<TStateMachine>();
+            }
+            TaskTracker.TrackActiveTask(result, 3);
+
+            runnerPromiseFieldRef = result; // set runner before copied.
+            result.stateMachine = stateMachine; // copy struct StateMachine(in release build).
+        }
+
+        AsyncUniTask<TStateMachine> nextNode;
+        public ref AsyncUniTask<TStateMachine> NextNode => ref nextNode;
+
+        static AsyncUniTask()
+        {
+            TaskPool.RegisterSizeGetter(typeof(AsyncUniTask<TStateMachine>), () => pool.Size);
+        }
+
+        void Return()
+        {
+            TaskTracker.RemoveTracking(this);
+            core.Reset();
+            stateMachine = default;
+            pool.TryPush(this);
+        }
+
+        bool TryReturn()
+        {
+            TaskTracker.RemoveTracking(this);
+            core.Reset();
+            stateMachine = default;
+            return pool.TryPush(this);
+        }
+
+        [DebuggerHidden]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        void Run()
+        {
+            stateMachine.MoveNext();
+        }
+
+        public UniTask Task
+        {
+            [DebuggerHidden]
+            get
+            {
+                return new UniTask(this, core.Version);
+            }
+        }
+
+        [DebuggerHidden]
+        public void SetResult()
+        {
+            core.TrySetResult(AsyncUnit.Default);
+        }
+
+        [DebuggerHidden]
+        public void SetException(Exception exception)
+        {
+            core.TrySetException(exception);
+        }
+
+        [DebuggerHidden]
+        public void GetResult(short token)
+        {
+            try
+            {
+                core.GetResult(token);
+            }
+            finally
+            {
+#if ENABLE_IL2CPP
+                // workaround for IL2CPP bug.
+                PlayerLoopHelper.AddContinuation(PlayerLoopTiming.LastPostLateUpdate, returnDelegate);
+#else
+                TryReturn();
+#endif
+            }
+        }
+
+        [DebuggerHidden]
+        public UniTaskStatus GetStatus(short token)
+        {
+            return core.GetStatus(token);
+        }
+
+        [DebuggerHidden]
+        public UniTaskStatus UnsafeGetStatus()
+        {
+            return core.UnsafeGetStatus();
+        }
+
+        [DebuggerHidden]
+        public void OnCompleted(Action<object> continuation, object state, short token)
+        {
+            core.OnCompleted(continuation, state, token);
+        }
+    }
+
+    internal sealed class AsyncUniTask<TStateMachine, T> : IStateMachineRunnerPromise<T>, IUniTaskSource<T>, ITaskPoolNode<AsyncUniTask<TStateMachine, T>>
+        where TStateMachine : IAsyncStateMachine
+    {
+        static TaskPool<AsyncUniTask<TStateMachine, T>> pool;
+
+#if ENABLE_IL2CPP
+        readonly Action returnDelegate;  
+#endif
+
+        public Action MoveNext { get; }
+
+        TStateMachine stateMachine;
+        UniTaskCompletionSourceCore<T> core;
+
+        AsyncUniTask()
+        {
+            MoveNext = Run;
+#if ENABLE_IL2CPP
+            returnDelegate = Return;
+#endif
+        }
+
+        public static void SetStateMachine(ref TStateMachine stateMachine, ref IStateMachineRunnerPromise<T> runnerPromiseFieldRef)
+        {
+            if (!pool.TryPop(out var result))
+            {
+                result = new AsyncUniTask<TStateMachine, T>();
+            }
+            TaskTracker.TrackActiveTask(result, 3);
+
+            runnerPromiseFieldRef = result; // set runner before copied.
+            result.stateMachine = stateMachine; // copy struct StateMachine(in release build).
+        }
+
+        AsyncUniTask<TStateMachine, T> nextNode;
+        public ref AsyncUniTask<TStateMachine, T> NextNode => ref nextNode;
+
+        static AsyncUniTask()
+        {
+            TaskPool.RegisterSizeGetter(typeof(AsyncUniTask<TStateMachine, T>), () => pool.Size);
+        }
+
+        void Return()
+        {
+            TaskTracker.RemoveTracking(this);
+            core.Reset();
+            stateMachine = default;
+            pool.TryPush(this);
+        }
+
+        bool TryReturn()
+        {
+            TaskTracker.RemoveTracking(this);
+            core.Reset();
+            stateMachine = default;
+            return pool.TryPush(this);
+        }
+
+        [DebuggerHidden]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        void Run()
+        {
+            // UnityEngine.Debug.Log($"MoveNext State:" + StateMachineUtility.GetState(stateMachine));
+            stateMachine.MoveNext();
+        }
+
+        public UniTask<T> Task
+        {
+            [DebuggerHidden]
+            get
+            {
+                return new UniTask<T>(this, core.Version);
+            }
+        }
+
+        [DebuggerHidden]
+        public void SetResult(T result)
+        {
+            core.TrySetResult(result);
+        }
+
+        [DebuggerHidden]
+        public void SetException(Exception exception)
+        {
+            core.TrySetException(exception);
+        }
+
+        [DebuggerHidden]
+        public T GetResult(short token)
+        {
+            try
+            {
+                return core.GetResult(token);
+            }
+            finally
+            {
+#if ENABLE_IL2CPP
+                // workaround for IL2CPP bug.
+                PlayerLoopHelper.AddContinuation(PlayerLoopTiming.LastPostLateUpdate, returnDelegate);
+#else
+                TryReturn();
+#endif
+            }
+        }
+
+        [DebuggerHidden]
+        void IUniTaskSource.GetResult(short token)
+        {
+            GetResult(token);
+        }
+
+        [DebuggerHidden]
+        public UniTaskStatus GetStatus(short token)
+        {
+            return core.GetStatus(token);
+        }
+
+        [DebuggerHidden]
+        public UniTaskStatus UnsafeGetStatus()
+        {
+            return core.UnsafeGetStatus();
+        }
+
+        [DebuggerHidden]
+        public void OnCompleted(Action<object> continuation, object state, short token)
+        {
+            core.OnCompleted(continuation, state, token);
+        }
+    }
+}
+

+ 11 - 0
Assets/Plugins/UniTask/Runtime/CompilerServices/StateMachineRunner.cs.meta

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

+ 34 - 0
Assets/Plugins/UniTask/Runtime/EnumerableAsyncExtensions.cs

@@ -0,0 +1,34 @@
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+
+using System;
+using System.Collections.Generic;
+
+namespace Cysharp.Threading.Tasks
+{
+    public static class EnumerableAsyncExtensions
+    {
+        // overload resolver - .Select(async x => { }) : IEnumerable<UniTask<T>>
+
+        public static IEnumerable<UniTask> Select<T>(this IEnumerable<T> source, Func<T, UniTask> selector)
+        {
+            return System.Linq.Enumerable.Select(source, selector);
+        }
+
+        public static IEnumerable<UniTask<TR>> Select<T, TR>(this IEnumerable<T> source, Func<T, UniTask<TR>> selector)
+        {
+            return System.Linq.Enumerable.Select(source, selector);
+        }
+
+        public static IEnumerable<UniTask> Select<T>(this IEnumerable<T> source, Func<T, int, UniTask> selector)
+        {
+            return System.Linq.Enumerable.Select(source, selector);
+        }
+
+        public static IEnumerable<UniTask<TR>> Select<T, TR>(this IEnumerable<T> source, Func<T, int, UniTask<TR>> selector)
+        {
+            return System.Linq.Enumerable.Select(source, selector);
+        }
+    }
+}
+
+

+ 11 - 0
Assets/Plugins/UniTask/Runtime/EnumerableAsyncExtensions.cs.meta

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

+ 287 - 0
Assets/Plugins/UniTask/Runtime/EnumeratorAsyncExtensions.cs

@@ -0,0 +1,287 @@
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+
+using System;
+using System.Collections;
+using System.Reflection;
+using System.Runtime.ExceptionServices;
+using System.Threading;
+using Cysharp.Threading.Tasks.Internal;
+using UnityEngine;
+
+namespace Cysharp.Threading.Tasks
+{
+    public static class EnumeratorAsyncExtensions
+    {
+        public static UniTask.Awaiter GetAwaiter<T>(this T enumerator)
+            where T : IEnumerator
+        {
+            var e = (IEnumerator)enumerator;
+            Error.ThrowArgumentNullException(e, nameof(enumerator));
+            return new UniTask(EnumeratorPromise.Create(e, PlayerLoopTiming.Update, CancellationToken.None, out var token), token).GetAwaiter();
+        }
+
+        public static UniTask WithCancellation(this IEnumerator enumerator, CancellationToken cancellationToken)
+        {
+            Error.ThrowArgumentNullException(enumerator, nameof(enumerator));
+            return new UniTask(EnumeratorPromise.Create(enumerator, PlayerLoopTiming.Update, cancellationToken, out var token), token);
+        }
+
+        public static UniTask ToUniTask(this IEnumerator enumerator, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken))
+        {
+            Error.ThrowArgumentNullException(enumerator, nameof(enumerator));
+            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>
+        {
+            static TaskPool<EnumeratorPromise> pool;
+            EnumeratorPromise nextNode;
+            public ref EnumeratorPromise NextNode => ref nextNode;
+
+            static EnumeratorPromise()
+            {
+                TaskPool.RegisterSizeGetter(typeof(EnumeratorPromise), () => pool.Size);
+            }
+
+            IEnumerator innerEnumerator;
+            CancellationToken cancellationToken;
+            int initialFrame;
+            bool loopRunning;
+            bool calledGetResult;
+
+            UniTaskCompletionSourceCore<object> core;
+
+            EnumeratorPromise()
+            {
+            }
+
+            public static IUniTaskSource Create(IEnumerator innerEnumerator, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
+            {
+                if (cancellationToken.IsCancellationRequested)
+                {
+                    return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token);
+                }
+
+                if (!pool.TryPop(out var result))
+                {
+                    result = new EnumeratorPromise();
+                }
+                TaskTracker.TrackActiveTask(result, 3);
+
+                result.innerEnumerator = ConsumeEnumerator(innerEnumerator);
+                result.cancellationToken = cancellationToken;
+                result.loopRunning = true;
+                result.calledGetResult = false;
+                result.initialFrame = -1;
+
+                token = result.core.Version;
+
+                // run immediately.
+                if (result.MoveNext())
+                {
+                    PlayerLoopHelper.AddAction(timing, result);
+                }
+                
+                return result;
+            }
+
+            public void GetResult(short token)
+            {
+                try
+                {
+                    calledGetResult = true;
+                    core.GetResult(token);
+                }
+                finally
+                {
+                    if (!loopRunning)
+                    {
+                        TryReturn();
+                    }
+                }
+            }
+
+            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 (calledGetResult)
+                {
+                    loopRunning = false;
+                    TryReturn();
+                    return false;
+                }
+
+                if (innerEnumerator == null) // invalid status, returned but loop running?
+                {
+                    return false;
+                }
+
+                if (cancellationToken.IsCancellationRequested)
+                {
+                    loopRunning = false;
+                    core.TrySetCanceled(cancellationToken);
+                    return false;
+                }
+
+                if (initialFrame == -1)
+                {
+                    // Time can not touch in threadpool.
+                    if (PlayerLoopHelper.IsMainThread)
+                    {
+                        initialFrame = Time.frameCount;
+                    }
+                }
+                else if (initialFrame == Time.frameCount)
+                {
+                    return true; // already executed in first frame, skip.
+                }
+
+                try
+                {
+                    if (innerEnumerator.MoveNext())
+                    {
+                        return true;
+                    }
+                }
+                catch (Exception ex)
+                {
+                    loopRunning = false;
+                    core.TrySetException(ex);
+                    return false;
+                }
+
+                loopRunning = false;
+                core.TrySetResult(null);
+                return false;
+            }
+
+            bool TryReturn()
+            {
+                TaskTracker.RemoveTracking(this);
+                core.Reset();
+                innerEnumerator = default;
+                cancellationToken = default;
+
+                return pool.TryPush(this);
+            }
+
+            // Unwrap YieldInstructions
+
+            static IEnumerator ConsumeEnumerator(IEnumerator enumerator)
+            {
+                while (enumerator.MoveNext())
+                {
+                    var current = enumerator.Current;
+                    if (current == null)
+                    {
+                        yield return null;
+                    }
+                    else if (current is CustomYieldInstruction cyi)
+                    {
+                        // WWW, WaitForSecondsRealtime
+                        while (cyi.keepWaiting)
+                        {
+                            yield return null;
+                        }
+                    }
+                    else if (current is YieldInstruction)
+                    {
+                        IEnumerator innerCoroutine = null;
+                        switch (current)
+                        {
+                            case AsyncOperation ao:
+                                innerCoroutine = UnwrapWaitAsyncOperation(ao);
+                                break;
+                            case WaitForSeconds wfs:
+                                innerCoroutine = UnwrapWaitForSeconds(wfs);
+                                break;
+                        }
+                        if (innerCoroutine != null)
+                        {
+                            while (innerCoroutine.MoveNext())
+                            {
+                                yield return null;
+                            }
+                        }
+                        else
+                        {
+                            goto WARN;
+                        }
+                    }
+                    else if (current is IEnumerator e3)
+                    {
+                        var e4 = ConsumeEnumerator(e3);
+                        while (e4.MoveNext())
+                        {
+                            yield return null;
+                        }
+                    }
+                    else
+                    {
+                        goto WARN;
+                    }
+
+                    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;
+                }
+            }
+
+            static readonly FieldInfo waitForSeconds_Seconds = typeof(WaitForSeconds).GetField("m_Seconds", BindingFlags.Instance | BindingFlags.GetField | BindingFlags.NonPublic);
+
+            static IEnumerator UnwrapWaitForSeconds(WaitForSeconds waitForSeconds)
+            {
+                var second = (float)waitForSeconds_Seconds.GetValue(waitForSeconds);
+                var elapsed = 0.0f;
+                while (true)
+                {
+                    yield return null;
+
+                    elapsed += Time.deltaTime;
+                    if (elapsed >= second)
+                    {
+                        break;
+                    }
+                };
+            }
+
+            static IEnumerator UnwrapWaitAsyncOperation(AsyncOperation asyncOperation)
+            {
+                while (!asyncOperation.isDone)
+                {
+                    yield return null;
+                }
+            }
+        }
+    }
+}

+ 11 - 0
Assets/Plugins/UniTask/Runtime/EnumeratorAsyncExtensions.cs.meta

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

+ 14 - 0
Assets/Plugins/UniTask/Runtime/ExceptionExtensions.cs

@@ -0,0 +1,14 @@
+
+using System;
+
+namespace Cysharp.Threading.Tasks
+{
+    public static class ExceptionExtensions
+    {
+        public static bool IsOperationCanceledException(this Exception exception)
+        {
+            return exception is OperationCanceledException;
+        }
+    }
+}
+

+ 11 - 0
Assets/Plugins/UniTask/Runtime/ExceptionExtensions.cs.meta

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

+ 8 - 0
Assets/Plugins/UniTask/Runtime/External.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: cf517c50f33e7d44ba67f73d9af65b7c
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
Assets/Plugins/UniTask/Runtime/External/Addressables.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: d1069caf8c315764eb37219313ae63cc
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 483 - 0
Assets/Plugins/UniTask/Runtime/External/Addressables/AddressablesAsyncExtensions.cs

@@ -0,0 +1,483 @@
+// asmdef Version Defines, enabled when com.unity.addressables is imported.
+
+#if UNITASK_ADDRESSABLE_SUPPORT
+
+using Cysharp.Threading.Tasks.Internal;
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.ExceptionServices;
+using System.Threading;
+using UnityEngine.AddressableAssets;
+using UnityEngine.ResourceManagement.AsyncOperations;
+
+namespace Cysharp.Threading.Tasks
+{
+    public static class AddressablesAsyncExtensions
+    {
+#region AsyncOperationHandle
+
+        public static UniTask.Awaiter GetAwaiter(this AsyncOperationHandle handle)
+        {
+            return ToUniTask(handle).GetAwaiter();
+        }
+
+        public static UniTask WithCancellation(this AsyncOperationHandle handle, CancellationToken cancellationToken, bool cancelImmediately = false, bool autoReleaseWhenCanceled = false)
+        {
+            return ToUniTask(handle, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately, autoReleaseWhenCanceled: autoReleaseWhenCanceled);
+        }
+
+        public static UniTask ToUniTask(this AsyncOperationHandle handle, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false, bool autoReleaseWhenCanceled = false)
+        {
+            if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled(cancellationToken);
+
+            if (!handle.IsValid())
+            {
+                // autoReleaseHandle:true handle is invalid(immediately internal handle == null) so return completed.
+                return UniTask.CompletedTask;
+            }
+
+            if (handle.IsDone)
+            {
+                if (handle.Status == AsyncOperationStatus.Failed)
+                {
+                    return UniTask.FromException(handle.OperationException);
+                }
+                return UniTask.CompletedTask;
+            }
+
+            return new UniTask(AsyncOperationHandleConfiguredSource.Create(handle, timing, progress, cancellationToken, cancelImmediately, autoReleaseWhenCanceled, out var token), token);
+        }
+
+        public struct AsyncOperationHandleAwaiter : ICriticalNotifyCompletion
+        {
+            AsyncOperationHandle handle;
+            Action<AsyncOperationHandle> continuationAction;
+
+            public AsyncOperationHandleAwaiter(AsyncOperationHandle handle)
+            {
+                this.handle = handle;
+                this.continuationAction = null;
+            }
+
+            public bool IsCompleted => handle.IsDone;
+
+            public void GetResult()
+            {
+                if (continuationAction != null)
+                {
+                    handle.Completed -= continuationAction;
+                    continuationAction = null;
+                }
+
+                if (handle.Status == AsyncOperationStatus.Failed)
+                {
+                    var e = handle.OperationException;
+                    handle = default;
+                    ExceptionDispatchInfo.Capture(e).Throw();
+                }
+
+                var result = handle.Result;
+                handle = default;
+            }
+
+            public void OnCompleted(Action continuation)
+            {
+                UnsafeOnCompleted(continuation);
+            }
+
+            public void UnsafeOnCompleted(Action continuation)
+            {
+                Error.ThrowWhenContinuationIsAlreadyRegistered(continuationAction);
+                continuationAction = PooledDelegate<AsyncOperationHandle>.Create(continuation);
+                handle.Completed += continuationAction;
+            }
+        }
+
+        sealed class AsyncOperationHandleConfiguredSource : IUniTaskSource, IPlayerLoopItem, ITaskPoolNode<AsyncOperationHandleConfiguredSource>
+        {
+            static TaskPool<AsyncOperationHandleConfiguredSource> pool;
+            AsyncOperationHandleConfiguredSource nextNode;
+            public ref AsyncOperationHandleConfiguredSource NextNode => ref nextNode;
+
+            static AsyncOperationHandleConfiguredSource()
+            {
+                TaskPool.RegisterSizeGetter(typeof(AsyncOperationHandleConfiguredSource), () => pool.Size);
+            }
+
+            readonly Action<AsyncOperationHandle> completedCallback;
+            AsyncOperationHandle handle;
+            CancellationToken cancellationToken;
+            CancellationTokenRegistration cancellationTokenRegistration;
+            IProgress<float> progress;
+            bool autoReleaseWhenCanceled;
+            bool cancelImmediately;
+            bool completed;
+
+            UniTaskCompletionSourceCore<AsyncUnit> core;
+
+            AsyncOperationHandleConfiguredSource()
+            {
+                completedCallback = HandleCompleted;
+            }
+
+            public static IUniTaskSource Create(AsyncOperationHandle handle, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, bool cancelImmediately, bool autoReleaseWhenCanceled, out short token)
+            {
+                if (cancellationToken.IsCancellationRequested)
+                {
+                    return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token);
+                }
+
+                if (!pool.TryPop(out var result))
+                {
+                    result = new AsyncOperationHandleConfiguredSource();
+                }
+
+                result.handle = handle;
+                result.progress = progress;
+                result.cancellationToken = cancellationToken;
+                result.cancelImmediately = cancelImmediately;
+                result.autoReleaseWhenCanceled = autoReleaseWhenCanceled;
+                result.completed = false;
+                
+                if (cancelImmediately && cancellationToken.CanBeCanceled)
+                {
+                    result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
+                    {
+                        var promise = (AsyncOperationHandleConfiguredSource)state;
+                        if (promise.autoReleaseWhenCanceled && promise.handle.IsValid())
+                        {
+                            Addressables.Release(promise.handle);
+                        }
+                        promise.core.TrySetCanceled(promise.cancellationToken);
+                    }, result);
+                }
+
+                TaskTracker.TrackActiveTask(result, 3);
+
+                PlayerLoopHelper.AddAction(timing, result);
+
+                handle.Completed += result.completedCallback;
+
+                token = result.core.Version;
+                return result;
+            }
+
+            void HandleCompleted(AsyncOperationHandle _)
+            {
+                if (handle.IsValid())
+                {
+                    handle.Completed -= completedCallback;
+                }
+
+                if (completed)
+                {
+                    return;
+                }
+                
+                completed = true;
+                if (cancellationToken.IsCancellationRequested)
+                {
+                    if (autoReleaseWhenCanceled && handle.IsValid())
+                    {
+                        Addressables.Release(handle);
+                    }
+                    core.TrySetCanceled(cancellationToken);
+                }
+                else if (handle.Status == AsyncOperationStatus.Failed)
+                {
+                    core.TrySetException(handle.OperationException);
+                }
+                else
+                {
+                    core.TrySetResult(AsyncUnit.Default);
+                }
+            }
+
+            public void GetResult(short token)
+            {
+                try
+                {
+                    core.GetResult(token);
+                }
+                finally
+                {
+                    if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
+                    {
+                        TryReturn();
+                    }
+                    else
+                    {
+                        TaskTracker.RemoveTracking(this);
+                    }
+                }
+            }
+
+            public UniTaskStatus GetStatus(short token)
+            {
+                return core.GetStatus(token);
+            }
+
+            public UniTaskStatus UnsafeGetStatus()
+            {
+                return core.UnsafeGetStatus();
+            }
+
+            public void OnCompleted(Action<object> continuation, object state, short token)
+            {
+                core.OnCompleted(continuation, state, token);
+            }
+
+            public bool MoveNext()
+            {
+                if (completed)
+                {
+                    return false;
+                }
+
+                if (cancellationToken.IsCancellationRequested)
+                {
+                    completed = true;
+                    if (autoReleaseWhenCanceled && handle.IsValid())
+                    {
+                        Addressables.Release(handle);
+                    }
+                    core.TrySetCanceled(cancellationToken);
+                    return false;
+                }
+
+                if (progress != null && handle.IsValid())
+                {
+                    progress.Report(handle.GetDownloadStatus().Percent);
+                }
+
+                return true;
+            }
+
+            bool TryReturn()
+            {
+                TaskTracker.RemoveTracking(this);
+                core.Reset();
+                handle = default;
+                progress = default;
+                cancellationToken = default;
+                cancellationTokenRegistration.Dispose();
+                return pool.TryPush(this);
+            }
+        }
+
+#endregion
+
+#region AsyncOperationHandle_T
+
+        public static UniTask<T>.Awaiter GetAwaiter<T>(this AsyncOperationHandle<T> handle)
+        {
+            return ToUniTask(handle).GetAwaiter();
+        }
+
+        public static UniTask<T> WithCancellation<T>(this AsyncOperationHandle<T> handle, CancellationToken cancellationToken, bool cancelImmediately = false, bool autoReleaseWhenCanceled = false)
+        {
+            return ToUniTask(handle, cancellationToken: cancellationToken, cancelImmediately: cancelImmediately, autoReleaseWhenCanceled: autoReleaseWhenCanceled);
+        }
+
+        public static UniTask<T> ToUniTask<T>(this AsyncOperationHandle<T> handle, IProgress<float> progress = null, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default(CancellationToken), bool cancelImmediately = false, bool autoReleaseWhenCanceled = false)
+        {
+            if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<T>(cancellationToken);
+
+            if (!handle.IsValid())
+            {
+                throw new Exception("Attempting to use an invalid operation handle");
+            }
+
+            if (handle.IsDone)
+            {
+                if (handle.Status == AsyncOperationStatus.Failed)
+                {
+                    return UniTask.FromException<T>(handle.OperationException);
+                }
+                return UniTask.FromResult(handle.Result);
+            }
+
+            return new UniTask<T>(AsyncOperationHandleConfiguredSource<T>.Create(handle, timing, progress, cancellationToken, cancelImmediately, autoReleaseWhenCanceled, out var token), token);
+        }
+
+        sealed class AsyncOperationHandleConfiguredSource<T> : IUniTaskSource<T>, IPlayerLoopItem, ITaskPoolNode<AsyncOperationHandleConfiguredSource<T>>
+        {
+            static TaskPool<AsyncOperationHandleConfiguredSource<T>> pool;
+            AsyncOperationHandleConfiguredSource<T> nextNode;
+            public ref AsyncOperationHandleConfiguredSource<T> NextNode => ref nextNode;
+
+            static AsyncOperationHandleConfiguredSource()
+            {
+                TaskPool.RegisterSizeGetter(typeof(AsyncOperationHandleConfiguredSource<T>), () => pool.Size);
+            }
+
+            readonly Action<AsyncOperationHandle<T>> completedCallback;
+            AsyncOperationHandle<T> handle;
+            CancellationToken cancellationToken;
+            CancellationTokenRegistration cancellationTokenRegistration;
+            IProgress<float> progress;
+            bool autoReleaseWhenCanceled;
+            bool cancelImmediately;
+            bool completed;
+
+            UniTaskCompletionSourceCore<T> core;
+
+            AsyncOperationHandleConfiguredSource()
+            {
+                completedCallback = HandleCompleted;
+            }
+
+            public static IUniTaskSource<T> Create(AsyncOperationHandle<T> handle, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, bool cancelImmediately, bool autoReleaseWhenCanceled, out short token)
+            {
+                if (cancellationToken.IsCancellationRequested)
+                {
+                    return AutoResetUniTaskCompletionSource<T>.CreateFromCanceled(cancellationToken, out token);
+                }
+
+                if (!pool.TryPop(out var result))
+                {
+                    result = new AsyncOperationHandleConfiguredSource<T>();
+                }
+
+                result.handle = handle;
+                result.cancellationToken = cancellationToken;
+                result.completed = false;
+                result.progress = progress;
+                result.autoReleaseWhenCanceled = autoReleaseWhenCanceled;
+                result.cancelImmediately = cancelImmediately;
+                
+                if (cancelImmediately && cancellationToken.CanBeCanceled)
+                {
+                    result.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(state =>
+                    {
+                        var promise = (AsyncOperationHandleConfiguredSource<T>)state;
+                        if (promise.autoReleaseWhenCanceled && promise.handle.IsValid())
+                        {
+                            Addressables.Release(promise.handle);
+                        }
+                        promise.core.TrySetCanceled(promise.cancellationToken);
+                    }, result);
+                }
+
+                TaskTracker.TrackActiveTask(result, 3);
+
+                PlayerLoopHelper.AddAction(timing, result);
+
+                handle.Completed += result.completedCallback;
+
+                token = result.core.Version;
+                return result;
+            }
+
+            void HandleCompleted(AsyncOperationHandle<T> argHandle)
+            {
+                if (handle.IsValid())
+                {
+                    handle.Completed -= completedCallback;
+                }
+
+                if (completed)
+                {
+                    return;
+                }
+                completed = true;
+                if (cancellationToken.IsCancellationRequested)
+                {
+                    if (autoReleaseWhenCanceled && handle.IsValid())
+                    {
+                        Addressables.Release(handle);
+                    }
+                    core.TrySetCanceled(cancellationToken);
+                }
+                else if (argHandle.Status == AsyncOperationStatus.Failed)
+                {
+                    core.TrySetException(argHandle.OperationException);
+                }
+                else
+                {
+                    core.TrySetResult(argHandle.Result);
+                }
+            }
+
+            public T GetResult(short token)
+            {
+                try
+                {
+                    return core.GetResult(token);
+                }
+                finally
+                {
+                    if (!(cancelImmediately && cancellationToken.IsCancellationRequested))
+                    {
+                        TryReturn();
+                    }
+                    else
+                    {
+                        TaskTracker.RemoveTracking(this);
+                    }
+                }
+            }
+
+            void IUniTaskSource.GetResult(short token)
+            {
+                GetResult(token);
+            }
+
+            public UniTaskStatus GetStatus(short token)
+            {
+                return core.GetStatus(token);
+            }
+
+            public UniTaskStatus UnsafeGetStatus()
+            {
+                return core.UnsafeGetStatus();
+            }
+
+            public void OnCompleted(Action<object> continuation, object state, short token)
+            {
+                core.OnCompleted(continuation, state, token);
+            }
+
+            public bool MoveNext()
+            {
+                if (completed)
+                {
+                    return false;
+                }
+
+                if (cancellationToken.IsCancellationRequested)
+                {
+                    completed = true;
+                    if (autoReleaseWhenCanceled && handle.IsValid())
+                    {
+                        Addressables.Release(handle);
+                    }
+                    core.TrySetCanceled(cancellationToken);
+                    return false;
+                }
+
+                if (progress != null && handle.IsValid())
+                {
+                    progress.Report(handle.GetDownloadStatus().Percent);
+                }
+
+                return true;
+            }
+
+            bool TryReturn()
+            {
+                TaskTracker.RemoveTracking(this);
+                core.Reset();
+                handle = default;
+                progress = default;
+                cancellationToken = default;
+                cancellationTokenRegistration.Dispose();
+                return pool.TryPush(this);
+            }
+        }
+
+#endregion
+    }
+}
+
+#endif

+ 11 - 0
Assets/Plugins/UniTask/Runtime/External/Addressables/AddressablesAsyncExtensions.cs.meta

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

+ 28 - 0
Assets/Plugins/UniTask/Runtime/External/Addressables/UniTask.Addressables.asmdef

@@ -0,0 +1,28 @@
+{
+    "name": "UniTask.Addressables",
+    "references": [
+        "UniTask",
+        "Unity.ResourceManager",
+        "Unity.Addressables"
+    ],
+    "includePlatforms": [],
+    "excludePlatforms": [],
+    "allowUnsafeCode": false,
+    "overrideReferences": false,
+    "precompiledReferences": [],
+    "autoReferenced": true,
+    "defineConstraints": [],
+    "versionDefines": [
+        {
+            "name": "com.unity.addressables",
+            "expression": "",
+            "define": "UNITASK_ADDRESSABLE_SUPPORT"
+        },
+	{
+            "name": "com.unity.addressables.cn",
+            "expression": "",
+            "define": "UNITASK_ADDRESSABLE_SUPPORT"
+        }
+    ],
+    "noEngineReferences": false
+}

+ 7 - 0
Assets/Plugins/UniTask/Runtime/External/Addressables/UniTask.Addressables.asmdef.meta

@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 593a5b492d29ac6448b1ebf7f035ef33
+AssemblyDefinitionImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
Assets/Plugins/UniTask/Runtime/External/DOTween.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 1528053fd3ded1649b737b84b08e4603
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 436 - 0
Assets/Plugins/UniTask/Runtime/External/DOTween/DOTweenAsyncExtensions.cs

@@ -0,0 +1,436 @@
+// asmdef Version Defines, enabled when com.demigiant.dotween is imported.
+
+#if UNITASK_DOTWEEN_SUPPORT
+
+using Cysharp.Threading.Tasks.Internal;
+using DG.Tweening;
+using System;
+using System.Collections.Concurrent;
+using System.Runtime.CompilerServices;
+using System.Threading;
+
+namespace Cysharp.Threading.Tasks
+{
+    public enum TweenCancelBehaviour
+    {
+        Kill,
+        KillWithCompleteCallback,
+        Complete,
+        CompleteWithSequenceCallback,
+        CancelAwait,
+
+        // AndCancelAwait
+        KillAndCancelAwait,
+        KillWithCompleteCallbackAndCancelAwait,
+        CompleteAndCancelAwait,
+        CompleteWithSequenceCallbackAndCancelAwait
+    }
+
+    public static class DOTweenAsyncExtensions
+    {
+        enum CallbackType
+        {
+            Kill,
+            Complete,
+            Pause,
+            Play,
+            Rewind,
+            StepComplete
+        }
+
+        public static TweenAwaiter GetAwaiter(this Tween tween)
+        {
+            return new TweenAwaiter(tween);
+        }
+
+        public static UniTask WithCancellation(this Tween tween, CancellationToken cancellationToken)
+        {
+            Error.ThrowArgumentNullException(tween, nameof(tween));
+
+            if (!tween.IsActive()) return UniTask.CompletedTask;
+            return new UniTask(TweenConfiguredSource.Create(tween, TweenCancelBehaviour.Kill, cancellationToken, CallbackType.Kill, out var token), token);
+        }
+
+        public static UniTask ToUniTask(this Tween tween, TweenCancelBehaviour tweenCancelBehaviour = TweenCancelBehaviour.Kill, CancellationToken cancellationToken = default)
+        {
+            Error.ThrowArgumentNullException(tween, nameof(tween));
+
+            if (!tween.IsActive()) return UniTask.CompletedTask;
+            return new UniTask(TweenConfiguredSource.Create(tween, tweenCancelBehaviour, cancellationToken, CallbackType.Kill, out var token), token);
+        }
+
+        public static UniTask AwaitForComplete(this Tween tween, TweenCancelBehaviour tweenCancelBehaviour = TweenCancelBehaviour.Kill, CancellationToken cancellationToken = default)
+        {
+            Error.ThrowArgumentNullException(tween, nameof(tween));
+
+            if (!tween.IsActive()) return UniTask.CompletedTask;
+            return new UniTask(TweenConfiguredSource.Create(tween, tweenCancelBehaviour, cancellationToken, CallbackType.Complete, out var token), token);
+        }
+
+        public static UniTask AwaitForPause(this Tween tween, TweenCancelBehaviour tweenCancelBehaviour = TweenCancelBehaviour.Kill, CancellationToken cancellationToken = default)
+        {
+            Error.ThrowArgumentNullException(tween, nameof(tween));
+
+            if (!tween.IsActive()) return UniTask.CompletedTask;
+            return new UniTask(TweenConfiguredSource.Create(tween, tweenCancelBehaviour, cancellationToken, CallbackType.Pause, out var token), token);
+        }
+
+        public static UniTask AwaitForPlay(this Tween tween, TweenCancelBehaviour tweenCancelBehaviour = TweenCancelBehaviour.Kill, CancellationToken cancellationToken = default)
+        {
+            Error.ThrowArgumentNullException(tween, nameof(tween));
+
+            if (!tween.IsActive()) return UniTask.CompletedTask;
+            return new UniTask(TweenConfiguredSource.Create(tween, tweenCancelBehaviour, cancellationToken, CallbackType.Play, out var token), token);
+        }
+
+        public static UniTask AwaitForRewind(this Tween tween, TweenCancelBehaviour tweenCancelBehaviour = TweenCancelBehaviour.Kill, CancellationToken cancellationToken = default)
+        {
+            Error.ThrowArgumentNullException(tween, nameof(tween));
+
+            if (!tween.IsActive()) return UniTask.CompletedTask;
+            return new UniTask(TweenConfiguredSource.Create(tween, tweenCancelBehaviour, cancellationToken, CallbackType.Rewind, out var token), token);
+        }
+
+        public static UniTask AwaitForStepComplete(this Tween tween, TweenCancelBehaviour tweenCancelBehaviour = TweenCancelBehaviour.Kill, CancellationToken cancellationToken = default)
+        {
+            Error.ThrowArgumentNullException(tween, nameof(tween));
+
+            if (!tween.IsActive()) return UniTask.CompletedTask;
+            return new UniTask(TweenConfiguredSource.Create(tween, tweenCancelBehaviour, cancellationToken, CallbackType.StepComplete, out var token), token);
+        }
+
+        public struct TweenAwaiter : ICriticalNotifyCompletion
+        {
+            readonly Tween tween;
+
+            // killed(non active) as completed.
+            public bool IsCompleted => !tween.IsActive();
+
+            public TweenAwaiter(Tween tween)
+            {
+                this.tween = tween;
+            }
+
+            public TweenAwaiter GetAwaiter()
+            {
+                return this;
+            }
+
+            public void GetResult()
+            {
+            }
+
+            public void OnCompleted(System.Action continuation)
+            {
+                UnsafeOnCompleted(continuation);
+            }
+
+            public void UnsafeOnCompleted(System.Action continuation)
+            {
+                // onKill is called after OnCompleted, both Complete(false/true) and Kill(false/true).
+                tween.onKill = PooledTweenCallback.Create(continuation);
+            }
+        }
+
+        sealed class TweenConfiguredSource : IUniTaskSource, ITaskPoolNode<TweenConfiguredSource>
+        {
+            static TaskPool<TweenConfiguredSource> pool;
+            TweenConfiguredSource nextNode;
+            public ref TweenConfiguredSource NextNode => ref nextNode;
+
+            static TweenConfiguredSource()
+            {
+                TaskPool.RegisterSizeGetter(typeof(TweenConfiguredSource), () => pool.Size);
+            }
+
+            readonly TweenCallback onCompleteCallbackDelegate;
+
+            Tween tween;
+            TweenCancelBehaviour cancelBehaviour;
+            CancellationToken cancellationToken;
+            CancellationTokenRegistration cancellationRegistration;
+            CallbackType callbackType;
+            bool canceled;
+
+            TweenCallback originalCompleteAction;
+            UniTaskCompletionSourceCore<AsyncUnit> core;
+
+            TweenConfiguredSource()
+            {
+                onCompleteCallbackDelegate = OnCompleteCallbackDelegate;
+            }
+
+            public static IUniTaskSource Create(Tween tween, TweenCancelBehaviour cancelBehaviour, CancellationToken cancellationToken, CallbackType callbackType, out short token)
+            {
+                if (cancellationToken.IsCancellationRequested)
+                {
+                    DoCancelBeforeCreate(tween, cancelBehaviour);
+                    return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token);
+                }
+
+                if (!pool.TryPop(out var result))
+                {
+                    result = new TweenConfiguredSource();
+                }
+
+                result.tween = tween;
+                result.cancelBehaviour = cancelBehaviour;
+                result.cancellationToken = cancellationToken;
+                result.callbackType = callbackType;
+                result.canceled = false;
+
+                switch (callbackType)
+                {
+                    case CallbackType.Kill:
+                        result.originalCompleteAction = tween.onKill;
+                        tween.onKill = result.onCompleteCallbackDelegate;
+                        break;
+                    case CallbackType.Complete:
+                        result.originalCompleteAction = tween.onComplete;
+                        tween.onComplete = result.onCompleteCallbackDelegate;
+                        break;
+                    case CallbackType.Pause:
+                        result.originalCompleteAction = tween.onPause;
+                        tween.onPause = result.onCompleteCallbackDelegate;
+                        break;
+                    case CallbackType.Play:
+                        result.originalCompleteAction = tween.onPlay;
+                        tween.onPlay = result.onCompleteCallbackDelegate;
+                        break;
+                    case CallbackType.Rewind:
+                        result.originalCompleteAction = tween.onRewind;
+                        tween.onRewind = result.onCompleteCallbackDelegate;
+                        break;
+                    case CallbackType.StepComplete:
+                        result.originalCompleteAction = tween.onStepComplete;
+                        tween.onStepComplete = result.onCompleteCallbackDelegate;
+                        break;
+                    default:
+                        break;
+                }
+
+                if (result.originalCompleteAction == result.onCompleteCallbackDelegate)
+                {
+                    result.originalCompleteAction = null;
+                }
+
+                if (cancellationToken.CanBeCanceled)
+                {
+                    result.cancellationRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(x =>
+                    {
+                        var source = (TweenConfiguredSource)x;
+                        switch (source.cancelBehaviour)
+                        {
+                            case TweenCancelBehaviour.Kill:
+                            default:
+                                source.tween.Kill(false);
+                                break;
+                            case TweenCancelBehaviour.KillAndCancelAwait:
+                                source.canceled = true;
+                                source.tween.Kill(false);
+                                break;
+                            case TweenCancelBehaviour.KillWithCompleteCallback:
+                                source.tween.Kill(true);
+                                break;
+                            case TweenCancelBehaviour.KillWithCompleteCallbackAndCancelAwait:
+                                source.canceled = true;
+                                source.tween.Kill(true);
+                                break;
+                            case TweenCancelBehaviour.Complete:
+                                source.tween.Complete(false);
+                                break;
+                            case TweenCancelBehaviour.CompleteAndCancelAwait:
+                                source.canceled = true;
+                                source.tween.Complete(false);
+                                break;
+                            case TweenCancelBehaviour.CompleteWithSequenceCallback:
+                                source.tween.Complete(true);
+                                break;
+                            case TweenCancelBehaviour.CompleteWithSequenceCallbackAndCancelAwait:
+                                source.canceled = true;
+                                source.tween.Complete(true);
+                                break;
+                            case TweenCancelBehaviour.CancelAwait:
+                                source.RestoreOriginalCallback();
+                                source.core.TrySetCanceled(source.cancellationToken);
+                                break;
+                        }
+                    }, result);
+                }
+
+                TaskTracker.TrackActiveTask(result, 3);
+
+                token = result.core.Version;
+                return result;
+            }
+
+            void OnCompleteCallbackDelegate()
+            {
+                if (cancellationToken.IsCancellationRequested)
+                {
+                    if (this.cancelBehaviour == TweenCancelBehaviour.KillAndCancelAwait
+                        || this.cancelBehaviour == TweenCancelBehaviour.KillWithCompleteCallbackAndCancelAwait
+                        || this.cancelBehaviour == TweenCancelBehaviour.CompleteAndCancelAwait
+                        || this.cancelBehaviour == TweenCancelBehaviour.CompleteWithSequenceCallbackAndCancelAwait
+                        || this.cancelBehaviour == TweenCancelBehaviour.CancelAwait)
+                    {
+                        canceled = true;
+                    }
+                }
+                if (canceled)
+                {
+                    core.TrySetCanceled(cancellationToken);
+                }
+                else
+                {
+                    originalCompleteAction?.Invoke();
+                    core.TrySetResult(AsyncUnit.Default);
+                }
+            }
+
+            static void DoCancelBeforeCreate(Tween tween, TweenCancelBehaviour tweenCancelBehaviour)
+            {
+
+                switch (tweenCancelBehaviour)
+                {
+                    case TweenCancelBehaviour.Kill:
+                    default:
+                        tween.Kill(false);
+                        break;
+                    case TweenCancelBehaviour.KillAndCancelAwait:
+                        tween.Kill(false);
+                        break;
+                    case TweenCancelBehaviour.KillWithCompleteCallback:
+                        tween.Kill(true);
+                        break;
+                    case TweenCancelBehaviour.KillWithCompleteCallbackAndCancelAwait:
+                        tween.Kill(true);
+                        break;
+                    case TweenCancelBehaviour.Complete:
+                        tween.Complete(false);
+                        break;
+                    case TweenCancelBehaviour.CompleteAndCancelAwait:
+                        tween.Complete(false);
+                        break;
+                    case TweenCancelBehaviour.CompleteWithSequenceCallback:
+                        tween.Complete(true);
+                        break;
+                    case TweenCancelBehaviour.CompleteWithSequenceCallbackAndCancelAwait:
+                        tween.Complete(true);
+                        break;
+                    case TweenCancelBehaviour.CancelAwait:
+                        break;
+                }
+            }
+
+            public void GetResult(short token)
+            {
+                try
+                {
+                    core.GetResult(token);
+                }
+                finally
+                {
+                    TryReturn();
+                }
+            }
+
+            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);
+            }
+
+            bool TryReturn()
+            {
+                TaskTracker.RemoveTracking(this);
+                core.Reset();
+                cancellationRegistration.Dispose();
+
+                RestoreOriginalCallback();
+
+                tween = default;
+                cancellationToken = default;
+                originalCompleteAction = default;
+                return pool.TryPush(this);
+            }
+
+            void RestoreOriginalCallback()
+            {
+                switch (callbackType)
+                {
+                    case CallbackType.Kill:
+                        tween.onKill = originalCompleteAction;
+                        break;
+                    case CallbackType.Complete:
+                        tween.onComplete = originalCompleteAction;
+                        break;
+                    case CallbackType.Pause:
+                        tween.onPause = originalCompleteAction;
+                        break;
+                    case CallbackType.Play:
+                        tween.onPlay = originalCompleteAction;
+                        break;
+                    case CallbackType.Rewind:
+                        tween.onRewind = originalCompleteAction;
+                        break;
+                    case CallbackType.StepComplete:
+                        tween.onStepComplete = originalCompleteAction;
+                        break;
+                    default:
+                        break;
+                }
+            }
+        }
+    }
+
+    sealed class PooledTweenCallback
+    {
+        static readonly ConcurrentQueue<PooledTweenCallback> pool = new ConcurrentQueue<PooledTweenCallback>();
+
+        readonly TweenCallback runDelegate;
+
+        Action continuation;
+
+
+        PooledTweenCallback()
+        {
+            runDelegate = Run;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static TweenCallback Create(Action continuation)
+        {
+            if (!pool.TryDequeue(out var item))
+            {
+                item = new PooledTweenCallback();
+            }
+
+            item.continuation = continuation;
+            return item.runDelegate;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        void Run()
+        {
+            var call = continuation;
+            continuation = null;
+            if (call != null)
+            {
+                pool.Enqueue(this);
+                call.Invoke();
+            }
+        }
+    }
+}
+
+#endif

+ 11 - 0
Assets/Plugins/UniTask/Runtime/External/DOTween/DOTweenAsyncExtensions.cs.meta

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

+ 22 - 0
Assets/Plugins/UniTask/Runtime/External/DOTween/UniTask.DOTween.asmdef

@@ -0,0 +1,22 @@
+{
+    "name": "UniTask.DOTween",
+    "references": [
+        "UniTask",
+        "DOTween.Modules"
+    ],
+    "includePlatforms": [],
+    "excludePlatforms": [],
+    "allowUnsafeCode": false,
+    "overrideReferences": false,
+    "precompiledReferences": [],
+    "autoReferenced": true,
+    "defineConstraints": [],
+    "versionDefines": [
+        {
+            "name": "com.demigiant.dotween",
+            "expression": "",
+            "define": "UNITASK_DOTWEEN_SUPPORT"
+        }
+    ],
+    "noEngineReferences": false
+}

+ 7 - 0
Assets/Plugins/UniTask/Runtime/External/DOTween/UniTask.DOTween.asmdef.meta

@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 029c1c1b674aaae47a6841a0b89ad80e
+AssemblyDefinitionImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 8 - 0
Assets/Plugins/UniTask/Runtime/External/TextMeshPro.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 15a377bb93d68c345bb70cf0eed60674
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 224 - 0
Assets/Plugins/UniTask/Runtime/External/TextMeshPro/TextMeshProAsyncExtensions.InputField.cs

@@ -0,0 +1,224 @@
+#if UNITASK_TEXTMESHPRO_SUPPORT
+
+using System;
+using System.Threading;
+using TMPro;
+
+namespace Cysharp.Threading.Tasks
+{
+    public static partial class TextMeshProAsyncExtensions
+    {
+        public static IAsyncValueChangedEventHandler<string> GetAsyncValueChangedEventHandler(this TMP_InputField inputField)
+        {
+            return new AsyncUnityEventHandler<string>(inputField.onValueChanged, inputField.GetCancellationTokenOnDestroy(), false);
+        }
+
+        public static IAsyncValueChangedEventHandler<string> GetAsyncValueChangedEventHandler(this TMP_InputField inputField, CancellationToken cancellationToken)
+        {
+            return new AsyncUnityEventHandler<string>(inputField.onValueChanged, cancellationToken, false);
+        }
+
+        public static UniTask<string> OnValueChangedAsync(this TMP_InputField inputField)
+        {
+            return new AsyncUnityEventHandler<string>(inputField.onValueChanged, inputField.GetCancellationTokenOnDestroy(), true).OnInvokeAsync();
+        }
+
+        public static UniTask<string> OnValueChangedAsync(this TMP_InputField inputField, CancellationToken cancellationToken)
+        {
+            return new AsyncUnityEventHandler<string>(inputField.onValueChanged, cancellationToken, true).OnInvokeAsync();
+        }
+
+        public static IUniTaskAsyncEnumerable<string> OnValueChangedAsAsyncEnumerable(this TMP_InputField inputField)
+        {
+            return new UnityEventHandlerAsyncEnumerable<string>(inputField.onValueChanged, inputField.GetCancellationTokenOnDestroy());
+        }
+
+        public static IUniTaskAsyncEnumerable<string> OnValueChangedAsAsyncEnumerable(this TMP_InputField inputField, CancellationToken cancellationToken)
+        {
+            return new UnityEventHandlerAsyncEnumerable<string>(inputField.onValueChanged, cancellationToken);
+        }
+
+        public static IAsyncEndEditEventHandler<string> GetAsyncEndEditEventHandler(this TMP_InputField inputField)
+        {
+            return new AsyncUnityEventHandler<string>(inputField.onEndEdit, inputField.GetCancellationTokenOnDestroy(), false);
+        }
+
+        public static IAsyncEndEditEventHandler<string> GetAsyncEndEditEventHandler(this TMP_InputField inputField, CancellationToken cancellationToken)
+        {
+            return new AsyncUnityEventHandler<string>(inputField.onEndEdit, cancellationToken, false);
+        }
+
+        public static UniTask<string> OnEndEditAsync(this TMP_InputField inputField)
+        {
+            return new AsyncUnityEventHandler<string>(inputField.onEndEdit, inputField.GetCancellationTokenOnDestroy(), true).OnInvokeAsync();
+        }
+
+        public static UniTask<string> OnEndEditAsync(this TMP_InputField inputField, CancellationToken cancellationToken)
+        {
+            return new AsyncUnityEventHandler<string>(inputField.onEndEdit, cancellationToken, true).OnInvokeAsync();
+        }
+
+        public static IUniTaskAsyncEnumerable<string> OnEndEditAsAsyncEnumerable(this TMP_InputField inputField)
+        {
+            return new UnityEventHandlerAsyncEnumerable<string>(inputField.onEndEdit, inputField.GetCancellationTokenOnDestroy());
+        }
+
+        public static IUniTaskAsyncEnumerable<string> OnEndEditAsAsyncEnumerable(this TMP_InputField inputField, CancellationToken cancellationToken)
+        {
+            return new UnityEventHandlerAsyncEnumerable<string>(inputField.onEndEdit, cancellationToken);
+        }
+
+        public static IAsyncEndTextSelectionEventHandler<(string, int, int)> GetAsyncEndTextSelectionEventHandler(this TMP_InputField inputField)
+        {
+            return new AsyncUnityEventHandler<(string, int, int)>(new TextSelectionEventConverter(inputField.onEndTextSelection), inputField.GetCancellationTokenOnDestroy(), false);
+        }
+
+        public static IAsyncEndTextSelectionEventHandler<(string, int, int)> GetAsyncEndTextSelectionEventHandler(this TMP_InputField inputField, CancellationToken cancellationToken)
+        {
+            return new AsyncUnityEventHandler<(string, int, int)>(new TextSelectionEventConverter(inputField.onEndTextSelection), cancellationToken, false);
+        }
+
+        public static UniTask<(string, int, int)> OnEndTextSelectionAsync(this TMP_InputField inputField)
+        {
+            return new AsyncUnityEventHandler<(string, int, int)>(new TextSelectionEventConverter(inputField.onEndTextSelection), inputField.GetCancellationTokenOnDestroy(), true).OnInvokeAsync();
+        }
+
+        public static UniTask<(string, int, int)> OnEndTextSelectionAsync(this TMP_InputField inputField, CancellationToken cancellationToken)
+        {
+            return new AsyncUnityEventHandler<(string, int, int)>(new TextSelectionEventConverter(inputField.onEndTextSelection), cancellationToken, true).OnInvokeAsync();
+        }
+
+        public static IUniTaskAsyncEnumerable<(string, int, int)> OnEndTextSelectionAsAsyncEnumerable(this TMP_InputField inputField)
+        {
+            return new UnityEventHandlerAsyncEnumerable<(string, int, int)>(new TextSelectionEventConverter(inputField.onEndTextSelection), inputField.GetCancellationTokenOnDestroy());
+        }
+
+        public static IUniTaskAsyncEnumerable<(string, int, int)> OnEndTextSelectionAsAsyncEnumerable(this TMP_InputField inputField, CancellationToken cancellationToken)
+        {
+            return new UnityEventHandlerAsyncEnumerable<(string, int, int)>(new TextSelectionEventConverter(inputField.onEndTextSelection), cancellationToken);
+        }
+
+        public static IAsyncTextSelectionEventHandler<(string, int, int)> GetAsyncTextSelectionEventHandler(this TMP_InputField inputField)
+        {
+            return new AsyncUnityEventHandler<(string, int, int)>(new TextSelectionEventConverter(inputField.onTextSelection), inputField.GetCancellationTokenOnDestroy(), false);
+        }
+
+        public static IAsyncTextSelectionEventHandler<(string, int, int)> GetAsyncTextSelectionEventHandler(this TMP_InputField inputField, CancellationToken cancellationToken)
+        {
+            return new AsyncUnityEventHandler<(string, int, int)>(new TextSelectionEventConverter(inputField.onTextSelection), cancellationToken, false);
+        }
+
+        public static UniTask<(string, int, int)> OnTextSelectionAsync(this TMP_InputField inputField)
+        {
+            return new AsyncUnityEventHandler<(string, int, int)>(new TextSelectionEventConverter(inputField.onTextSelection), inputField.GetCancellationTokenOnDestroy(), true).OnInvokeAsync();
+        }
+
+        public static UniTask<(string, int, int)> OnTextSelectionAsync(this TMP_InputField inputField, CancellationToken cancellationToken)
+        {
+            return new AsyncUnityEventHandler<(string, int, int)>(new TextSelectionEventConverter(inputField.onTextSelection), cancellationToken, true).OnInvokeAsync();
+        }
+
+        public static IUniTaskAsyncEnumerable<(string, int, int)> OnTextSelectionAsAsyncEnumerable(this TMP_InputField inputField)
+        {
+            return new UnityEventHandlerAsyncEnumerable<(string, int, int)>(new TextSelectionEventConverter(inputField.onTextSelection), inputField.GetCancellationTokenOnDestroy());
+        }
+
+        public static IUniTaskAsyncEnumerable<(string, int, int)> OnTextSelectionAsAsyncEnumerable(this TMP_InputField inputField, CancellationToken cancellationToken)
+        {
+            return new UnityEventHandlerAsyncEnumerable<(string, int, int)>(new TextSelectionEventConverter(inputField.onTextSelection), cancellationToken);
+        }
+
+        public static IAsyncDeselectEventHandler<string> GetAsyncDeselectEventHandler(this TMP_InputField inputField)
+        {
+            return new AsyncUnityEventHandler<string>(inputField.onDeselect, inputField.GetCancellationTokenOnDestroy(), false);
+        }
+
+        public static IAsyncDeselectEventHandler<string> GetAsyncDeselectEventHandler(this TMP_InputField inputField, CancellationToken cancellationToken)
+        {
+            return new AsyncUnityEventHandler<string>(inputField.onDeselect, cancellationToken, false);
+        }
+
+        public static UniTask<string> OnDeselectAsync(this TMP_InputField inputField)
+        {
+            return new AsyncUnityEventHandler<string>(inputField.onDeselect, inputField.GetCancellationTokenOnDestroy(), true).OnInvokeAsync();
+        }
+
+        public static UniTask<string> OnDeselectAsync(this TMP_InputField inputField, CancellationToken cancellationToken)
+        {
+            return new AsyncUnityEventHandler<string>(inputField.onDeselect, cancellationToken, true).OnInvokeAsync();
+        }
+
+        public static IUniTaskAsyncEnumerable<string> OnDeselectAsAsyncEnumerable(this TMP_InputField inputField)
+        {
+            return new UnityEventHandlerAsyncEnumerable<string>(inputField.onDeselect, inputField.GetCancellationTokenOnDestroy());
+        }
+
+        public static IUniTaskAsyncEnumerable<string> OnDeselectAsAsyncEnumerable(this TMP_InputField inputField, CancellationToken cancellationToken)
+        {
+            return new UnityEventHandlerAsyncEnumerable<string>(inputField.onDeselect, cancellationToken);
+        }
+
+        public static IAsyncSelectEventHandler<string> GetAsyncSelectEventHandler(this TMP_InputField inputField)
+        {
+            return new AsyncUnityEventHandler<string>(inputField.onSelect, inputField.GetCancellationTokenOnDestroy(), false);
+        }
+
+        public static IAsyncSelectEventHandler<string> GetAsyncSelectEventHandler(this TMP_InputField inputField, CancellationToken cancellationToken)
+        {
+            return new AsyncUnityEventHandler<string>(inputField.onSelect, cancellationToken, false);
+        }
+
+        public static UniTask<string> OnSelectAsync(this TMP_InputField inputField)
+        {
+            return new AsyncUnityEventHandler<string>(inputField.onSelect, inputField.GetCancellationTokenOnDestroy(), true).OnInvokeAsync();
+        }
+
+        public static UniTask<string> OnSelectAsync(this TMP_InputField inputField, CancellationToken cancellationToken)
+        {
+            return new AsyncUnityEventHandler<string>(inputField.onSelect, cancellationToken, true).OnInvokeAsync();
+        }
+
+        public static IUniTaskAsyncEnumerable<string> OnSelectAsAsyncEnumerable(this TMP_InputField inputField)
+        {
+            return new UnityEventHandlerAsyncEnumerable<string>(inputField.onSelect, inputField.GetCancellationTokenOnDestroy());
+        }
+
+        public static IUniTaskAsyncEnumerable<string> OnSelectAsAsyncEnumerable(this TMP_InputField inputField, CancellationToken cancellationToken)
+        {
+            return new UnityEventHandlerAsyncEnumerable<string>(inputField.onSelect, cancellationToken);
+        }
+
+        public static IAsyncSubmitEventHandler<string> GetAsyncSubmitEventHandler(this TMP_InputField inputField)
+        {
+            return new AsyncUnityEventHandler<string>(inputField.onSubmit, inputField.GetCancellationTokenOnDestroy(), false);
+        }
+
+        public static IAsyncSubmitEventHandler<string> GetAsyncSubmitEventHandler(this TMP_InputField inputField, CancellationToken cancellationToken)
+        {
+            return new AsyncUnityEventHandler<string>(inputField.onSubmit, cancellationToken, false);
+        }
+
+        public static UniTask<string> OnSubmitAsync(this TMP_InputField inputField)
+        {
+            return new AsyncUnityEventHandler<string>(inputField.onSubmit, inputField.GetCancellationTokenOnDestroy(), true).OnInvokeAsync();
+        }
+
+        public static UniTask<string> OnSubmitAsync(this TMP_InputField inputField, CancellationToken cancellationToken)
+        {
+            return new AsyncUnityEventHandler<string>(inputField.onSubmit, cancellationToken, true).OnInvokeAsync();
+        }
+
+        public static IUniTaskAsyncEnumerable<string> OnSubmitAsAsyncEnumerable(this TMP_InputField inputField)
+        {
+            return new UnityEventHandlerAsyncEnumerable<string>(inputField.onSubmit, inputField.GetCancellationTokenOnDestroy());
+        }
+
+        public static IUniTaskAsyncEnumerable<string> OnSubmitAsAsyncEnumerable(this TMP_InputField inputField, CancellationToken cancellationToken)
+        {
+            return new UnityEventHandlerAsyncEnumerable<string>(inputField.onSubmit, cancellationToken);
+        }
+
+    }
+}
+
+#endif

+ 11 - 0
Assets/Plugins/UniTask/Runtime/External/TextMeshPro/TextMeshProAsyncExtensions.InputField.cs.meta

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

+ 130 - 0
Assets/Plugins/UniTask/Runtime/External/TextMeshPro/TextMeshProAsyncExtensions.cs

@@ -0,0 +1,130 @@
+#if UNITASK_TEXTMESHPRO_SUPPORT
+
+using System;
+using System.Threading;
+using TMPro;
+using UnityEngine.Events;
+
+namespace Cysharp.Threading.Tasks
+{
+    public static partial class TextMeshProAsyncExtensions
+    {
+        // <string> -> Text
+        public static void BindTo(this IUniTaskAsyncEnumerable<string> source, TMP_Text text, bool rebindOnError = true)
+        {
+            BindToCore(source, text, text.GetCancellationTokenOnDestroy(), rebindOnError).Forget();
+        }
+
+        public static void BindTo(this IUniTaskAsyncEnumerable<string> source, TMP_Text text, CancellationToken cancellationToken, bool rebindOnError = true)
+        {
+            BindToCore(source, text, cancellationToken, rebindOnError).Forget();
+        }
+
+        static async UniTaskVoid BindToCore(IUniTaskAsyncEnumerable<string> source, TMP_Text text, CancellationToken cancellationToken, bool rebindOnError)
+        {
+            var repeat = false;
+            BIND_AGAIN:
+            var e = source.GetAsyncEnumerator(cancellationToken);
+            try
+            {
+                while (true)
+                {
+                    bool moveNext;
+                    try
+                    {
+                        moveNext = await e.MoveNextAsync();
+                        repeat = false;
+                    }
+                    catch (Exception ex)
+                    {
+                        if (ex is OperationCanceledException) return;
+
+                        if (rebindOnError && !repeat)
+                        {
+                            repeat = true;
+                            goto BIND_AGAIN;
+                        }
+                        else
+                        {
+                            throw;
+                        }
+                    }
+
+                    if (!moveNext) return;
+
+                    text.text = e.Current;
+                }
+            }
+            finally
+            {
+                if (e != null)
+                {
+                    await e.DisposeAsync();
+                }
+            }
+        }
+
+        // <T> -> Text
+
+        public static void BindTo<T>(this IUniTaskAsyncEnumerable<T> source, TMP_Text text, bool rebindOnError = true)
+        {
+            BindToCore(source, text, text.GetCancellationTokenOnDestroy(), rebindOnError).Forget();
+        }
+
+        public static void BindTo<T>(this IUniTaskAsyncEnumerable<T> source, TMP_Text text, CancellationToken cancellationToken, bool rebindOnError = true)
+        {
+            BindToCore(source, text, cancellationToken, rebindOnError).Forget();
+        }
+
+        public static void BindTo<T>(this AsyncReactiveProperty<T> source, TMP_Text text, bool rebindOnError = true)
+        {
+            BindToCore(source, text, text.GetCancellationTokenOnDestroy(), rebindOnError).Forget();
+        }
+
+        static async UniTaskVoid BindToCore<T>(IUniTaskAsyncEnumerable<T> source, TMP_Text text, CancellationToken cancellationToken, bool rebindOnError)
+        {
+            var repeat = false;
+            BIND_AGAIN:
+            var e = source.GetAsyncEnumerator(cancellationToken);
+            try
+            {
+                while (true)
+                {
+                    bool moveNext;
+                    try
+                    {
+                        moveNext = await e.MoveNextAsync();
+                        repeat = false;
+                    }
+                    catch (Exception ex)
+                    {
+                        if (ex is OperationCanceledException) return;
+
+                        if (rebindOnError && !repeat)
+                        {
+                            repeat = true;
+                            goto BIND_AGAIN;
+                        }
+                        else
+                        {
+                            throw;
+                        }
+                    }
+
+                    if (!moveNext) return;
+
+                    text.text = e.Current.ToString();
+                }
+            }
+            finally
+            {
+                if (e != null)
+                {
+                    await e.DisposeAsync();
+                }
+            }
+        }
+    }
+}
+
+#endif

+ 11 - 0
Assets/Plugins/UniTask/Runtime/External/TextMeshPro/TextMeshProAsyncExtensions.cs.meta

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

+ 27 - 0
Assets/Plugins/UniTask/Runtime/External/TextMeshPro/UniTask.TextMeshPro.asmdef

@@ -0,0 +1,27 @@
+{
+    "name": "UniTask.TextMeshPro",
+    "references": [
+        "UniTask",
+        "Unity.TextMeshPro"
+    ],
+    "includePlatforms": [],
+    "excludePlatforms": [],
+    "allowUnsafeCode": false,
+    "overrideReferences": false,
+    "precompiledReferences": [],
+    "autoReferenced": true,
+    "defineConstraints": [],
+    "versionDefines": [
+        {
+            "name": "com.unity.textmeshpro",
+            "expression": "",
+            "define": "UNITASK_TEXTMESHPRO_SUPPORT"
+        },
+        {
+            "name": "com.unity.ugui",
+            "expression": "2.0.0",
+            "define": "UNITASK_TEXTMESHPRO_SUPPORT"
+        }
+    ],
+    "noEngineReferences": false
+}

+ 7 - 0
Assets/Plugins/UniTask/Runtime/External/TextMeshPro/UniTask.TextMeshPro.asmdef.meta

@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: dc47925d1a5fa2946bdd37746b2b5d48
+AssemblyDefinitionImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 91 - 0
Assets/Plugins/UniTask/Runtime/IUniTaskAsyncEnumerable.cs

@@ -0,0 +1,91 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Threading;
+
+namespace Cysharp.Threading.Tasks
+{
+    public interface IUniTaskAsyncEnumerable<out T>
+    {
+        IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default);
+    }
+
+    public interface IUniTaskAsyncEnumerator<out T> : IUniTaskAsyncDisposable
+    {
+        T Current { get; }
+        UniTask<bool> MoveNextAsync();
+    }
+
+    public interface IUniTaskAsyncDisposable
+    {
+        UniTask DisposeAsync();
+    }
+
+    public interface IUniTaskOrderedAsyncEnumerable<TElement> : IUniTaskAsyncEnumerable<TElement>
+    {
+        IUniTaskOrderedAsyncEnumerable<TElement> CreateOrderedEnumerable<TKey>(Func<TElement, TKey> keySelector, IComparer<TKey> comparer, bool descending);
+        IUniTaskOrderedAsyncEnumerable<TElement> CreateOrderedEnumerable<TKey>(Func<TElement, UniTask<TKey>> keySelector, IComparer<TKey> comparer, bool descending);
+        IUniTaskOrderedAsyncEnumerable<TElement> CreateOrderedEnumerable<TKey>(Func<TElement, CancellationToken, UniTask<TKey>> keySelector, IComparer<TKey> comparer, bool descending);
+    }
+
+    public interface IConnectableUniTaskAsyncEnumerable<out T> : IUniTaskAsyncEnumerable<T>
+    {
+        IDisposable Connect();
+    }
+
+    // don't use AsyncGrouping.
+    //public interface IUniTaskAsyncGrouping<out TKey, out TElement> : IUniTaskAsyncEnumerable<TElement>
+    //{
+    //    TKey Key { get; }
+    //}
+
+    public static class UniTaskAsyncEnumerableExtensions
+    {
+        public static UniTaskCancelableAsyncEnumerable<T> WithCancellation<T>(this IUniTaskAsyncEnumerable<T> source, CancellationToken cancellationToken)
+        {
+            return new UniTaskCancelableAsyncEnumerable<T>(source, cancellationToken);
+        }
+    }
+
+    [StructLayout(LayoutKind.Auto)]
+    public readonly struct UniTaskCancelableAsyncEnumerable<T>
+    {
+        private readonly IUniTaskAsyncEnumerable<T> enumerable;
+        private readonly CancellationToken cancellationToken;
+
+        internal UniTaskCancelableAsyncEnumerable(IUniTaskAsyncEnumerable<T> enumerable, CancellationToken cancellationToken)
+        {
+            this.enumerable = enumerable;
+            this.cancellationToken = cancellationToken;
+        }
+
+        public Enumerator GetAsyncEnumerator()
+        {
+            return new Enumerator(enumerable.GetAsyncEnumerator(cancellationToken));
+        }
+
+        [StructLayout(LayoutKind.Auto)]
+        public readonly struct Enumerator
+        {
+            private readonly IUniTaskAsyncEnumerator<T> enumerator;
+
+            internal Enumerator(IUniTaskAsyncEnumerator<T> enumerator)
+            {
+                this.enumerator = enumerator;
+            }
+
+            public T Current => enumerator.Current;
+
+            public UniTask<bool> MoveNextAsync()
+            {
+                return enumerator.MoveNextAsync();
+            }
+
+
+            public UniTask DisposeAsync()
+            {
+                return enumerator.DisposeAsync();
+            }
+        }
+    }
+}

+ 11 - 0
Assets/Plugins/UniTask/Runtime/IUniTaskAsyncEnumerable.cs.meta

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

+ 127 - 0
Assets/Plugins/UniTask/Runtime/IUniTaskSource.cs

@@ -0,0 +1,127 @@
+#pragma warning disable CS1591
+#pragma warning disable CS0108
+
+#if (UNITASK_NETCORE && !NETSTANDARD2_0) || UNITY_2022_3_OR_NEWER
+#define SUPPORT_VALUETASK
+#endif
+
+using System;
+using System.Runtime.CompilerServices;
+
+namespace Cysharp.Threading.Tasks
+{
+    public enum UniTaskStatus
+    {
+        /// <summary>The operation has not yet completed.</summary>
+        Pending = 0,
+        /// <summary>The operation completed successfully.</summary>
+        Succeeded = 1,
+        /// <summary>The operation completed with an error.</summary>
+        Faulted = 2,
+        /// <summary>The operation completed due to cancellation.</summary>
+        Canceled = 3
+    }
+
+    // similar as IValueTaskSource
+    public interface IUniTaskSource
+#if SUPPORT_VALUETASK
+        : System.Threading.Tasks.Sources.IValueTaskSource
+#endif
+    {
+        UniTaskStatus GetStatus(short token);
+        void OnCompleted(Action<object> continuation, object state, short token);
+        void GetResult(short token);
+
+        UniTaskStatus UnsafeGetStatus(); // only for debug use.
+
+#if SUPPORT_VALUETASK
+
+        System.Threading.Tasks.Sources.ValueTaskSourceStatus System.Threading.Tasks.Sources.IValueTaskSource.GetStatus(short token)
+        {
+            return (System.Threading.Tasks.Sources.ValueTaskSourceStatus)(int)((IUniTaskSource)this).GetStatus(token);
+        }
+
+        void System.Threading.Tasks.Sources.IValueTaskSource.GetResult(short token)
+        {
+            ((IUniTaskSource)this).GetResult(token);
+        }
+
+        void System.Threading.Tasks.Sources.IValueTaskSource.OnCompleted(Action<object> continuation, object state, short token, System.Threading.Tasks.Sources.ValueTaskSourceOnCompletedFlags flags)
+        {
+            // ignore flags, always none.
+            ((IUniTaskSource)this).OnCompleted(continuation, state, token);
+        }
+
+#endif
+    }
+
+    public interface IUniTaskSource<out T> : IUniTaskSource
+#if SUPPORT_VALUETASK
+        , System.Threading.Tasks.Sources.IValueTaskSource<T>
+#endif
+    {
+        new T GetResult(short token);
+
+#if SUPPORT_VALUETASK
+
+        new public UniTaskStatus GetStatus(short token)
+        {
+            return ((IUniTaskSource)this).GetStatus(token);
+        }
+
+        new public void OnCompleted(Action<object> continuation, object state, short token)
+        {
+            ((IUniTaskSource)this).OnCompleted(continuation, state, token);
+        }
+
+        System.Threading.Tasks.Sources.ValueTaskSourceStatus System.Threading.Tasks.Sources.IValueTaskSource<T>.GetStatus(short token)
+        {
+            return (System.Threading.Tasks.Sources.ValueTaskSourceStatus)(int)((IUniTaskSource)this).GetStatus(token);
+        }
+
+        T System.Threading.Tasks.Sources.IValueTaskSource<T>.GetResult(short token)
+        {
+            return ((IUniTaskSource<T>)this).GetResult(token);
+        }
+
+        void System.Threading.Tasks.Sources.IValueTaskSource<T>.OnCompleted(Action<object> continuation, object state, short token, System.Threading.Tasks.Sources.ValueTaskSourceOnCompletedFlags flags)
+        {
+            // ignore flags, always none.
+            ((IUniTaskSource)this).OnCompleted(continuation, state, token);
+        }
+
+#endif
+    }
+
+    public static class UniTaskStatusExtensions
+    {
+        /// <summary>status != Pending.</summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static bool IsCompleted(this UniTaskStatus status)
+        {
+            return status != UniTaskStatus.Pending;
+        }
+
+        /// <summary>status == Succeeded.</summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static bool IsCompletedSuccessfully(this UniTaskStatus status)
+        {
+            return status == UniTaskStatus.Succeeded;
+        }
+
+        /// <summary>status == Canceled.</summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static bool IsCanceled(this UniTaskStatus status)
+        {
+            return status == UniTaskStatus.Canceled;
+        }
+
+        /// <summary>status == Faulted.</summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static bool IsFaulted(this UniTaskStatus status)
+        {
+            return status == UniTaskStatus.Faulted;
+        }
+    }
+}
+

+ 11 - 0
Assets/Plugins/UniTask/Runtime/IUniTaskSource.cs.meta

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

+ 8 - 0
Assets/Plugins/UniTask/Runtime/Internal.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: a12a6d190fc3eaf49a421f46a032a3b2
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 150 - 0
Assets/Plugins/UniTask/Runtime/Internal/ArrayPool.cs

@@ -0,0 +1,150 @@
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+
+using System;
+using System.Threading;
+
+namespace Cysharp.Threading.Tasks.Internal
+{
+    // Same interface as System.Buffers.ArrayPool<T> but only provides Shared.
+
+    internal sealed class ArrayPool<T>
+    {
+        // Same size as System.Buffers.DefaultArrayPool<T>
+        const int DefaultMaxNumberOfArraysPerBucket = 50;
+
+        static readonly T[] EmptyArray = new T[0];
+
+        public static readonly ArrayPool<T> Shared = new ArrayPool<T>();
+
+        readonly MinimumQueue<T[]>[] buckets;
+        readonly SpinLock[] locks;
+
+        ArrayPool()
+        {
+            // see: GetQueueIndex
+            buckets = new MinimumQueue<T[]>[18];
+            locks = new SpinLock[18];
+            for (int i = 0; i < buckets.Length; i++)
+            {
+                buckets[i] = new MinimumQueue<T[]>(4);
+                locks[i] = new SpinLock(false);
+            }
+        }
+
+        public T[] Rent(int minimumLength)
+        {
+            if (minimumLength < 0)
+            {
+                throw new ArgumentOutOfRangeException("minimumLength");
+            }
+            else if (minimumLength == 0)
+            {
+                return EmptyArray;
+            }
+
+            var size = CalculateSize(minimumLength);
+            var index = GetQueueIndex(size);
+            if (index != -1)
+            {
+                var q = buckets[index];
+                var lockTaken = false;
+                try
+                {
+                    locks[index].Enter(ref lockTaken);
+
+                    if (q.Count != 0)
+                    {
+                        return q.Dequeue();
+                    }
+                }
+                finally
+                {
+                    if (lockTaken) locks[index].Exit(false);
+                }
+            }
+
+            return new T[size];
+        }
+
+        public void Return(T[] array, bool clearArray = false)
+        {
+            if (array == null || array.Length == 0)
+            {
+                return;
+            }
+
+            var index = GetQueueIndex(array.Length);
+            if (index != -1)
+            {
+                if (clearArray)
+                {
+                    Array.Clear(array, 0, array.Length);
+                }
+
+                var q = buckets[index];
+                var lockTaken = false;
+
+                try
+                {
+                    locks[index].Enter(ref lockTaken);
+
+                    if (q.Count > DefaultMaxNumberOfArraysPerBucket)
+                    {
+                        return;
+                    }
+
+                    q.Enqueue(array);
+                }
+                finally
+                {
+                    if (lockTaken) locks[index].Exit(false);
+                }
+            }
+        }
+
+        static int CalculateSize(int size)
+        {
+            size--;
+            size |= size >> 1;
+            size |= size >> 2;
+            size |= size >> 4;
+            size |= size >> 8;
+            size |= size >> 16;
+            size += 1;
+
+            if (size < 8)
+            {
+                size = 8;
+            }
+
+            return size;
+        }
+
+        static int GetQueueIndex(int size)
+        {
+            switch (size)
+            {
+                case 8: return 0;
+                case 16: return 1;
+                case 32: return 2;
+                case 64: return 3;
+                case 128: return 4;
+                case 256: return 5;
+                case 512: return 6;
+                case 1024: return 7;
+                case 2048: return 8;
+                case 4096: return 9;
+                case 8192: return 10;
+                case 16384: return 11;
+                case 32768: return 12;
+                case 65536: return 13;
+                case 131072: return 14;
+                case 262144: return 15;
+                case 524288: return 16;
+                case 1048576: return 17; // max array length
+                default:
+                    return -1;
+            }
+        }
+    }
+}

+ 12 - 0
Assets/Plugins/UniTask/Runtime/Internal/ArrayPool.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: f83ebad81fb89fb4882331616ca6d248
+timeCreated: 1532361008
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 115 - 0
Assets/Plugins/UniTask/Runtime/Internal/ArrayPoolUtil.cs

@@ -0,0 +1,115 @@
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+
+namespace Cysharp.Threading.Tasks.Internal
+{
+    internal static class ArrayPoolUtil
+    {
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        internal static void EnsureCapacity<T>(ref T[] array, int index, ArrayPool<T> pool)
+        {
+            if (array.Length <= index)
+            {
+                EnsureCapacityCore(ref array, index, pool);
+            }
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        static void EnsureCapacityCore<T>(ref T[] array, int index, ArrayPool<T> pool)
+        {
+            if (array.Length <= index)
+            {
+                var newSize = array.Length * 2;
+                var newArray = pool.Rent((index < newSize) ? newSize : (index * 2));
+                Array.Copy(array, 0, newArray, 0, array.Length);
+
+                pool.Return(array, clearArray: !RuntimeHelpersAbstraction.IsWellKnownNoReferenceContainsType<T>());
+
+                array = newArray;
+            }
+        }
+
+        public static RentArray<T> Materialize<T>(IEnumerable<T> source)
+        {
+            if (source is T[] array)
+            {
+                return new RentArray<T>(array, array.Length, null);
+            }
+
+            var defaultCount = 32;
+            if (source is ICollection<T> coll)
+            {
+                if (coll.Count == 0)
+                {
+                    return new RentArray<T>(Array.Empty<T>(), 0, null);
+                }
+
+                defaultCount = coll.Count;
+                var pool = ArrayPool<T>.Shared;
+                var buffer = pool.Rent(defaultCount);
+                coll.CopyTo(buffer, 0);
+                return new RentArray<T>(buffer, coll.Count, pool);
+            }
+            else if (source is IReadOnlyCollection<T> rcoll)
+            {
+                defaultCount = rcoll.Count;
+            }
+
+            if (defaultCount == 0)
+            {
+                return new RentArray<T>(Array.Empty<T>(), 0, null);
+            }
+
+            {
+                var pool = ArrayPool<T>.Shared;
+
+                var index = 0;
+                var buffer = pool.Rent(defaultCount);
+                foreach (var item in source)
+                {
+                    EnsureCapacity(ref buffer, index, pool);
+                    buffer[index++] = item;
+                }
+
+                return new RentArray<T>(buffer, index, pool);
+            }
+        }
+
+        public struct RentArray<T> : IDisposable
+        {
+            public readonly T[] Array;
+            public readonly int Length;
+            ArrayPool<T> pool;
+
+            public RentArray(T[] array, int length, ArrayPool<T> pool)
+            {
+                this.Array = array;
+                this.Length = length;
+                this.pool = pool;
+            }
+
+            public void Dispose()
+            {
+                DisposeManually(!RuntimeHelpersAbstraction.IsWellKnownNoReferenceContainsType<T>());
+            }
+
+            public void DisposeManually(bool clearArray)
+            {
+                if (pool != null)
+                {
+                    if (clearArray)
+                    {
+                        System.Array.Clear(Array, 0, Length);
+                    }
+
+                    pool.Return(Array, clearArray: false);
+                    pool = null;
+                }
+            }
+        }
+    }
+}
+

+ 12 - 0
Assets/Plugins/UniTask/Runtime/Internal/ArrayPoolUtil.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 424cc208fb61d4e448b08fcfa0eee25e
+timeCreated: 1532361007
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 73 - 0
Assets/Plugins/UniTask/Runtime/Internal/ArrayUtil.cs

@@ -0,0 +1,73 @@
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+
+namespace Cysharp.Threading.Tasks.Internal
+{
+    internal static class ArrayUtil
+    {
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static void EnsureCapacity<T>(ref T[] array, int index)
+        {
+            if (array.Length <= index)
+            {
+                EnsureCore(ref array, index);
+            }
+        }
+
+        // rare case, no inlining.
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        static void EnsureCore<T>(ref T[] array, int index)
+        {
+            var newSize = array.Length * 2;
+            var newArray = new T[(index < newSize) ? newSize : (index * 2)];
+            Array.Copy(array, 0, newArray, 0, array.Length);
+
+            array = newArray;
+        }
+
+        /// <summary>
+        /// Optimizing utility to avoid .ToArray() that creates buffer copy(cut to just size).
+        /// </summary>
+        public static (T[] array, int length) Materialize<T>(IEnumerable<T> source)
+        {
+            if (source is T[] array)
+            {
+                return (array, array.Length);
+            }
+
+            var defaultCount = 4;
+            if (source is ICollection<T> coll)
+            {
+                defaultCount = coll.Count;
+                var buffer = new T[defaultCount];
+                coll.CopyTo(buffer, 0);
+                return (buffer, defaultCount);
+            }
+            else if (source is IReadOnlyCollection<T> rcoll)
+            {
+                defaultCount = rcoll.Count;
+            }
+
+            if (defaultCount == 0)
+            {
+                return (Array.Empty<T>(), 0);
+            }
+
+            {
+                var index = 0;
+                var buffer = new T[defaultCount];
+                foreach (var item in source)
+                {
+                    EnsureCapacity(ref buffer, index);
+                    buffer[index++] = item;
+                }
+
+                return (buffer, index);
+            }
+        }
+    }
+}
+

+ 12 - 0
Assets/Plugins/UniTask/Runtime/Internal/ArrayUtil.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 23146a82ec99f2542a87971c8d3d7988
+timeCreated: 1532361007
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 225 - 0
Assets/Plugins/UniTask/Runtime/Internal/ContinuationQueue.cs

@@ -0,0 +1,225 @@
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+
+using System;
+using System.Threading;
+
+namespace Cysharp.Threading.Tasks.Internal
+{
+    internal sealed class ContinuationQueue
+    {
+        const int MaxArrayLength = 0X7FEFFFFF;
+        const int InitialSize = 16;
+
+        readonly PlayerLoopTiming timing;
+
+        SpinLock gate = new SpinLock(false);
+        bool dequing = false;
+
+        int actionListCount = 0;
+        Action[] actionList = new Action[InitialSize];
+
+        int waitingListCount = 0;
+        Action[] waitingList = new Action[InitialSize];
+
+        public ContinuationQueue(PlayerLoopTiming timing)
+        {
+            this.timing = timing;
+        }
+
+        public void Enqueue(Action continuation)
+        {
+            bool lockTaken = false;
+            try
+            {
+                gate.Enter(ref lockTaken);
+
+                if (dequing)
+                {
+                    // Ensure Capacity
+                    if (waitingList.Length == waitingListCount)
+                    {
+                        var newLength = waitingListCount * 2;
+                        if ((uint)newLength > MaxArrayLength) newLength = MaxArrayLength;
+
+                        var newArray = new Action[newLength];
+                        Array.Copy(waitingList, newArray, waitingListCount);
+                        waitingList = newArray;
+                    }
+                    waitingList[waitingListCount] = continuation;
+                    waitingListCount++;
+                }
+                else
+                {
+                    // Ensure Capacity
+                    if (actionList.Length == actionListCount)
+                    {
+                        var newLength = actionListCount * 2;
+                        if ((uint)newLength > MaxArrayLength) newLength = MaxArrayLength;
+
+                        var newArray = new Action[newLength];
+                        Array.Copy(actionList, newArray, actionListCount);
+                        actionList = newArray;
+                    }
+                    actionList[actionListCount] = continuation;
+                    actionListCount++;
+                }
+            }
+            finally
+            {
+                if (lockTaken) gate.Exit(false);
+            }
+        }
+
+        public int Clear()
+        {
+            var rest = actionListCount + waitingListCount;
+
+            actionListCount = 0;
+            actionList = new Action[InitialSize];
+
+            waitingListCount = 0;
+            waitingList = new Action[InitialSize];
+
+            return rest;
+        }
+
+        // delegate entrypoint.
+        public void Run()
+        {
+            // for debugging, create named stacktrace.
+#if DEBUG
+            switch (timing)
+            {
+                case PlayerLoopTiming.Initialization:
+                    Initialization();
+                    break;
+                case PlayerLoopTiming.LastInitialization:
+                    LastInitialization();
+                    break;
+                case PlayerLoopTiming.EarlyUpdate:
+                    EarlyUpdate();
+                    break;
+                case PlayerLoopTiming.LastEarlyUpdate:
+                    LastEarlyUpdate();
+                    break;
+                case PlayerLoopTiming.FixedUpdate:
+                    FixedUpdate();
+                    break;
+                case PlayerLoopTiming.LastFixedUpdate:
+                    LastFixedUpdate();
+                    break;
+                case PlayerLoopTiming.PreUpdate:
+                    PreUpdate();
+                    break;
+                case PlayerLoopTiming.LastPreUpdate:
+                    LastPreUpdate();
+                    break;
+                case PlayerLoopTiming.Update:
+                    Update();
+                    break;
+                case PlayerLoopTiming.LastUpdate:
+                    LastUpdate();
+                    break;
+                case PlayerLoopTiming.PreLateUpdate:
+                    PreLateUpdate();
+                    break;
+                case PlayerLoopTiming.LastPreLateUpdate:
+                    LastPreLateUpdate();
+                    break;
+                case PlayerLoopTiming.PostLateUpdate:
+                    PostLateUpdate();
+                    break;
+                case PlayerLoopTiming.LastPostLateUpdate:
+                    LastPostLateUpdate();
+                    break;
+#if UNITY_2020_2_OR_NEWER
+                case PlayerLoopTiming.TimeUpdate:
+                    TimeUpdate();
+                    break;
+                case PlayerLoopTiming.LastTimeUpdate:
+                    LastTimeUpdate();
+                    break;
+#endif
+                default:
+                    break;
+            }
+#else
+            RunCore();
+#endif
+        }
+
+        void Initialization() => RunCore();
+        void LastInitialization() => RunCore();
+        void EarlyUpdate() => RunCore();
+        void LastEarlyUpdate() => RunCore();
+        void FixedUpdate() => RunCore();
+        void LastFixedUpdate() => RunCore();
+        void PreUpdate() => RunCore();
+        void LastPreUpdate() => RunCore();
+        void Update() => RunCore();
+        void LastUpdate() => RunCore();
+        void PreLateUpdate() => RunCore();
+        void LastPreLateUpdate() => RunCore();
+        void PostLateUpdate() => RunCore();
+        void LastPostLateUpdate() => RunCore();
+#if UNITY_2020_2_OR_NEWER
+        void TimeUpdate() => RunCore();
+        void LastTimeUpdate() => RunCore();
+#endif
+
+        [System.Diagnostics.DebuggerHidden]
+        void RunCore()
+        {
+            {
+                bool lockTaken = false;
+                try
+                {
+                    gate.Enter(ref lockTaken);
+                    if (actionListCount == 0) return;
+                    dequing = true;
+                }
+                finally
+                {
+                    if (lockTaken) gate.Exit(false);
+                }
+            }
+
+            for (int i = 0; i < actionListCount; i++)
+            {
+
+                var action = actionList[i];
+                actionList[i] = null;
+                try
+                {
+                    action();
+                }
+                catch (Exception ex)
+                {
+                    UnityEngine.Debug.LogException(ex);
+                }
+            }
+
+            {
+                bool lockTaken = false;
+                try
+                {
+                    gate.Enter(ref lockTaken);
+                    dequing = false;
+
+                    var swapTempActionList = actionList;
+
+                    actionListCount = waitingListCount;
+                    actionList = waitingList;
+
+                    waitingListCount = 0;
+                    waitingList = swapTempActionList;
+                }
+                finally
+                {
+                    if (lockTaken) gate.Exit(false);
+                }
+            }
+        }
+    }
+}
+

+ 11 - 0
Assets/Plugins/UniTask/Runtime/Internal/ContinuationQueue.cs.meta

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

+ 249 - 0
Assets/Plugins/UniTask/Runtime/Internal/DiagnosticsExtensions.cs

@@ -0,0 +1,249 @@
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Security;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using UnityEngine;
+
+namespace Cysharp.Threading.Tasks.Internal
+{
+    internal static class DiagnosticsExtensions
+    {
+        static bool displayFilenames = true;
+
+        static readonly Regex typeBeautifyRegex = new Regex("`.+$", RegexOptions.Compiled);
+
+        static readonly Dictionary<Type, string> builtInTypeNames = new Dictionary<Type, string>
+        {
+            { typeof(void), "void" },
+            { typeof(bool), "bool" },
+            { typeof(byte), "byte" },
+            { typeof(char), "char" },
+            { typeof(decimal), "decimal" },
+            { typeof(double), "double" },
+            { typeof(float), "float" },
+            { typeof(int), "int" },
+            { typeof(long), "long" },
+            { typeof(object), "object" },
+            { typeof(sbyte), "sbyte" },
+            { typeof(short), "short" },
+            { typeof(string), "string" },
+            { typeof(uint), "uint" },
+            { typeof(ulong), "ulong" },
+            { typeof(ushort), "ushort" },
+            { typeof(Task), "Task" },
+            { typeof(UniTask), "UniTask" },
+            { typeof(UniTaskVoid), "UniTaskVoid" }
+        };
+
+        public static string CleanupAsyncStackTrace(this StackTrace stackTrace)
+        {
+            if (stackTrace == null) return "";
+
+            var sb = new StringBuilder();
+            for (int i = 0; i < stackTrace.FrameCount; i++)
+            {
+                var sf = stackTrace.GetFrame(i);
+
+                var mb = sf.GetMethod();
+
+                if (IgnoreLine(mb)) continue;
+                if (IsAsync(mb))
+                {
+                    sb.Append("async ");
+                    TryResolveStateMachineMethod(ref mb, out var decType);
+                }
+
+                // return type
+                if (mb is MethodInfo mi)
+                {
+                    sb.Append(BeautifyType(mi.ReturnType, false));
+                    sb.Append(" ");
+                }
+
+                // method name
+                sb.Append(BeautifyType(mb.DeclaringType, false));
+                if (!mb.IsConstructor)
+                {
+                    sb.Append(".");
+                }
+                sb.Append(mb.Name);
+                if (mb.IsGenericMethod)
+                {
+                    sb.Append("<");
+                    foreach (var item in mb.GetGenericArguments())
+                    {
+                        sb.Append(BeautifyType(item, true));
+                    }
+                    sb.Append(">");
+                }
+
+                // parameter
+                sb.Append("(");
+                sb.Append(string.Join(", ", mb.GetParameters().Select(p => BeautifyType(p.ParameterType, true) + " " + p.Name)));
+                sb.Append(")");
+
+                // file name
+                if (displayFilenames && (sf.GetILOffset() != -1))
+                {
+                    String fileName = null;
+
+                    try
+                    {
+                        fileName = sf.GetFileName();
+                    }
+                    catch (NotSupportedException)
+                    {
+                        displayFilenames = false;
+                    }
+                    catch (SecurityException)
+                    {
+                        displayFilenames = false;
+                    }
+
+                    if (fileName != null)
+                    {
+                        sb.Append(' ');
+                        sb.AppendFormat(CultureInfo.InvariantCulture, "(at {0})", AppendHyperLink(fileName, sf.GetFileLineNumber().ToString()));
+                    }
+                }
+
+                sb.AppendLine();
+            }
+            return sb.ToString();
+        }
+
+
+        static bool IsAsync(MethodBase methodInfo)
+        {
+            var declareType = methodInfo.DeclaringType;
+            return typeof(IAsyncStateMachine).IsAssignableFrom(declareType);
+        }
+
+        // code from Ben.Demystifier/EnhancedStackTrace.Frame.cs
+        static bool TryResolveStateMachineMethod(ref MethodBase method, out Type declaringType)
+        {
+            declaringType = method.DeclaringType;
+
+            var parentType = declaringType.DeclaringType;
+            if (parentType == null)
+            {
+                return false;
+            }
+
+            var methods = parentType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly);
+            if (methods == null)
+            {
+                return false;
+            }
+
+            foreach (var candidateMethod in methods)
+            {
+                var attributes = candidateMethod.GetCustomAttributes<StateMachineAttribute>(false);
+                if (attributes == null)
+                {
+                    continue;
+                }
+
+                foreach (var asma in attributes)
+                {
+                    if (asma.StateMachineType == declaringType)
+                    {
+                        method = candidateMethod;
+                        declaringType = candidateMethod.DeclaringType;
+                        // Mark the iterator as changed; so it gets the + annotation of the original method
+                        // async statemachines resolve directly to their builder methods so aren't marked as changed
+                        return asma is IteratorStateMachineAttribute;
+                    }
+                }
+            }
+
+            return false;
+        }
+
+        static string BeautifyType(Type t, bool shortName)
+        {
+            if (builtInTypeNames.TryGetValue(t, out var builtin))
+            {
+                return builtin;
+            }
+            if (t.IsGenericParameter) return t.Name;
+            if (t.IsArray) return BeautifyType(t.GetElementType(), shortName) + "[]";
+            if (t.FullName?.StartsWith("System.ValueTuple") ?? false)
+            {
+                return "(" + string.Join(", ", t.GetGenericArguments().Select(x => BeautifyType(x, true))) + ")";
+            }
+            if (!t.IsGenericType) return shortName ? t.Name : t.FullName.Replace("Cysharp.Threading.Tasks.Triggers.", "").Replace("Cysharp.Threading.Tasks.Internal.", "").Replace("Cysharp.Threading.Tasks.", "") ?? t.Name;
+
+            var innerFormat = string.Join(", ", t.GetGenericArguments().Select(x => BeautifyType(x, true)));
+
+            var genericType = t.GetGenericTypeDefinition().FullName;
+            if (genericType == "System.Threading.Tasks.Task`1")
+            {
+                genericType = "Task";
+            }
+
+            return typeBeautifyRegex.Replace(genericType, "").Replace("Cysharp.Threading.Tasks.Triggers.", "").Replace("Cysharp.Threading.Tasks.Internal.", "").Replace("Cysharp.Threading.Tasks.", "") + "<" + innerFormat + ">";
+        }
+
+        static bool IgnoreLine(MethodBase methodInfo)
+        {
+            var declareType = methodInfo.DeclaringType.FullName;
+            if (declareType == "System.Threading.ExecutionContext")
+            {
+                return true;
+            }
+            else if (declareType.StartsWith("System.Runtime.CompilerServices"))
+            {
+                return true;
+            }
+            else if (declareType.StartsWith("Cysharp.Threading.Tasks.CompilerServices"))
+            {
+                return true;
+            }
+            else if (declareType == "System.Threading.Tasks.AwaitTaskContinuation")
+            {
+                return true;
+            }
+            else if (declareType.StartsWith("System.Threading.Tasks.Task"))
+            {
+                return true;
+            }
+            else if (declareType.StartsWith("Cysharp.Threading.Tasks.UniTaskCompletionSourceCore"))
+            {
+                return true;
+            }
+            else if (declareType.StartsWith("Cysharp.Threading.Tasks.AwaiterActions"))
+            {
+                return true;
+            }
+
+            return false;
+        }
+
+        static string AppendHyperLink(string path, string line)
+        {
+            var fi = new FileInfo(path);
+            if (fi.Directory == null)
+            {
+                return fi.Name;
+            }
+            else
+            {
+                var fname = fi.FullName.Replace(Path.DirectorySeparatorChar, '/').Replace(PlayerLoopHelper.ApplicationDataPath, "");
+                var withAssetsPath = "Assets/" + fname;
+                return "<a href=\"" + withAssetsPath + "\" line=\"" + line + "\">" + withAssetsPath + ":" + line + "</a>";
+            }
+        }
+    }
+}
+

+ 11 - 0
Assets/Plugins/UniTask/Runtime/Internal/DiagnosticsExtensions.cs.meta

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

+ 79 - 0
Assets/Plugins/UniTask/Runtime/Internal/Error.cs

@@ -0,0 +1,79 @@
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+
+using System;
+using System.Runtime.CompilerServices;
+
+namespace Cysharp.Threading.Tasks.Internal
+{
+    internal static class Error
+    {
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static void ThrowArgumentNullException<T>(T value, string paramName)
+          where T : class
+        {
+            if (value == null) ThrowArgumentNullExceptionCore(paramName);
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        static void ThrowArgumentNullExceptionCore(string paramName)
+        {
+            throw new ArgumentNullException(paramName);
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static Exception ArgumentOutOfRange(string paramName)
+        {
+            return new ArgumentOutOfRangeException(paramName);
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static Exception NoElements()
+        {
+            return new InvalidOperationException("Source sequence doesn't contain any elements.");
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static Exception MoreThanOneElement()
+        {
+            return new InvalidOperationException("Source sequence contains more than one element.");
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        public static void ThrowArgumentException(string message)
+        {
+            throw new ArgumentException(message);
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        public static void ThrowNotYetCompleted()
+        {
+            throw new InvalidOperationException("Not yet completed.");
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        public static T ThrowNotYetCompleted<T>()
+        {
+            throw new InvalidOperationException("Not yet completed.");
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static void ThrowWhenContinuationIsAlreadyRegistered<T>(T continuationField)
+          where T : class
+        {
+            if (continuationField != null) ThrowInvalidOperationExceptionCore("continuation is already registered.");
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        static void ThrowInvalidOperationExceptionCore(string message)
+        {
+            throw new InvalidOperationException(message);
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        public static void ThrowOperationCanceledException()
+        {
+            throw new OperationCanceledException();
+        }
+    }
+}
+

+ 12 - 0
Assets/Plugins/UniTask/Runtime/Internal/Error.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 5f39f495294d4604b8082202faf98554
+timeCreated: 1532361007
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 112 - 0
Assets/Plugins/UniTask/Runtime/Internal/MinimumQueue.cs

@@ -0,0 +1,112 @@
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+
+using System;
+using System.Runtime.CompilerServices;
+
+namespace Cysharp.Threading.Tasks.Internal
+{
+    // optimized version of Standard Queue<T>.
+    internal class MinimumQueue<T>
+    {
+        const int MinimumGrow = 4;
+        const int GrowFactor = 200;
+
+        T[] array;
+        int head;
+        int tail;
+        int size;
+
+        public MinimumQueue(int capacity)
+        {
+            if (capacity < 0) throw new ArgumentOutOfRangeException("capacity");
+            array = new T[capacity];
+            head = tail = size = 0;
+        }
+
+        public int Count
+        {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            get { return size; }
+        }
+
+        public T Peek()
+        {
+            if (size == 0) ThrowForEmptyQueue();
+            return array[head];
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void Enqueue(T item)
+        {
+            if (size == array.Length)
+            {
+                Grow();
+            }
+
+            array[tail] = item;
+            MoveNext(ref tail);
+            size++;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public T Dequeue()
+        {
+            if (size == 0) ThrowForEmptyQueue();
+
+            int head = this.head;
+            T[] array = this.array;
+            T removed = array[head];
+            array[head] = default(T);
+            MoveNext(ref this.head);
+            size--;
+            return removed;
+        }
+
+        void Grow()
+        {
+            int newcapacity = (int)((long)array.Length * (long)GrowFactor / 100);
+            if (newcapacity < array.Length + MinimumGrow)
+            {
+                newcapacity = array.Length + MinimumGrow;
+            }
+            SetCapacity(newcapacity);
+        }
+
+        void SetCapacity(int capacity)
+        {
+            T[] newarray = new T[capacity];
+            if (size > 0)
+            {
+                if (head < tail)
+                {
+                    Array.Copy(array, head, newarray, 0, size);
+                }
+                else
+                {
+                    Array.Copy(array, head, newarray, 0, array.Length - head);
+                    Array.Copy(array, 0, newarray, array.Length - head, tail);
+                }
+            }
+
+            array = newarray;
+            head = 0;
+            tail = (size == capacity) ? 0 : size;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        void MoveNext(ref int index)
+        {
+            int tmp = index + 1;
+            if (tmp == array.Length)
+            {
+                tmp = 0;
+            }
+            index = tmp;
+        }
+
+        void ThrowForEmptyQueue()
+        {
+            throw new InvalidOperationException("EmptyQueue");
+        }
+    }
+}

+ 11 - 0
Assets/Plugins/UniTask/Runtime/Internal/MinimumQueue.cs.meta

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

+ 260 - 0
Assets/Plugins/UniTask/Runtime/Internal/PlayerLoopRunner.cs

@@ -0,0 +1,260 @@
+
+using System;
+using UnityEngine;
+
+namespace Cysharp.Threading.Tasks.Internal
+{
+    internal sealed class PlayerLoopRunner
+    {
+        const int InitialSize = 16;
+
+        readonly PlayerLoopTiming timing;
+        readonly object runningAndQueueLock = new object();
+        readonly object arrayLock = new object();
+        readonly Action<Exception> unhandledExceptionCallback;
+
+        int tail = 0;
+        bool running = false;
+        IPlayerLoopItem[] loopItems = new IPlayerLoopItem[InitialSize];
+        MinimumQueue<IPlayerLoopItem> waitQueue = new MinimumQueue<IPlayerLoopItem>(InitialSize);
+
+
+
+        public PlayerLoopRunner(PlayerLoopTiming timing)
+        {
+            this.unhandledExceptionCallback = ex => Debug.LogException(ex);
+            this.timing = timing;
+        }
+
+        public void AddAction(IPlayerLoopItem item)
+        {
+            lock (runningAndQueueLock)
+            {
+                if (running)
+                {
+                    waitQueue.Enqueue(item);
+                    return;
+                }
+            }
+
+            lock (arrayLock)
+            {
+                // Ensure Capacity
+                if (loopItems.Length == tail)
+                {
+                    Array.Resize(ref loopItems, checked(tail * 2));
+                }
+                loopItems[tail++] = item;
+            }
+        }
+
+        public int Clear()
+        {
+            lock (arrayLock)
+            {
+                var rest = 0;
+
+                for (var index = 0; index < loopItems.Length; index++)
+                {
+                    if (loopItems[index] != null)
+                    {
+                        rest++;
+                    }
+
+                    loopItems[index] = null;
+                }
+
+                tail = 0;
+                return rest;
+            }
+        }
+
+        // delegate entrypoint.
+        public void Run()
+        {
+            // for debugging, create named stacktrace.
+#if DEBUG
+            switch (timing)
+            {
+                case PlayerLoopTiming.Initialization:
+                    Initialization();
+                    break;
+                case PlayerLoopTiming.LastInitialization:
+                    LastInitialization();
+                    break;
+                case PlayerLoopTiming.EarlyUpdate:
+                    EarlyUpdate();
+                    break;
+                case PlayerLoopTiming.LastEarlyUpdate:
+                    LastEarlyUpdate();
+                    break;
+                case PlayerLoopTiming.FixedUpdate:
+                    FixedUpdate();
+                    break;
+                case PlayerLoopTiming.LastFixedUpdate:
+                    LastFixedUpdate();
+                    break;
+                case PlayerLoopTiming.PreUpdate:
+                    PreUpdate();
+                    break;
+                case PlayerLoopTiming.LastPreUpdate:
+                    LastPreUpdate();
+                    break;
+                case PlayerLoopTiming.Update:
+                    Update();
+                    break;
+                case PlayerLoopTiming.LastUpdate:
+                    LastUpdate();
+                    break;
+                case PlayerLoopTiming.PreLateUpdate:
+                    PreLateUpdate();
+                    break;
+                case PlayerLoopTiming.LastPreLateUpdate:
+                    LastPreLateUpdate();
+                    break;
+                case PlayerLoopTiming.PostLateUpdate:
+                    PostLateUpdate();
+                    break;
+                case PlayerLoopTiming.LastPostLateUpdate:
+                    LastPostLateUpdate();
+                    break;
+#if UNITY_2020_2_OR_NEWER
+                case PlayerLoopTiming.TimeUpdate:
+                    TimeUpdate();
+                    break;
+                case PlayerLoopTiming.LastTimeUpdate:
+                    LastTimeUpdate();
+                    break;
+#endif
+                default:
+                    break;
+            }
+#else
+            RunCore();
+#endif
+        }
+
+        void Initialization() => RunCore();
+        void LastInitialization() => RunCore();
+        void EarlyUpdate() => RunCore();
+        void LastEarlyUpdate() => RunCore();
+        void FixedUpdate() => RunCore();
+        void LastFixedUpdate() => RunCore();
+        void PreUpdate() => RunCore();
+        void LastPreUpdate() => RunCore();
+        void Update() => RunCore();
+        void LastUpdate() => RunCore();
+        void PreLateUpdate() => RunCore();
+        void LastPreLateUpdate() => RunCore();
+        void PostLateUpdate() => RunCore();
+        void LastPostLateUpdate() => RunCore();
+#if UNITY_2020_2_OR_NEWER
+        void TimeUpdate() => RunCore();
+        void LastTimeUpdate() => RunCore();
+#endif
+
+        [System.Diagnostics.DebuggerHidden]
+        void RunCore()
+        {
+            lock (runningAndQueueLock)
+            {
+                running = true;
+            }
+
+            lock (arrayLock)
+            {
+                var j = tail - 1;
+
+                for (int i = 0; i < loopItems.Length; i++)
+                {
+                    var action = loopItems[i];
+                    if (action != null)
+                    {
+                        try
+                        {
+                            if (!action.MoveNext())
+                            {
+                                loopItems[i] = null;
+                            }
+                            else
+                            {
+                                continue; // next i 
+                            }
+                        }
+                        catch (Exception ex)
+                        {
+                            loopItems[i] = null;
+                            try
+                            {
+                                unhandledExceptionCallback(ex);
+                            }
+                            catch { }
+                        }
+                    }
+
+                    // find null, loop from tail
+                    while (i < j)
+                    {
+                        var fromTail = loopItems[j];
+                        if (fromTail != null)
+                        {
+                            try
+                            {
+                                if (!fromTail.MoveNext())
+                                {
+                                    loopItems[j] = null;
+                                    j--;
+                                    continue; // next j
+                                }
+                                else
+                                {
+                                    // swap
+                                    loopItems[i] = fromTail;
+                                    loopItems[j] = null;
+                                    j--;
+                                    goto NEXT_LOOP; // next i
+                                }
+                            }
+                            catch (Exception ex)
+                            {
+                                loopItems[j] = null;
+                                j--;
+                                try
+                                {
+                                    unhandledExceptionCallback(ex);
+                                }
+                                catch { }
+                                continue; // next j
+                            }
+                        }
+                        else
+                        {
+                            j--;
+                        }
+                    }
+
+                    tail = i; // loop end
+                    break; // LOOP END
+
+                    NEXT_LOOP:
+                    continue;
+                }
+
+
+                lock (runningAndQueueLock)
+                {
+                    running = false;
+                    while (waitQueue.Count != 0)
+                    {
+                        if (loopItems.Length == tail)
+                        {
+                            Array.Resize(ref loopItems, checked(tail * 2));
+                        }
+                        loopItems[tail++] = waitQueue.Dequeue();
+                    }
+                }
+            }
+        }
+    }
+}
+

+ 11 - 0
Assets/Plugins/UniTask/Runtime/Internal/PlayerLoopRunner.cs.meta

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

+ 50 - 0
Assets/Plugins/UniTask/Runtime/Internal/PooledDelegate.cs

@@ -0,0 +1,50 @@
+using System;
+using System.Runtime.CompilerServices;
+
+namespace Cysharp.Threading.Tasks.Internal
+{
+    internal sealed class PooledDelegate<T> : ITaskPoolNode<PooledDelegate<T>>
+    {
+        static TaskPool<PooledDelegate<T>> pool;
+
+        PooledDelegate<T> nextNode;
+        public ref PooledDelegate<T> NextNode => ref nextNode;
+
+        static PooledDelegate()
+        {
+            TaskPool.RegisterSizeGetter(typeof(PooledDelegate<T>), () => pool.Size);
+        }
+
+        readonly Action<T> runDelegate;
+        Action continuation;
+
+        PooledDelegate()
+        {
+            runDelegate = Run;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static Action<T> Create(Action continuation)
+        {
+            if (!pool.TryPop(out var item))
+            {
+                item = new PooledDelegate<T>();
+            }
+
+            item.continuation = continuation;
+            return item.runDelegate;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        void Run(T _)
+        {
+            var call = continuation;
+            continuation = null;
+            if (call != null)
+            {
+                pool.TryPush(this);
+                call.Invoke();
+            }
+        }
+    }
+}

+ 11 - 0
Assets/Plugins/UniTask/Runtime/Internal/PooledDelegate.cs.meta

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

+ 64 - 0
Assets/Plugins/UniTask/Runtime/Internal/RuntimeHelpersAbstraction.cs

@@ -0,0 +1,64 @@
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+
+using System;
+#if UNITY_2018_3_OR_NEWER
+using UnityEngine;
+#endif
+
+namespace Cysharp.Threading.Tasks.Internal
+{
+    internal static class RuntimeHelpersAbstraction
+    {
+        // If we can use RuntimeHelpers.IsReferenceOrContainsReferences(.NET Core 2.0), use it.
+        public static bool IsWellKnownNoReferenceContainsType<T>()
+        {
+            return WellKnownNoReferenceContainsType<T>.IsWellKnownType;
+        }
+
+        static bool WellKnownNoReferenceContainsTypeInitialize(Type t)
+        {
+            // The primitive types are Boolean, Byte, SByte, Int16, UInt16, Int32, UInt32, Int64, UInt64, IntPtr, UIntPtr, Char, Double, and Single.
+            if (t.IsPrimitive) return true;
+
+            if (t.IsEnum) return true;
+            if (t == typeof(DateTime)) return true;
+            if (t == typeof(DateTimeOffset)) return true;
+            if (t == typeof(Guid)) return true;
+            if (t == typeof(decimal)) return true;
+
+            // unwrap nullable
+            if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>))
+            {
+                return WellKnownNoReferenceContainsTypeInitialize(t.GetGenericArguments()[0]);
+            }
+
+#if UNITY_2018_3_OR_NEWER
+
+            // or add other wellknown types(Vector, etc...) here
+            if (t == typeof(Vector2)) return true;
+            if (t == typeof(Vector3)) return true;
+            if (t == typeof(Vector4)) return true;
+            if (t == typeof(Color)) return true;
+            if (t == typeof(Rect)) return true;
+            if (t == typeof(Bounds)) return true;
+            if (t == typeof(Quaternion)) return true;
+            if (t == typeof(Vector2Int)) return true;
+            if (t == typeof(Vector3Int)) return true;
+
+#endif
+
+            return false;
+        }
+
+        static class WellKnownNoReferenceContainsType<T>
+        {
+            public static readonly bool IsWellKnownType;
+
+            static WellKnownNoReferenceContainsType()
+            {
+                IsWellKnownType = WellKnownNoReferenceContainsTypeInitialize(typeof(T));
+            }
+        }
+    }
+}
+

+ 12 - 0
Assets/Plugins/UniTask/Runtime/Internal/RuntimeHelpersAbstraction.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 94975e4d4e0c0ea4ba787d3872ce9bb4
+timeCreated: 1532361007
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 153 - 0
Assets/Plugins/UniTask/Runtime/Internal/StatePool.cs

@@ -0,0 +1,153 @@
+using System;
+using System.Collections.Concurrent;
+using System.Runtime.CompilerServices;
+
+namespace Cysharp.Threading.Tasks.Internal
+{
+    internal static class StateTuple
+    {
+        public static StateTuple<T1> Create<T1>(T1 item1)
+        {
+            return StatePool<T1>.Create(item1);
+        }
+
+        public static StateTuple<T1, T2> Create<T1, T2>(T1 item1, T2 item2)
+        {
+            return StatePool<T1, T2>.Create(item1, item2);
+        }
+
+        public static StateTuple<T1, T2, T3> Create<T1, T2, T3>(T1 item1, T2 item2, T3 item3)
+        {
+            return StatePool<T1, T2, T3>.Create(item1, item2, item3);
+        }
+    }
+
+    internal class StateTuple<T1> : IDisposable
+    {
+        public T1 Item1;
+
+        public void Deconstruct(out T1 item1)
+        {
+            item1 = this.Item1;
+        }
+
+        public void Dispose()
+        {
+            StatePool<T1>.Return(this);
+        }
+    }
+
+    internal static class StatePool<T1>
+    {
+        static readonly ConcurrentQueue<StateTuple<T1>> queue = new ConcurrentQueue<StateTuple<T1>>();
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static StateTuple<T1> Create(T1 item1)
+        {
+            if (queue.TryDequeue(out var value))
+            {
+                value.Item1 = item1;
+                return value;
+            }
+
+            return new StateTuple<T1> { Item1 = item1 };
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static void Return(StateTuple<T1> tuple)
+        {
+            tuple.Item1 = default;
+            queue.Enqueue(tuple);
+        }
+    }
+
+    internal class StateTuple<T1, T2> : IDisposable
+    {
+        public T1 Item1;
+        public T2 Item2;
+
+        public void Deconstruct(out T1 item1, out T2 item2)
+        {
+            item1 = this.Item1;
+            item2 = this.Item2;
+        }
+
+        public void Dispose()
+        {
+            StatePool<T1, T2>.Return(this);
+        }
+    }
+
+    internal static class StatePool<T1, T2>
+    {
+        static readonly ConcurrentQueue<StateTuple<T1, T2>> queue = new ConcurrentQueue<StateTuple<T1, T2>>();
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static StateTuple<T1, T2> Create(T1 item1, T2 item2)
+        {
+            if (queue.TryDequeue(out var value))
+            {
+                value.Item1 = item1;
+                value.Item2 = item2;
+                return value;
+            }
+
+            return new StateTuple<T1, T2> { Item1 = item1, Item2 = item2 };
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static void Return(StateTuple<T1, T2> tuple)
+        {
+            tuple.Item1 = default;
+            tuple.Item2 = default;
+            queue.Enqueue(tuple);
+        }
+    }
+
+    internal class StateTuple<T1, T2, T3> : IDisposable
+    {
+        public T1 Item1;
+        public T2 Item2;
+        public T3 Item3;
+
+        public void Deconstruct(out T1 item1, out T2 item2, out T3 item3)
+        {
+            item1 = this.Item1;
+            item2 = this.Item2;
+            item3 = this.Item3;
+        }
+
+        public void Dispose()
+        {
+            StatePool<T1, T2, T3>.Return(this);
+        }
+    }
+
+    internal static class StatePool<T1, T2, T3>
+    {
+        static readonly ConcurrentQueue<StateTuple<T1, T2, T3>> queue = new ConcurrentQueue<StateTuple<T1, T2, T3>>();
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static StateTuple<T1, T2, T3> Create(T1 item1, T2 item2, T3 item3)
+        {
+            if (queue.TryDequeue(out var value))
+            {
+                value.Item1 = item1;
+                value.Item2 = item2;
+                value.Item3 = item3;
+                return value;
+            }
+
+            return new StateTuple<T1, T2, T3> { Item1 = item1, Item2 = item2, Item3 = item3 };
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static void Return(StateTuple<T1, T2, T3> tuple)
+        {
+            tuple.Item1 = default;
+            tuple.Item2 = default;
+            tuple.Item3 = default;
+            queue.Enqueue(tuple);
+        }
+    }
+}

+ 11 - 0
Assets/Plugins/UniTask/Runtime/Internal/StatePool.cs.meta

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

+ 178 - 0
Assets/Plugins/UniTask/Runtime/Internal/TaskTracker.cs

@@ -0,0 +1,178 @@
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Text;
+using System.Threading;
+using Cysharp.Threading.Tasks.Internal;
+
+namespace Cysharp.Threading.Tasks
+{
+    // public for add user custom.
+
+    public static class TaskTracker
+    {
+#if UNITY_EDITOR
+
+        static int trackingId = 0;
+
+        public const string EnableAutoReloadKey = "UniTaskTrackerWindow_EnableAutoReloadKey";
+        public const string EnableTrackingKey = "UniTaskTrackerWindow_EnableTrackingKey";
+        public const string EnableStackTraceKey = "UniTaskTrackerWindow_EnableStackTraceKey";
+
+        public static class EditorEnableState
+        {
+            static bool enableAutoReload;
+            public static bool EnableAutoReload
+            {
+                get { return enableAutoReload; }
+                set
+                {
+                    enableAutoReload = value;
+                    UnityEditor.EditorPrefs.SetBool(EnableAutoReloadKey, value);
+                }
+            }
+
+            static bool enableTracking;
+            public static bool EnableTracking
+            {
+                get { return enableTracking; }
+                set
+                {
+                    enableTracking = value;
+                    UnityEditor.EditorPrefs.SetBool(EnableTrackingKey, value);
+                }
+            }
+
+            static bool enableStackTrace;
+            public static bool EnableStackTrace
+            {
+                get { return enableStackTrace; }
+                set
+                {
+                    enableStackTrace = value;
+                    UnityEditor.EditorPrefs.SetBool(EnableStackTraceKey, value);
+                }
+            }
+        }
+
+#endif
+
+
+        static List<KeyValuePair<IUniTaskSource, (string formattedType, int trackingId, DateTime addTime, string stackTrace)>> listPool = new List<KeyValuePair<IUniTaskSource, (string formattedType, int trackingId, DateTime addTime, string stackTrace)>>();
+
+        static readonly WeakDictionary<IUniTaskSource, (string formattedType, int trackingId, DateTime addTime, string stackTrace)> tracking = new WeakDictionary<IUniTaskSource, (string formattedType, int trackingId, DateTime addTime, string stackTrace)>();
+
+        [Conditional("UNITY_EDITOR")]
+        public static void TrackActiveTask(IUniTaskSource task, int skipFrame)
+        {
+#if UNITY_EDITOR
+            dirty = true;
+            if (!EditorEnableState.EnableTracking) return;
+            var stackTrace = EditorEnableState.EnableStackTrace ? new StackTrace(skipFrame, true).CleanupAsyncStackTrace() : "";
+
+            string typeName;
+            if (EditorEnableState.EnableStackTrace)
+            {
+                var sb = new StringBuilder();
+                TypeBeautify(task.GetType(), sb);
+                typeName = sb.ToString();
+            }
+            else
+            {
+                typeName = task.GetType().Name;
+            }
+            tracking.TryAdd(task, (typeName, Interlocked.Increment(ref trackingId), DateTime.UtcNow, stackTrace));
+#endif
+        }
+
+        [Conditional("UNITY_EDITOR")]
+        public static void RemoveTracking(IUniTaskSource task)
+        {
+#if UNITY_EDITOR
+            dirty = true;
+            if (!EditorEnableState.EnableTracking) return;
+            var success = tracking.TryRemove(task);
+#endif
+        }
+
+        static bool dirty;
+
+        public static bool CheckAndResetDirty()
+        {
+            var current = dirty;
+            dirty = false;
+            return current;
+        }
+
+        /// <summary>(trackingId, awaiterType, awaiterStatus, createdTime, stackTrace)</summary>
+        public static void ForEachActiveTask(Action<int, string, UniTaskStatus, DateTime, string> action)
+        {
+            lock (listPool)
+            {
+                var count = tracking.ToList(ref listPool, clear: false);
+                try
+                {
+                    for (int i = 0; i < count; i++)
+                    {
+                        action(listPool[i].Value.trackingId, listPool[i].Value.formattedType, listPool[i].Key.UnsafeGetStatus(), listPool[i].Value.addTime, listPool[i].Value.stackTrace);
+                        listPool[i] = default;
+                    }
+                }
+                catch
+                {
+                    listPool.Clear();
+                    throw;
+                }
+            }
+        }
+
+        static void TypeBeautify(Type type, StringBuilder sb)
+        {
+            if (type.IsNested)
+            {
+                // TypeBeautify(type.DeclaringType, sb);
+                sb.Append(type.DeclaringType.Name.ToString());
+                sb.Append(".");
+            }
+
+            if (type.IsGenericType)
+            {
+                var genericsStart = type.Name.IndexOf("`");
+                if (genericsStart != -1)
+                {
+                    sb.Append(type.Name.Substring(0, genericsStart));
+                }
+                else
+                {
+                    sb.Append(type.Name);
+                }
+                sb.Append("<");
+                var first = true;
+                foreach (var item in type.GetGenericArguments())
+                {
+                    if (!first)
+                    {
+                        sb.Append(", ");
+                    }
+                    first = false;
+                    TypeBeautify(item, sb);
+                }
+                sb.Append(">");
+            }
+            else
+            {
+                sb.Append(type.Name);
+            }
+        }
+
+        //static string RemoveUniTaskNamespace(string str)
+        //{
+        //    return str.Replace("Cysharp.Threading.Tasks.CompilerServices", "")
+        //        .Replace("Cysharp.Threading.Tasks.Linq", "")
+        //        .Replace("Cysharp.Threading.Tasks", "");
+        //}
+    }
+}
+

+ 11 - 0
Assets/Plugins/UniTask/Runtime/Internal/TaskTracker.cs.meta

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

+ 267 - 0
Assets/Plugins/UniTask/Runtime/Internal/UnityEqualityComparer.cs

@@ -0,0 +1,267 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace Cysharp.Threading.Tasks.Internal
+{
+    internal static class UnityEqualityComparer
+    {
+        public static readonly IEqualityComparer<Vector2> Vector2 = new Vector2EqualityComparer();
+        public static readonly IEqualityComparer<Vector3> Vector3 = new Vector3EqualityComparer();
+        public static readonly IEqualityComparer<Vector4> Vector4 = new Vector4EqualityComparer();
+        public static readonly IEqualityComparer<Color> Color = new ColorEqualityComparer();
+        public static readonly IEqualityComparer<Color32> Color32 = new Color32EqualityComparer();
+        public static readonly IEqualityComparer<Rect> Rect = new RectEqualityComparer();
+        public static readonly IEqualityComparer<Bounds> Bounds = new BoundsEqualityComparer();
+        public static readonly IEqualityComparer<Quaternion> Quaternion = new QuaternionEqualityComparer();
+
+        static readonly RuntimeTypeHandle vector2Type = typeof(Vector2).TypeHandle;
+        static readonly RuntimeTypeHandle vector3Type = typeof(Vector3).TypeHandle;
+        static readonly RuntimeTypeHandle vector4Type = typeof(Vector4).TypeHandle;
+        static readonly RuntimeTypeHandle colorType = typeof(Color).TypeHandle;
+        static readonly RuntimeTypeHandle color32Type = typeof(Color32).TypeHandle;
+        static readonly RuntimeTypeHandle rectType = typeof(Rect).TypeHandle;
+        static readonly RuntimeTypeHandle boundsType = typeof(Bounds).TypeHandle;
+        static readonly RuntimeTypeHandle quaternionType = typeof(Quaternion).TypeHandle;
+
+#if UNITY_2017_2_OR_NEWER
+
+        public static readonly IEqualityComparer<Vector2Int> Vector2Int = new Vector2IntEqualityComparer();
+        public static readonly IEqualityComparer<Vector3Int> Vector3Int = new Vector3IntEqualityComparer();
+        public static readonly IEqualityComparer<RangeInt> RangeInt = new RangeIntEqualityComparer();
+        public static readonly IEqualityComparer<RectInt> RectInt = new RectIntEqualityComparer();
+        public static readonly IEqualityComparer<BoundsInt> BoundsInt = new BoundsIntEqualityComparer();
+
+        static readonly RuntimeTypeHandle vector2IntType = typeof(Vector2Int).TypeHandle;
+        static readonly RuntimeTypeHandle vector3IntType = typeof(Vector3Int).TypeHandle;
+        static readonly RuntimeTypeHandle rangeIntType = typeof(RangeInt).TypeHandle;
+        static readonly RuntimeTypeHandle rectIntType = typeof(RectInt).TypeHandle;
+        static readonly RuntimeTypeHandle boundsIntType = typeof(BoundsInt).TypeHandle;
+
+#endif
+
+        static class Cache<T>
+        {
+            public static readonly IEqualityComparer<T> Comparer;
+
+            static Cache()
+            {
+                var comparer = GetDefaultHelper(typeof(T));
+                if (comparer == null)
+                {
+                    Comparer = EqualityComparer<T>.Default;
+                }
+                else
+                {
+                    Comparer = (IEqualityComparer<T>)comparer;
+                }
+            }
+        }
+
+        public static IEqualityComparer<T> GetDefault<T>()
+        {
+            return Cache<T>.Comparer;
+        }
+
+        static object GetDefaultHelper(Type type)
+        {
+            var t = type.TypeHandle;
+
+            if (t.Equals(vector2Type)) return (object)UnityEqualityComparer.Vector2;
+            if (t.Equals(vector3Type)) return (object)UnityEqualityComparer.Vector3;
+            if (t.Equals(vector4Type)) return (object)UnityEqualityComparer.Vector4;
+            if (t.Equals(colorType)) return (object)UnityEqualityComparer.Color;
+            if (t.Equals(color32Type)) return (object)UnityEqualityComparer.Color32;
+            if (t.Equals(rectType)) return (object)UnityEqualityComparer.Rect;
+            if (t.Equals(boundsType)) return (object)UnityEqualityComparer.Bounds;
+            if (t.Equals(quaternionType)) return (object)UnityEqualityComparer.Quaternion;
+
+#if UNITY_2017_2_OR_NEWER
+
+            if (t.Equals(vector2IntType)) return (object)UnityEqualityComparer.Vector2Int;
+            if (t.Equals(vector3IntType)) return (object)UnityEqualityComparer.Vector3Int;
+            if (t.Equals(rangeIntType)) return (object)UnityEqualityComparer.RangeInt;
+            if (t.Equals(rectIntType)) return (object)UnityEqualityComparer.RectInt;
+            if (t.Equals(boundsIntType)) return (object)UnityEqualityComparer.BoundsInt;
+#endif
+
+            return null;
+        }
+
+        sealed class Vector2EqualityComparer : IEqualityComparer<Vector2>
+        {
+            public bool Equals(Vector2 self, Vector2 vector)
+            {
+                return self.x.Equals(vector.x) && self.y.Equals(vector.y);
+            }
+
+            public int GetHashCode(Vector2 obj)
+            {
+                return obj.x.GetHashCode() ^ obj.y.GetHashCode() << 2;
+            }
+        }
+
+        sealed class Vector3EqualityComparer : IEqualityComparer<Vector3>
+        {
+            public bool Equals(Vector3 self, Vector3 vector)
+            {
+                return self.x.Equals(vector.x) && self.y.Equals(vector.y) && self.z.Equals(vector.z);
+            }
+
+            public int GetHashCode(Vector3 obj)
+            {
+                return obj.x.GetHashCode() ^ obj.y.GetHashCode() << 2 ^ obj.z.GetHashCode() >> 2;
+            }
+        }
+
+        sealed class Vector4EqualityComparer : IEqualityComparer<Vector4>
+        {
+            public bool Equals(Vector4 self, Vector4 vector)
+            {
+                return self.x.Equals(vector.x) && self.y.Equals(vector.y) && self.z.Equals(vector.z) && self.w.Equals(vector.w);
+            }
+
+            public int GetHashCode(Vector4 obj)
+            {
+                return obj.x.GetHashCode() ^ obj.y.GetHashCode() << 2 ^ obj.z.GetHashCode() >> 2 ^ obj.w.GetHashCode() >> 1;
+            }
+        }
+
+        sealed class ColorEqualityComparer : IEqualityComparer<Color>
+        {
+            public bool Equals(Color self, Color other)
+            {
+                return self.r.Equals(other.r) && self.g.Equals(other.g) && self.b.Equals(other.b) && self.a.Equals(other.a);
+            }
+
+            public int GetHashCode(Color obj)
+            {
+                return obj.r.GetHashCode() ^ obj.g.GetHashCode() << 2 ^ obj.b.GetHashCode() >> 2 ^ obj.a.GetHashCode() >> 1;
+            }
+        }
+
+        sealed class RectEqualityComparer : IEqualityComparer<Rect>
+        {
+            public bool Equals(Rect self, Rect other)
+            {
+                return self.x.Equals(other.x) && self.width.Equals(other.width) && self.y.Equals(other.y) && self.height.Equals(other.height);
+            }
+
+            public int GetHashCode(Rect obj)
+            {
+                return obj.x.GetHashCode() ^ obj.width.GetHashCode() << 2 ^ obj.y.GetHashCode() >> 2 ^ obj.height.GetHashCode() >> 1;
+            }
+        }
+
+        sealed class BoundsEqualityComparer : IEqualityComparer<Bounds>
+        {
+            public bool Equals(Bounds self, Bounds vector)
+            {
+                return self.center.Equals(vector.center) && self.extents.Equals(vector.extents);
+            }
+
+            public int GetHashCode(Bounds obj)
+            {
+                return obj.center.GetHashCode() ^ obj.extents.GetHashCode() << 2;
+            }
+        }
+
+        sealed class QuaternionEqualityComparer : IEqualityComparer<Quaternion>
+        {
+            public bool Equals(Quaternion self, Quaternion vector)
+            {
+                return self.x.Equals(vector.x) && self.y.Equals(vector.y) && self.z.Equals(vector.z) && self.w.Equals(vector.w);
+            }
+
+            public int GetHashCode(Quaternion obj)
+            {
+                return obj.x.GetHashCode() ^ obj.y.GetHashCode() << 2 ^ obj.z.GetHashCode() >> 2 ^ obj.w.GetHashCode() >> 1;
+            }
+        }
+
+        sealed class Color32EqualityComparer : IEqualityComparer<Color32>
+        {
+            public bool Equals(Color32 self, Color32 vector)
+            {
+                return self.a.Equals(vector.a) && self.r.Equals(vector.r) && self.g.Equals(vector.g) && self.b.Equals(vector.b);
+            }
+
+            public int GetHashCode(Color32 obj)
+            {
+                return obj.a.GetHashCode() ^ obj.r.GetHashCode() << 2 ^ obj.g.GetHashCode() >> 2 ^ obj.b.GetHashCode() >> 1;
+            }
+        }
+
+#if UNITY_2017_2_OR_NEWER
+
+        sealed class Vector2IntEqualityComparer : IEqualityComparer<Vector2Int>
+        {
+            public bool Equals(Vector2Int self, Vector2Int vector)
+            {
+                return self.x.Equals(vector.x) && self.y.Equals(vector.y);
+            }
+
+            public int GetHashCode(Vector2Int obj)
+            {
+                return obj.x.GetHashCode() ^ obj.y.GetHashCode() << 2;
+            }
+        }
+
+        sealed class Vector3IntEqualityComparer : IEqualityComparer<Vector3Int>
+        {
+            public static readonly Vector3IntEqualityComparer Default = new Vector3IntEqualityComparer();
+
+            public bool Equals(Vector3Int self, Vector3Int vector)
+            {
+                return self.x.Equals(vector.x) && self.y.Equals(vector.y) && self.z.Equals(vector.z);
+            }
+
+            public int GetHashCode(Vector3Int obj)
+            {
+                return obj.x.GetHashCode() ^ obj.y.GetHashCode() << 2 ^ obj.z.GetHashCode() >> 2;
+            }
+        }
+
+        sealed class RangeIntEqualityComparer : IEqualityComparer<RangeInt>
+        {
+            public bool Equals(RangeInt self, RangeInt vector)
+            {
+                return self.start.Equals(vector.start) && self.length.Equals(vector.length);
+            }
+
+            public int GetHashCode(RangeInt obj)
+            {
+                return obj.start.GetHashCode() ^ obj.length.GetHashCode() << 2;
+            }
+        }
+
+        sealed class RectIntEqualityComparer : IEqualityComparer<RectInt>
+        {
+            public bool Equals(RectInt self, RectInt other)
+            {
+                return self.x.Equals(other.x) && self.width.Equals(other.width) && self.y.Equals(other.y) && self.height.Equals(other.height);
+            }
+
+            public int GetHashCode(RectInt obj)
+            {
+                return obj.x.GetHashCode() ^ obj.width.GetHashCode() << 2 ^ obj.y.GetHashCode() >> 2 ^ obj.height.GetHashCode() >> 1;
+            }
+        }
+
+        sealed class BoundsIntEqualityComparer : IEqualityComparer<BoundsInt>
+        {
+            public bool Equals(BoundsInt self, BoundsInt vector)
+            {
+                return Vector3IntEqualityComparer.Default.Equals(self.position, vector.position)
+                    && Vector3IntEqualityComparer.Default.Equals(self.size, vector.size);
+            }
+
+            public int GetHashCode(BoundsInt obj)
+            {
+                return Vector3IntEqualityComparer.Default.GetHashCode(obj.position) ^ Vector3IntEqualityComparer.Default.GetHashCode(obj.size) << 2;
+            }
+        }
+
+#endif
+    }
+}

+ 11 - 0
Assets/Plugins/UniTask/Runtime/Internal/UnityEqualityComparer.cs.meta

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

+ 28 - 0
Assets/Plugins/UniTask/Runtime/Internal/UnityWebRequestExtensions.cs

@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using UnityEngine.Networking;
+
+namespace Cysharp.Threading.Tasks.Internal
+{
+#if ENABLE_UNITYWEBREQUEST && (!UNITY_2019_1_OR_NEWER || UNITASK_WEBREQUEST_SUPPORT)
+    
+    internal static class UnityWebRequestResultExtensions
+    {
+        public static bool IsError(this UnityWebRequest unityWebRequest)
+        {
+#if UNITY_2020_2_OR_NEWER
+            var result = unityWebRequest.result;
+            return (result == UnityWebRequest.Result.ConnectionError)
+                || (result == UnityWebRequest.Result.DataProcessingError)
+                || (result == UnityWebRequest.Result.ProtocolError);
+#else
+            return unityWebRequest.isHttpError || unityWebRequest.isNetworkError;
+#endif
+        }
+    }
+
+#endif
+}

+ 11 - 0
Assets/Plugins/UniTask/Runtime/Internal/UnityWebRequestExtensions.cs.meta

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

+ 37 - 0
Assets/Plugins/UniTask/Runtime/Internal/ValueStopwatch.cs

@@ -0,0 +1,37 @@
+using System;
+using System.Diagnostics;
+
+namespace Cysharp.Threading.Tasks.Internal
+{
+    internal readonly struct ValueStopwatch
+    {
+        static readonly double TimestampToTicks = TimeSpan.TicksPerSecond / (double)Stopwatch.Frequency;
+
+        readonly long startTimestamp;
+
+        public static ValueStopwatch StartNew() => new ValueStopwatch(Stopwatch.GetTimestamp());
+
+        ValueStopwatch(long startTimestamp)
+        {
+            this.startTimestamp = startTimestamp;
+        }
+
+        public TimeSpan Elapsed => TimeSpan.FromTicks(this.ElapsedTicks);
+
+        public bool IsInvalid => startTimestamp == 0;
+
+        public long ElapsedTicks
+        {
+            get
+            {
+                if (startTimestamp == 0)
+                {
+                    throw new InvalidOperationException("Detected invalid initialization(use 'default'), only to create from StartNew().");
+                }
+
+                var delta = Stopwatch.GetTimestamp() - startTimestamp;
+                return (long)(delta * TimestampToTicks);
+            }
+        }
+    }
+}

+ 11 - 0
Assets/Plugins/UniTask/Runtime/Internal/ValueStopwatch.cs.meta

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

+ 334 - 0
Assets/Plugins/UniTask/Runtime/Internal/WeakDictionary.cs

@@ -0,0 +1,334 @@
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+
+using System;
+using System.Collections.Generic;
+using System.Threading;
+
+namespace Cysharp.Threading.Tasks.Internal
+{
+    // Add, Remove, Enumerate with sweep. All operations are thread safe(in spinlock).
+    internal class WeakDictionary<TKey, TValue>
+        where TKey : class
+    {
+        Entry[] buckets;
+        int size;
+        SpinLock gate; // mutable struct(not readonly)
+
+        readonly float loadFactor;
+        readonly IEqualityComparer<TKey> keyEqualityComparer;
+
+        public WeakDictionary(int capacity = 4, float loadFactor = 0.75f, IEqualityComparer<TKey> keyComparer = null)
+        {
+            var tableSize = CalculateCapacity(capacity, loadFactor);
+            this.buckets = new Entry[tableSize];
+            this.loadFactor = loadFactor;
+            this.gate = new SpinLock(false);
+            this.keyEqualityComparer = keyComparer ?? EqualityComparer<TKey>.Default;
+        }
+
+        public bool TryAdd(TKey key, TValue value)
+        {
+            bool lockTaken = false;
+            try
+            {
+                gate.Enter(ref lockTaken);
+                return TryAddInternal(key, value);
+            }
+            finally
+            {
+                if (lockTaken) gate.Exit(false);
+            }
+        }
+
+        public bool TryGetValue(TKey key, out TValue value)
+        {
+            bool lockTaken = false;
+            try
+            {
+                gate.Enter(ref lockTaken);
+                if (TryGetEntry(key, out _, out var entry))
+                {
+                    value = entry.Value;
+                    return true;
+                }
+
+                value = default(TValue);
+                return false;
+            }
+            finally
+            {
+                if (lockTaken) gate.Exit(false);
+            }
+        }
+
+        public bool TryRemove(TKey key)
+        {
+            bool lockTaken = false;
+            try
+            {
+                gate.Enter(ref lockTaken);
+                if (TryGetEntry(key, out var hashIndex, out var entry))
+                {
+                    Remove(hashIndex, entry);
+                    return true;
+                }
+
+                return false;
+            }
+            finally
+            {
+                if (lockTaken) gate.Exit(false);
+            }
+        }
+
+        bool TryAddInternal(TKey key, TValue value)
+        {
+            var nextCapacity = CalculateCapacity(size + 1, loadFactor);
+
+            TRY_ADD_AGAIN:
+            if (buckets.Length < nextCapacity)
+            {
+                // rehash
+                var nextBucket = new Entry[nextCapacity];
+                for (int i = 0; i < buckets.Length; i++)
+                {
+                    var e = buckets[i];
+                    while (e != null)
+                    {
+                        AddToBuckets(nextBucket, key, e.Value, e.Hash);
+                        e = e.Next;
+                    }
+                }
+
+                buckets = nextBucket;
+                goto TRY_ADD_AGAIN;
+            }
+            else
+            {
+                // add entry
+                var successAdd = AddToBuckets(buckets, key, value, keyEqualityComparer.GetHashCode(key));
+                if (successAdd) size++;
+                return successAdd;
+            }
+        }
+
+        bool AddToBuckets(Entry[] targetBuckets, TKey newKey, TValue value, int keyHash)
+        {
+            var h = keyHash;
+            var hashIndex = h & (targetBuckets.Length - 1);
+
+            TRY_ADD_AGAIN:
+            if (targetBuckets[hashIndex] == null)
+            {
+                targetBuckets[hashIndex] = new Entry
+                {
+                    Key = new WeakReference<TKey>(newKey, false),
+                    Value = value,
+                    Hash = h
+                };
+
+                return true;
+            }
+            else
+            {
+                // add to last.
+                var entry = targetBuckets[hashIndex];
+                while (entry != null)
+                {
+                    if (entry.Key.TryGetTarget(out var target))
+                    {
+                        if (keyEqualityComparer.Equals(newKey, target))
+                        {
+                            return false; // duplicate
+                        }
+                    }
+                    else
+                    {
+                        Remove(hashIndex, entry);
+                        if (targetBuckets[hashIndex] == null) goto TRY_ADD_AGAIN; // add new entry
+                    }
+
+                    if (entry.Next != null)
+                    {
+                        entry = entry.Next;
+                    }
+                    else
+                    {
+                        // found last
+                        entry.Next = new Entry
+                        {
+                            Key = new WeakReference<TKey>(newKey, false),
+                            Value = value,
+                            Hash = h
+                        };
+                        entry.Next.Prev = entry;
+                    }
+                }
+
+                return false;
+            }
+        }
+
+        bool TryGetEntry(TKey key, out int hashIndex, out Entry entry)
+        {
+            var table = buckets;
+            var hash = keyEqualityComparer.GetHashCode(key);
+            hashIndex = hash & table.Length - 1;
+            entry = table[hashIndex];
+
+            while (entry != null)
+            {
+                if (entry.Key.TryGetTarget(out var target))
+                {
+                    if (keyEqualityComparer.Equals(key, target))
+                    {
+                        return true;
+                    }
+                }
+                else
+                {
+                    // sweap
+                    Remove(hashIndex, entry);
+                }
+
+                entry = entry.Next;
+            }
+
+            return false;
+        }
+
+        void Remove(int hashIndex, Entry entry)
+        {
+            if (entry.Prev == null && entry.Next == null)
+            {
+                buckets[hashIndex] = null;
+            }
+            else
+            {
+                if (entry.Prev == null)
+                {
+                    buckets[hashIndex] = entry.Next;
+                }
+                if (entry.Prev != null)
+                {
+                    entry.Prev.Next = entry.Next;
+                }
+                if (entry.Next != null)
+                {
+                    entry.Next.Prev = entry.Prev;
+                }
+            }
+            size--;
+        }
+
+        public List<KeyValuePair<TKey, TValue>> ToList()
+        {
+            var list = new List<KeyValuePair<TKey, TValue>>(size);
+            ToList(ref list, false);
+            return list;
+        }
+
+        // avoid allocate everytime.
+        public int ToList(ref List<KeyValuePair<TKey, TValue>> list, bool clear = true)
+        {
+            if (clear)
+            {
+                list.Clear();
+            }
+
+            var listIndex = 0;
+
+            bool lockTaken = false;
+            try
+            {
+                for (int i = 0; i < buckets.Length; i++)
+                {
+                    var entry = buckets[i];
+                    while (entry != null)
+                    {
+                        if (entry.Key.TryGetTarget(out var target))
+                        {
+                            var item = new KeyValuePair<TKey, TValue>(target, entry.Value);
+                            if (listIndex < list.Count)
+                            {
+                                list[listIndex++] = item;
+                            }
+                            else
+                            {
+                                list.Add(item);
+                                listIndex++;
+                            }
+                        }
+                        else
+                        {
+                            // sweap
+                            Remove(i, entry);
+                        }
+
+                        entry = entry.Next;
+                    }
+                }
+            }
+            finally
+            {
+                if (lockTaken) gate.Exit(false);
+            }
+
+            return listIndex;
+        }
+
+        static int CalculateCapacity(int collectionSize, float loadFactor)
+        {
+            var size = (int)(((float)collectionSize) / loadFactor);
+
+            size--;
+            size |= size >> 1;
+            size |= size >> 2;
+            size |= size >> 4;
+            size |= size >> 8;
+            size |= size >> 16;
+            size += 1;
+
+            if (size < 8)
+            {
+                size = 8;
+            }
+            return size;
+        }
+
+        class Entry
+        {
+            public WeakReference<TKey> Key;
+            public TValue Value;
+            public int Hash;
+            public Entry Prev;
+            public Entry Next;
+
+            // debug only
+            public override string ToString()
+            {
+                if (Key.TryGetTarget(out var target))
+                {
+                    return target + "(" + Count() + ")";
+                }
+                else
+                {
+                    return "(Dead)";
+                }
+            }
+
+            int Count()
+            {
+                var count = 1;
+                var n = this;
+                while (n.Next != null)
+                {
+                    count++;
+                    n = n.Next;
+                }
+                return count;
+            }
+        }
+    }
+}
+

+ 11 - 0
Assets/Plugins/UniTask/Runtime/Internal/WeakDictionary.cs.meta

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

+ 8 - 0
Assets/Plugins/UniTask/Runtime/Linq.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: a3489ae7f48017c4cb817630e01e23d9
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 318 - 0
Assets/Plugins/UniTask/Runtime/Linq/Aggregate.cs

@@ -0,0 +1,318 @@
+using Cysharp.Threading.Tasks.Internal;
+using System;
+using System.Collections.Generic;
+using System.Threading;
+
+namespace Cysharp.Threading.Tasks.Linq
+{
+    public static partial class UniTaskAsyncEnumerable
+    {
+        public static UniTask<TSource> AggregateAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TSource, TSource> accumulator, CancellationToken cancellationToken = default)
+        {
+            Error.ThrowArgumentNullException(source, nameof(source));
+            Error.ThrowArgumentNullException(accumulator, nameof(accumulator));
+
+            return Aggregate.AggregateAsync(source, accumulator, cancellationToken);
+        }
+
+        public static UniTask<TAccumulate> AggregateAsync<TSource, TAccumulate>(this IUniTaskAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator, CancellationToken cancellationToken = default)
+        {
+            Error.ThrowArgumentNullException(source, nameof(source));
+            Error.ThrowArgumentNullException(accumulator, nameof(accumulator));
+
+            return Aggregate.AggregateAsync(source, seed, accumulator, cancellationToken);
+        }
+
+        public static UniTask<TResult> AggregateAsync<TSource, TAccumulate, TResult>(this IUniTaskAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator, Func<TAccumulate, TResult> resultSelector, CancellationToken cancellationToken = default)
+        {
+            Error.ThrowArgumentNullException(source, nameof(source));
+            Error.ThrowArgumentNullException(accumulator, nameof(accumulator));
+            Error.ThrowArgumentNullException(accumulator, nameof(resultSelector));
+
+            return Aggregate.AggregateAsync(source, seed, accumulator, resultSelector, cancellationToken);
+        }
+
+        public static UniTask<TSource> AggregateAwaitAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TSource, UniTask<TSource>> accumulator, CancellationToken cancellationToken = default)
+        {
+            Error.ThrowArgumentNullException(source, nameof(source));
+            Error.ThrowArgumentNullException(accumulator, nameof(accumulator));
+
+            return Aggregate.AggregateAwaitAsync(source, accumulator, cancellationToken);
+        }
+
+        public static UniTask<TAccumulate> AggregateAwaitAsync<TSource, TAccumulate>(this IUniTaskAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, UniTask<TAccumulate>> accumulator, CancellationToken cancellationToken = default)
+        {
+            Error.ThrowArgumentNullException(source, nameof(source));
+            Error.ThrowArgumentNullException(accumulator, nameof(accumulator));
+
+            return Aggregate.AggregateAwaitAsync(source, seed, accumulator, cancellationToken);
+        }
+
+        public static UniTask<TResult> AggregateAwaitAsync<TSource, TAccumulate, TResult>(this IUniTaskAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, UniTask<TAccumulate>> accumulator, Func<TAccumulate, UniTask<TResult>> resultSelector, CancellationToken cancellationToken = default)
+        {
+            Error.ThrowArgumentNullException(source, nameof(source));
+            Error.ThrowArgumentNullException(accumulator, nameof(accumulator));
+            Error.ThrowArgumentNullException(accumulator, nameof(resultSelector));
+
+            return Aggregate.AggregateAwaitAsync(source, seed, accumulator, resultSelector, cancellationToken);
+        }
+
+        public static UniTask<TSource> AggregateAwaitWithCancellationAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TSource, CancellationToken, UniTask<TSource>> accumulator, CancellationToken cancellationToken = default)
+        {
+            Error.ThrowArgumentNullException(source, nameof(source));
+            Error.ThrowArgumentNullException(accumulator, nameof(accumulator));
+
+            return Aggregate.AggregateAwaitWithCancellationAsync(source, accumulator, cancellationToken);
+        }
+
+        public static UniTask<TAccumulate> AggregateAwaitWithCancellationAsync<TSource, TAccumulate>(this IUniTaskAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, CancellationToken, UniTask<TAccumulate>> accumulator, CancellationToken cancellationToken = default)
+        {
+            Error.ThrowArgumentNullException(source, nameof(source));
+            Error.ThrowArgumentNullException(accumulator, nameof(accumulator));
+
+            return Aggregate.AggregateAwaitWithCancellationAsync(source, seed, accumulator, cancellationToken);
+        }
+
+        public static UniTask<TResult> AggregateAwaitWithCancellationAsync<TSource, TAccumulate, TResult>(this IUniTaskAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, CancellationToken, UniTask<TAccumulate>> accumulator, Func<TAccumulate, CancellationToken, UniTask<TResult>> resultSelector, CancellationToken cancellationToken = default)
+        {
+            Error.ThrowArgumentNullException(source, nameof(source));
+            Error.ThrowArgumentNullException(accumulator, nameof(accumulator));
+            Error.ThrowArgumentNullException(accumulator, nameof(resultSelector));
+
+            return Aggregate.AggregateAwaitWithCancellationAsync(source, seed, accumulator, resultSelector, cancellationToken);
+        }
+    }
+
+    internal static class Aggregate
+    {
+        internal static async UniTask<TSource> AggregateAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TSource, TSource> accumulator, CancellationToken cancellationToken)
+        {
+            var e = source.GetAsyncEnumerator(cancellationToken);
+            try
+            {
+                TSource value;
+                if (await e.MoveNextAsync())
+                {
+                    value = e.Current;
+                }
+                else
+                {
+                    throw Error.NoElements();
+                }
+
+                while (await e.MoveNextAsync())
+                {
+                    value = accumulator(value, e.Current);
+                }
+                return value;
+
+            }
+            finally
+            {
+                if (e != null)
+                {
+                    await e.DisposeAsync();
+                }
+            }
+        }
+
+        internal static async UniTask<TAccumulate> AggregateAsync<TSource, TAccumulate>(IUniTaskAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator, CancellationToken cancellationToken)
+        {
+            var e = source.GetAsyncEnumerator(cancellationToken);
+            try
+            {
+                TAccumulate value = seed;
+                while (await e.MoveNextAsync())
+                {
+                    value = accumulator(value, e.Current);
+                }
+                return value;
+
+            }
+            finally
+            {
+                if (e != null)
+                {
+                    await e.DisposeAsync();
+                }
+            }
+        }
+
+        internal static async UniTask<TResult> AggregateAsync<TSource, TAccumulate, TResult>(IUniTaskAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator, Func<TAccumulate, TResult> resultSelector, CancellationToken cancellationToken)
+        {
+            var e = source.GetAsyncEnumerator(cancellationToken);
+            try
+            {
+                TAccumulate value = seed;
+                while (await e.MoveNextAsync())
+                {
+                    value = accumulator(value, e.Current);
+                }
+                return resultSelector(value);
+
+            }
+            finally
+            {
+                if (e != null)
+                {
+                    await e.DisposeAsync();
+                }
+            }
+        }
+
+        // with async
+
+        internal static async UniTask<TSource> AggregateAwaitAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TSource, UniTask<TSource>> accumulator, CancellationToken cancellationToken)
+        {
+            var e = source.GetAsyncEnumerator(cancellationToken);
+            try
+            {
+                TSource value;
+                if (await e.MoveNextAsync())
+                {
+                    value = e.Current;
+                }
+                else
+                {
+                    throw Error.NoElements();
+                }
+
+                while (await e.MoveNextAsync())
+                {
+                    value = await accumulator(value, e.Current);
+                }
+                return value;
+
+            }
+            finally
+            {
+                if (e != null)
+                {
+                    await e.DisposeAsync();
+                }
+            }
+        }
+
+        internal static async UniTask<TAccumulate> AggregateAwaitAsync<TSource, TAccumulate>(IUniTaskAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, UniTask<TAccumulate>> accumulator, CancellationToken cancellationToken)
+        {
+            var e = source.GetAsyncEnumerator(cancellationToken);
+            try
+            {
+                TAccumulate value = seed;
+                while (await e.MoveNextAsync())
+                {
+                    value = await accumulator(value, e.Current);
+                }
+                return value;
+
+            }
+            finally
+            {
+                if (e != null)
+                {
+                    await e.DisposeAsync();
+                }
+            }
+        }
+
+        internal static async UniTask<TResult> AggregateAwaitAsync<TSource, TAccumulate, TResult>(IUniTaskAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, UniTask<TAccumulate>> accumulator, Func<TAccumulate, UniTask<TResult>> resultSelector, CancellationToken cancellationToken)
+        {
+            var e = source.GetAsyncEnumerator(cancellationToken);
+            try
+            {
+                TAccumulate value = seed;
+                while (await e.MoveNextAsync())
+                {
+                    value = await accumulator(value, e.Current);
+                }
+                return await resultSelector(value);
+
+            }
+            finally
+            {
+                if (e != null)
+                {
+                    await e.DisposeAsync();
+                }
+            }
+        }
+
+
+        // with cancellation
+
+        internal static async UniTask<TSource> AggregateAwaitWithCancellationAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TSource, CancellationToken, UniTask<TSource>> accumulator, CancellationToken cancellationToken)
+        {
+            var e = source.GetAsyncEnumerator(cancellationToken);
+            try
+            {
+                TSource value;
+                if (await e.MoveNextAsync())
+                {
+                    value = e.Current;
+                }
+                else
+                {
+                    throw Error.NoElements();
+                }
+
+                while (await e.MoveNextAsync())
+                {
+                    value = await accumulator(value, e.Current, cancellationToken);
+                }
+                return value;
+
+            }
+            finally
+            {
+                if (e != null)
+                {
+                    await e.DisposeAsync();
+                }
+            }
+        }
+
+        internal static async UniTask<TAccumulate> AggregateAwaitWithCancellationAsync<TSource, TAccumulate>(IUniTaskAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, CancellationToken, UniTask<TAccumulate>> accumulator, CancellationToken cancellationToken)
+        {
+            var e = source.GetAsyncEnumerator(cancellationToken);
+            try
+            {
+                TAccumulate value = seed;
+                while (await e.MoveNextAsync())
+                {
+                    value = await accumulator(value, e.Current, cancellationToken);
+                }
+                return value;
+
+            }
+            finally
+            {
+                if (e != null)
+                {
+                    await e.DisposeAsync();
+                }
+            }
+        }
+
+        internal static async UniTask<TResult> AggregateAwaitWithCancellationAsync<TSource, TAccumulate, TResult>(IUniTaskAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, CancellationToken, UniTask<TAccumulate>> accumulator, Func<TAccumulate, CancellationToken, UniTask<TResult>> resultSelector, CancellationToken cancellationToken)
+        {
+            var e = source.GetAsyncEnumerator(cancellationToken);
+            try
+            {
+                TAccumulate value = seed;
+                while (await e.MoveNextAsync())
+                {
+                    value = await accumulator(value, e.Current, cancellationToken);
+                }
+                return await resultSelector(value, cancellationToken);
+
+            }
+            finally
+            {
+                if (e != null)
+                {
+                    await e.DisposeAsync();
+                }
+            }
+        }
+    }
+}

+ 11 - 0
Assets/Plugins/UniTask/Runtime/Linq/Aggregate.cs.meta

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

+ 108 - 0
Assets/Plugins/UniTask/Runtime/Linq/All.cs

@@ -0,0 +1,108 @@
+using Cysharp.Threading.Tasks.Internal;
+using System;
+using System.Threading;
+
+namespace Cysharp.Threading.Tasks.Linq
+{
+    public static partial class UniTaskAsyncEnumerable
+    {
+        public static UniTask<Boolean> AllAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Boolean> predicate, CancellationToken cancellationToken = default)
+        {
+            Error.ThrowArgumentNullException(source, nameof(source));
+            Error.ThrowArgumentNullException(predicate, nameof(predicate));
+
+            return All.AllAsync(source, predicate, cancellationToken);
+        }
+
+        public static UniTask<Boolean> AllAwaitAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<Boolean>> predicate, CancellationToken cancellationToken = default)
+        {
+            Error.ThrowArgumentNullException(source, nameof(source));
+            Error.ThrowArgumentNullException(predicate, nameof(predicate));
+
+            return All.AllAwaitAsync(source, predicate, cancellationToken);
+        }
+
+        public static UniTask<Boolean> AllAwaitWithCancellationAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<Boolean>> predicate, CancellationToken cancellationToken = default)
+        {
+            Error.ThrowArgumentNullException(source, nameof(source));
+            Error.ThrowArgumentNullException(predicate, nameof(predicate));
+
+            return All.AllAwaitWithCancellationAsync(source, predicate, cancellationToken);
+        }
+    }
+
+    internal static class All
+    {
+        internal static async UniTask<bool> AllAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Boolean> predicate, CancellationToken cancellationToken)
+        {
+            var e = source.GetAsyncEnumerator(cancellationToken);
+            try
+            {
+                while (await e.MoveNextAsync())
+                {
+                    if (!predicate(e.Current))
+                    {
+                        return false;
+                    }
+                }
+
+                return true;
+            }
+            finally
+            {
+                if (e != null)
+                {
+                    await e.DisposeAsync();
+                }
+            }
+        }
+
+        internal static async UniTask<bool> AllAwaitAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<Boolean>> predicate, CancellationToken cancellationToken)
+        {
+            var e = source.GetAsyncEnumerator(cancellationToken);
+            try
+            {
+                while (await e.MoveNextAsync())
+                {
+                    if (!await predicate(e.Current))
+                    {
+                        return false;
+                    }
+                }
+
+                return true;
+            }
+            finally
+            {
+                if (e != null)
+                {
+                    await e.DisposeAsync();
+                }
+            }
+        }
+
+        internal static async UniTask<bool> AllAwaitWithCancellationAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<Boolean>> predicate, CancellationToken cancellationToken)
+        {
+            var e = source.GetAsyncEnumerator(cancellationToken);
+            try
+            {
+                while (await e.MoveNextAsync())
+                {
+                    if (!await predicate(e.Current, cancellationToken))
+                    {
+                        return false;
+                    }
+                }
+
+                return true;
+            }
+            finally
+            {
+                if (e != null)
+                {
+                    await e.DisposeAsync();
+                }
+            }
+        }
+    }
+}

+ 11 - 0
Assets/Plugins/UniTask/Runtime/Linq/All.cs.meta

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

Some files were not shown because too many files changed in this diff