claude-code-arcane 2.3.0 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +131 -41
  3. package/agents/game/ue-blueprint-specialist.md +125 -0
  4. package/agents/game/ue-gas-specialist.md +133 -0
  5. package/agents/game/ue-umg-specialist.md +131 -0
  6. package/dist/cli.js +642 -478
  7. package/docs/SKILLS-CATALOG.md +42 -3
  8. package/docs/USER-GUIDE.md +28 -54
  9. package/hooks/detect-unreal.sh +90 -0
  10. package/package.json +2 -1
  11. package/profiles/agile.yaml +1 -1
  12. package/profiles/ai.yaml +1 -1
  13. package/profiles/android-native.yaml +1 -1
  14. package/profiles/audio.yaml +1 -1
  15. package/profiles/backend-dotnet.yaml +1 -1
  16. package/profiles/backend-go.yaml +1 -1
  17. package/profiles/backend-nestjs.yaml +1 -1
  18. package/profiles/backend-nextjs.yaml +1 -1
  19. package/profiles/backend-ts.yaml +1 -1
  20. package/profiles/business.yaml +1 -1
  21. package/profiles/clevel.yaml +1 -1
  22. package/profiles/clickup.yaml +1 -1
  23. package/profiles/core.yaml +1 -1
  24. package/profiles/database.yaml +1 -1
  25. package/profiles/design.yaml +1 -1
  26. package/profiles/docs.yaml +1 -1
  27. package/profiles/ecommerce.yaml +1 -1
  28. package/profiles/finance.yaml +1 -1
  29. package/profiles/flutter.yaml +1 -1
  30. package/profiles/freelance.yaml +1 -1
  31. package/profiles/frontend.yaml +1 -1
  32. package/profiles/infra.yaml +1 -1
  33. package/profiles/integrations.yaml +1 -1
  34. package/profiles/ios-native.yaml +1 -1
  35. package/profiles/jira.yaml +1 -1
  36. package/profiles/job-hunt.yaml +1 -1
  37. package/profiles/marketing.yaml +1 -1
  38. package/profiles/mobile.yaml +1 -1
  39. package/profiles/regulatory.yaml +1 -1
  40. package/profiles/second-brain.yaml +1 -1
  41. package/profiles/security.yaml +1 -1
  42. package/profiles/self-improving.yaml +1 -1
  43. package/profiles/statusline.yaml +1 -1
  44. package/profiles/testing.yaml +1 -1
  45. package/profiles/unity-design.yaml +1 -1
  46. package/profiles/unity-dev.yaml +1 -1
  47. package/profiles/unreal-dev.yaml +97 -0
  48. package/profiles/visual-novel.yaml +1 -1
  49. package/rules/gamedev/unreal-code.md +125 -0
  50. package/skills/arcane-list/SKILL.md +12 -7
  51. package/skills/install-mcp/SKILL.md +135 -46
  52. package/skills/install-mcp/references/unreal-operations.md +55 -0
  53. package/skills/ue-actor-component-architecture/SKILL.md +509 -0
  54. package/skills/ue-actor-component-architecture/references/actor-lifecycle.md +301 -0
  55. package/skills/ue-actor-component-architecture/references/component-types.md +592 -0
  56. package/skills/ue-ai-navigation/SKILL.md +526 -0
  57. package/skills/ue-ai-navigation/references/behavior-tree-patterns.md +392 -0
  58. package/skills/ue-ai-navigation/references/behavior-tree-workflow.md +107 -0
  59. package/skills/ue-ai-navigation/references/custom-bttask.md +104 -0
  60. package/skills/ue-ai-navigation/references/eqs-reference.md +423 -0
  61. package/skills/ue-animation-system/SKILL.md +521 -0
  62. package/skills/ue-animation-system/references/anim-notify-reference.md +486 -0
  63. package/skills/ue-animation-system/references/locomotion-setup.md +550 -0
  64. package/skills/ue-async-threading/SKILL.md +433 -0
  65. package/skills/ue-async-threading/references/thread-safety-guide.md +213 -0
  66. package/skills/ue-async-threading/references/threading-patterns.md +345 -0
  67. package/skills/ue-audio-system/SKILL.md +527 -0
  68. package/skills/ue-audio-system/references/audio-setup-patterns.md +700 -0
  69. package/skills/ue-blueprints/SKILL.md +134 -0
  70. package/skills/ue-blueprints/references/communication.md +82 -0
  71. package/skills/ue-character-movement/SKILL.md +475 -0
  72. package/skills/ue-character-movement/references/cmc-extension-patterns.md +335 -0
  73. package/skills/ue-character-movement/references/movement-pipeline.md +189 -0
  74. package/skills/ue-cpp-foundations/SKILL.md +533 -0
  75. package/skills/ue-cpp-foundations/references/components-and-gc.md +107 -0
  76. package/skills/ue-cpp-foundations/references/container-patterns.md +544 -0
  77. package/skills/ue-cpp-foundations/references/delegate-patterns.md +497 -0
  78. package/skills/ue-cpp-foundations/references/gameplay-classes-cpp.md +136 -0
  79. package/skills/ue-cpp-foundations/references/property-specifiers.md +306 -0
  80. package/skills/ue-data-assets-tables/SKILL.md +527 -0
  81. package/skills/ue-data-assets-tables/references/asset-loading-patterns.md +306 -0
  82. package/skills/ue-data-assets-tables/references/data-driven-design.md +378 -0
  83. package/skills/ue-editor-tools/SKILL.md +523 -0
  84. package/skills/ue-editor-tools/references/detail-customization-patterns.md +395 -0
  85. package/skills/ue-editor-tools/references/editor-module-setup.md +480 -0
  86. package/skills/ue-game-features/SKILL.md +477 -0
  87. package/skills/ue-game-features/references/experience-system.md +222 -0
  88. package/skills/ue-game-features/references/game-feature-patterns.md +308 -0
  89. package/skills/ue-gameplay-abilities/SKILL.md +518 -0
  90. package/skills/ue-gameplay-abilities/references/ability-task-reference.md +391 -0
  91. package/skills/ue-gameplay-abilities/references/gameplay-effect-reference.md +397 -0
  92. package/skills/ue-gameplay-abilities/references/gas-setup-patterns.md +369 -0
  93. package/skills/ue-gameplay-framework/SKILL.md +466 -0
  94. package/skills/ue-gameplay-framework/references/framework-class-map.md +243 -0
  95. package/skills/ue-input-system/SKILL.md +394 -0
  96. package/skills/ue-input-system/references/cpp-setup.md +131 -0
  97. package/skills/ue-input-system/references/enhanced-input-workflow.md +117 -0
  98. package/skills/ue-input-system/references/input-action-reference.md +731 -0
  99. package/skills/ue-mass-entity/SKILL.md +476 -0
  100. package/skills/ue-mass-entity/references/mass-entity-patterns.md +319 -0
  101. package/skills/ue-mass-entity/references/mass-fragment-reference.md +119 -0
  102. package/skills/ue-materials-rendering/SKILL.md +526 -0
  103. package/skills/ue-materials-rendering/references/material-parameter-reference.md +216 -0
  104. package/skills/ue-materials-rendering/references/post-process-settings.md +383 -0
  105. package/skills/ue-module-build-system/SKILL.md +487 -0
  106. package/skills/ue-module-build-system/references/build-cs-reference.md +418 -0
  107. package/skills/ue-module-build-system/references/common-build-errors.md +381 -0
  108. package/skills/ue-naming-conventions/SKILL.md +142 -0
  109. package/skills/ue-naming-conventions/references/asset-name-modifiers.md +233 -0
  110. package/skills/ue-naming-conventions/references/content-structure.md +83 -0
  111. package/skills/ue-networking-replication/SKILL.md +452 -0
  112. package/skills/ue-networking-replication/references/replication-patterns.md +526 -0
  113. package/skills/ue-networking-replication/references/rpc-decision-guide.md +393 -0
  114. package/skills/ue-niagara-effects/SKILL.md +531 -0
  115. package/skills/ue-niagara-effects/references/niagara-data-interfaces.md +491 -0
  116. package/skills/ue-niagara-effects/references/niagara-parameter-types.md +153 -0
  117. package/skills/ue-niagara-effects/references/niagara-workflow.md +115 -0
  118. package/skills/ue-packaging/SKILL.md +116 -0
  119. package/skills/ue-physics-collision/SKILL.md +423 -0
  120. package/skills/ue-physics-collision/references/collision-channel-setup.md +218 -0
  121. package/skills/ue-physics-collision/references/trace-patterns.md +499 -0
  122. package/skills/ue-procedural-generation/SKILL.md +505 -0
  123. package/skills/ue-procedural-generation/references/pcg-node-reference.md +381 -0
  124. package/skills/ue-procedural-generation/references/procedural-mesh-patterns.md +940 -0
  125. package/skills/ue-project-context/SKILL.md +305 -0
  126. package/skills/ue-sequencer-cinematics/SKILL.md +506 -0
  127. package/skills/ue-sequencer-cinematics/references/sequencer-patterns.md +629 -0
  128. package/skills/ue-serialization-savegames/SKILL.md +524 -0
  129. package/skills/ue-serialization-savegames/references/save-system-architecture.md +705 -0
  130. package/skills/ue-state-trees/SKILL.md +489 -0
  131. package/skills/ue-state-trees/references/state-tree-mass-integration.md +184 -0
  132. package/skills/ue-state-trees/references/state-tree-patterns.md +321 -0
  133. package/skills/ue-testing-debugging/SKILL.md +520 -0
  134. package/skills/ue-testing-debugging/references/automation-test-patterns.md +387 -0
  135. package/skills/ue-testing-debugging/references/profiling-commands.md +357 -0
  136. package/skills/ue-ui-umg-slate/SKILL.md +431 -0
  137. package/skills/ue-ui-umg-slate/references/common-ui-setup.md +484 -0
  138. package/skills/ue-ui-umg-slate/references/widget-types.md +487 -0
  139. package/skills/ue-world-level-streaming/SKILL.md +518 -0
  140. package/skills/ue-world-level-streaming/references/streaming-patterns.md +414 -0
  141. package/templates/gamedev/unreal-project-context.md +107 -0
@@ -0,0 +1,391 @@
1
+ # Ability Task Reference
2
+
3
+ Common built-in `UAbilityTask` subclasses and how to create custom tasks.
4
+ Ability tasks extend ability execution across multiple frames using internal latent logic.
5
+
6
+ All tasks must be called from within `ActivateAbility` (or from within other tasks).
7
+ Tasks broadcast results via dynamic delegates. When the task completes, call `EndAbility`
8
+ if the ability is meant to end at that point.
9
+
10
+ ---
11
+
12
+ ## How Ability Tasks Work
13
+
14
+ 1. Create the task via a static factory function (never call `new` directly).
15
+ 2. Bind delegates for each outcome (OnCompleted, OnInterrupted, etc.).
16
+ 3. Call `ReadyForActivation()` to start the task.
17
+ 4. The task runs asynchronously; the ability remains active but yields.
18
+ 5. In delegate callbacks, perform follow-up logic and call `EndAbility` when done.
19
+
20
+ ```cpp
21
+ // Typical task usage in ActivateAbility:
22
+ void UMyAbility::ActivateAbility(...)
23
+ {
24
+ if (!CommitAbility(Handle, ActorInfo, ActivationInfo))
25
+ {
26
+ EndAbility(Handle, ActorInfo, ActivationInfo, true, true);
27
+ return;
28
+ }
29
+
30
+ UAbilityTask_PlayMontageAndWait* Task =
31
+ UAbilityTask_PlayMontageAndWait::CreatePlayMontageAndWaitProxy(
32
+ this, NAME_None, AttackMontage, 1.f);
33
+
34
+ Task->OnCompleted.AddDynamic(this, &UMyAbility::OnMontageCompleted);
35
+ Task->OnInterrupted.AddDynamic(this, &UMyAbility::OnMontageInterrupted);
36
+ Task->OnCancelled.AddDynamic(this, &UMyAbility::OnMontageCancelled);
37
+ Task->ReadyForActivation();
38
+ }
39
+
40
+ void UMyAbility::OnMontageCompleted()
41
+ {
42
+ EndAbility(CurrentSpecHandle, CurrentActorInfo, CurrentActivationInfo, true, false);
43
+ }
44
+
45
+ void UMyAbility::OnMontageInterrupted()
46
+ {
47
+ EndAbility(CurrentSpecHandle, CurrentActorInfo, CurrentActivationInfo, true, true);
48
+ }
49
+ ```
50
+
51
+ ---
52
+
53
+ ## UAbilityTask_PlayMontageAndWait
54
+
55
+ Plays an `AnimMontage` on the avatar actor's skeletal mesh and waits for it to finish.
56
+
57
+ ```cpp
58
+ #include "Abilities/Tasks/AbilityTask_PlayMontageAndWait.h"
59
+
60
+ UAbilityTask_PlayMontageAndWait* Task =
61
+ UAbilityTask_PlayMontageAndWait::CreatePlayMontageAndWaitProxy(
62
+ this, // OwningAbility
63
+ NAME_None, // Task instance name (NAME_None = auto)
64
+ AttackMontage, // UAnimMontage* to play
65
+ 1.f, // Rate
66
+ NAME_None, // StartSection (NAME_None = start from beginning)
67
+ false, // bStopWhenAbilityEnds
68
+ 1.f); // AnimRootMotionTranslationScale
69
+
70
+ Task->OnCompleted.AddDynamic(this, &UMyAbility::OnMontageCompleted);
71
+ Task->OnBlendOut.AddDynamic(this, &UMyAbility::OnMontageBlendOut);
72
+ Task->OnInterrupted.AddDynamic(this, &UMyAbility::OnMontageInterrupted);
73
+ Task->OnCancelled.AddDynamic(this, &UMyAbility::OnMontageCancelled);
74
+ Task->ReadyForActivation();
75
+ ```
76
+
77
+ Delegates:
78
+ - `OnCompleted`: Montage finished playing
79
+ - `OnBlendOut`: Montage started blending out
80
+ - `OnInterrupted`: Montage was interrupted by another montage
81
+ - `OnCancelled`: Task was cancelled (EndAbility called while running)
82
+
83
+ ---
84
+
85
+ ## UAbilityTask_WaitGameplayEvent
86
+
87
+ Waits for a `FGameplayEventData` to be sent via `HandleGameplayEvent` on the ASC.
88
+ Common use: waiting for an animation notify to trigger (e.g., `Event.Montage.Attack.Hit`).
89
+
90
+ ```cpp
91
+ #include "Abilities/Tasks/AbilityTask_WaitGameplayEvent.h"
92
+
93
+ FGameplayTag EventTag = FGameplayTag::RequestGameplayTag("Event.Montage.Attack.Hit");
94
+
95
+ UAbilityTask_WaitGameplayEvent* Task =
96
+ UAbilityTask_WaitGameplayEvent::WaitGameplayEvent(
97
+ this,
98
+ EventTag,
99
+ nullptr, // OptionalExternalTarget (null = use self ASC)
100
+ true, // TriggerOnce (false = keep listening)
101
+ true); // OnlyMatchExact
102
+
103
+ Task->EventReceived.AddDynamic(this, &UMyAbility::OnAttackHitEvent);
104
+ Task->ReadyForActivation();
105
+ ```
106
+
107
+ Sending the event (e.g., from an `AnimNotify`):
108
+ ```cpp
109
+ // In AnimNotify or character code:
110
+ FGameplayEventData EventData;
111
+ EventData.Instigator = GetOwner();
112
+ UAbilitySystemBlueprintLibrary::SendGameplayEventToActor(
113
+ GetOwner(),
114
+ FGameplayTag::RequestGameplayTag("Event.Montage.Attack.Hit"),
115
+ EventData);
116
+ ```
117
+
118
+ Delegate: `EventReceived(FGameplayEventData Payload)`
119
+
120
+ ---
121
+
122
+ ## UAbilityTask_WaitDelay
123
+
124
+ Waits for a fixed duration and then fires a callback. Equivalent to a GAS-aware timer.
125
+
126
+ ```cpp
127
+ #include "Abilities/Tasks/AbilityTask_WaitDelay.h"
128
+
129
+ UAbilityTask_WaitDelay* Task =
130
+ UAbilityTask_WaitDelay::WaitDelay(this, 2.f); // 2 second delay
131
+
132
+ Task->OnFinish.AddDynamic(this, &UMyAbility::OnDelayFinished);
133
+ Task->ReadyForActivation();
134
+ ```
135
+
136
+ Delegate: `OnFinish()`
137
+
138
+ ---
139
+
140
+ ## UAbilityTask_WaitTargetData
141
+
142
+ Spawns a `AGameplayAbilityTargetActor` to gather targeting information (line trace,
143
+ sphere trace, actor selection, etc.) and returns `FGameplayAbilityTargetDataHandle`.
144
+
145
+ ```cpp
146
+ #include "Abilities/Tasks/AbilityTask_WaitTargetData.h"
147
+ #include "Abilities/GameplayAbilityTargetActor_SingleLineTrace.h"
148
+
149
+ UAbilityTask_WaitTargetData* Task =
150
+ UAbilityTask_WaitTargetData::WaitTargetData(
151
+ this,
152
+ NAME_None,
153
+ EGameplayTargetingConfirmation::Instant, // Instant, UserConfirmed, Custom, etc.
154
+ AGameplayAbilityTargetActor_SingleLineTrace::StaticClass());
155
+
156
+ Task->ValidData.AddDynamic(this, &UMyAbility::OnValidTargetData);
157
+ Task->Cancelled.AddDynamic(this, &UMyAbility::OnTargetCancelled);
158
+ Task->ReadyForActivation();
159
+ ```
160
+
161
+ Targeting confirmation modes:
162
+ | Mode | Behavior |
163
+ |------|----------|
164
+ | `Instant` | Confirms immediately upon spawn |
165
+ | `UserConfirmed` | Waits for `SendGameplayEvent` with confirm tag |
166
+ | `Custom` | Custom confirmation logic in the TargetActor |
167
+ | `CustomMulti` | Confirms multiple targets over time |
168
+
169
+ Delegate `ValidData(FGameplayAbilityTargetDataHandle Data)`:
170
+ ```cpp
171
+ void UMyAbility::OnValidTargetData(const FGameplayAbilityTargetDataHandle& Data)
172
+ {
173
+ // Apply effect to targets
174
+ FGameplayEffectSpecHandle SpecHandle = MakeOutgoingGameplayEffectSpec(DamageEffect, Level);
175
+ ApplyGameplayEffectSpecToTarget(CurrentSpecHandle, CurrentActorInfo,
176
+ CurrentActivationInfo, SpecHandle, Data);
177
+ EndAbility(CurrentSpecHandle, CurrentActorInfo, CurrentActivationInfo, true, false);
178
+ }
179
+ ```
180
+
181
+ ---
182
+
183
+ ## UAbilityTask_WaitAttributeChange
184
+
185
+ Waits for an attribute to cross a threshold or change at all.
186
+
187
+ ```cpp
188
+ #include "Abilities/Tasks/AbilityTask_WaitAttributeChange.h"
189
+
190
+ UAbilityTask_WaitAttributeChange* Task =
191
+ UAbilityTask_WaitAttributeChange::WaitForAttributeChange(
192
+ this,
193
+ UMyHealthSet::GetHealthAttribute(),
194
+ FGameplayTag(), // WithTag: optional, only trigger if ASC has this tag
195
+ FGameplayTag(), // WithoutTag: only trigger if ASC lacks this tag
196
+ true); // TriggerOnce
197
+
198
+ Task->OnChange.AddDynamic(this, &UMyAbility::OnHealthChanged);
199
+ Task->ReadyForActivation();
200
+ ```
201
+
202
+ Delegate: `OnChange()`
203
+
204
+ For threshold-based (separate class — `UAbilityTask_WaitAttributeChangeThreshold`):
205
+ ```cpp
206
+ #include "Abilities/Tasks/AbilityTask_WaitAttributeChangeThreshold.h"
207
+
208
+ UAbilityTask_WaitAttributeChangeThreshold* Task =
209
+ UAbilityTask_WaitAttributeChangeThreshold::WaitForAttributeChangeThreshold(
210
+ this,
211
+ UMyHealthSet::GetHealthAttribute(),
212
+ EWaitAttributeChangeComparison::LessThan,
213
+ 0.3f, // Compare against: below 30%
214
+ false, // bTriggerOnce
215
+ nullptr);
216
+
217
+ Task->OnChange.AddDynamic(this, &UMyAbility::OnHealthBelowThreshold);
218
+ Task->ReadyForActivation();
219
+ ```
220
+
221
+ Delegate: `OnChange(bool bMatchesComparison, float CurrentValue)`
222
+
223
+ ---
224
+
225
+ ## UAbilityTask_WaitGameplayEffectApplied
226
+
227
+ Fires when a GameplayEffect matching specified tag requirements is applied to a target.
228
+
229
+ ```cpp
230
+ #include "Abilities/Tasks/AbilityTask_WaitGameplayEffectApplied.h"
231
+
232
+ FGameplayTargetDataFilterHandle FilterHandle;
233
+ FGameplayTagRequirements SourceTagReqs;
234
+ FGameplayTagRequirements TargetTagReqs;
235
+ FGameplayTagRequirements AssetTagReqs; // Tags the GE asset itself must have
236
+ FGameplayTagRequirements GrantedTagReqs; // Tags the GE grants to the target
237
+
238
+ UAbilityTask_WaitGameplayEffectApplied_Self* Task =
239
+ UAbilityTask_WaitGameplayEffectApplied_Self::WaitGameplayEffectAppliedToSelf(
240
+ this,
241
+ FilterHandle,
242
+ SourceTagReqs,
243
+ TargetTagReqs,
244
+ AssetTagReqs,
245
+ GrantedTagReqs,
246
+ false /*TriggerOnce*/,
247
+ nullptr /*OptionalExternalOwner*/,
248
+ false /*ListenForPeriodicEffect*/);
249
+
250
+ Task->OnApplied.AddDynamic(this, &UMyAbility::OnEffectApplied);
251
+ Task->ReadyForActivation();
252
+ ```
253
+
254
+ ---
255
+
256
+ ## Creating a Custom Ability Task
257
+
258
+ ```cpp
259
+ // MyAbilityTask_WaitInputRelease.h
260
+ #pragma once
261
+ #include "Abilities/Tasks/AbilityTask.h"
262
+ #include "MyAbilityTask_WaitInputRelease.generated.h"
263
+
264
+ DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnInputReleased);
265
+
266
+ UCLASS()
267
+ class UMyAbilityTask_WaitInputRelease : public UAbilityTask
268
+ {
269
+ GENERATED_BODY()
270
+ public:
271
+ // Factory function: always use a static factory, never construct directly
272
+ UFUNCTION(BlueprintCallable, Category = "Ability|Tasks",
273
+ meta = (HidePin = "OwningAbility", DefaultToSelf = "OwningAbility",
274
+ BlueprintInternalUseOnly = "true"))
275
+ static UMyAbilityTask_WaitInputRelease* WaitInputRelease(
276
+ UGameplayAbility* OwningAbility,
277
+ bool bTestAlreadyReleased = false);
278
+
279
+ UPROPERTY(BlueprintAssignable)
280
+ FOnInputReleased OnReleased;
281
+
282
+ virtual void Activate() override;
283
+ virtual void TickTask(float DeltaTime) override;
284
+ virtual void OnDestroy(bool bInOwnerFinished) override;
285
+
286
+ private:
287
+ bool bStartedAlreadyReleased = false;
288
+ };
289
+ ```
290
+
291
+ ```cpp
292
+ // MyAbilityTask_WaitInputRelease.cpp
293
+ #include "MyAbilityTask_WaitInputRelease.h"
294
+ #include "AbilitySystemComponent.h"
295
+
296
+ UMyAbilityTask_WaitInputRelease* UMyAbilityTask_WaitInputRelease::WaitInputRelease(
297
+ UGameplayAbility* OwningAbility,
298
+ bool bTestAlreadyReleased)
299
+ {
300
+ UMyAbilityTask_WaitInputRelease* Task =
301
+ NewAbilityTask<UMyAbilityTask_WaitInputRelease>(OwningAbility);
302
+ Task->bStartedAlreadyReleased = bTestAlreadyReleased;
303
+ return Task;
304
+ }
305
+
306
+ void UMyAbilityTask_WaitInputRelease::Activate()
307
+ {
308
+ // Enable ticking so we can poll input state
309
+ bTickingTask = true;
310
+ }
311
+
312
+ void UMyAbilityTask_WaitInputRelease::TickTask(float DeltaTime)
313
+ {
314
+ // GetAbilitySpecHandle and AbilitySystemComponent come from UAbilityTask base
315
+ if (AbilitySystemComponent.IsValid())
316
+ {
317
+ const FGameplayAbilitySpec* Spec =
318
+ AbilitySystemComponent->FindAbilitySpecFromHandle(GetAbilitySpecHandle());
319
+ if (Spec && !Spec->InputPressed)
320
+ {
321
+ if (ShouldBroadcastAbilityTaskDelegates())
322
+ {
323
+ OnReleased.Broadcast();
324
+ }
325
+ EndTask();
326
+ }
327
+ }
328
+ }
329
+
330
+ void UMyAbilityTask_WaitInputRelease::OnDestroy(bool bInOwnerFinished)
331
+ {
332
+ Super::OnDestroy(bInOwnerFinished);
333
+ }
334
+ ```
335
+
336
+ Usage in an ability:
337
+ ```cpp
338
+ UMyAbilityTask_WaitInputRelease* Task =
339
+ UMyAbilityTask_WaitInputRelease::WaitInputRelease(this);
340
+ Task->OnReleased.AddDynamic(this, &UMyChargeAbility::OnInputReleased);
341
+ Task->ReadyForActivation();
342
+ ```
343
+
344
+ ---
345
+
346
+ ## Task Lifecycle Notes
347
+
348
+ - Tasks are automatically cleaned up when `EndAbility` or `CancelAbility` is called.
349
+ - Call `EndTask()` inside the task when done; do not call `delete`.
350
+ - `ShouldBroadcastAbilityTaskDelegates()` guards against broadcasting after the ability ends.
351
+ - `bTickingTask = true` must be set in `Activate()` to enable `TickTask`. Default is false.
352
+ - `NewAbilityTask<T>()` is the correct factory; never use `NewObject<T>()` for tasks.
353
+
354
+ ---
355
+
356
+ ## Task Execution Flow
357
+
358
+ ```
359
+ ActivateAbility()
360
+ └── Task::WaitXxx() (static factory)
361
+ └── Bind delegates
362
+ └── Task::ReadyForActivation()
363
+ └── Task::Activate() [task starts its internal logic]
364
+ └── (async frames pass)
365
+ └── Event fires → delegate broadcast
366
+ └── Ability callback runs gameplay logic
367
+ └── EndAbility() called
368
+ └── Task::OnDestroy() cleanup
369
+ ```
370
+
371
+ ---
372
+
373
+ ## Common Task Mistakes
374
+
375
+ **Not calling ReadyForActivation:** The task is created but never starts. Always call this after
376
+ binding delegates.
377
+
378
+ **Binding delegates after ReadyForActivation:** Some tasks fire synchronously in `Activate()`
379
+ (e.g., `WaitDelay` with 0 duration). Bind delegates before calling `ReadyForActivation`.
380
+
381
+ **Calling EndAbility inside a task without ending the task first:** The task will linger.
382
+ Let `EndAbility` clean it up, or call `EndTask()` explicitly if the task should stop without
383
+ ending the ability.
384
+
385
+ **Broadcasting delegates after ability ends:** Always check `ShouldBroadcastAbilityTaskDelegates()`
386
+ before broadcasting inside `TickTask` or callback functions to avoid operating on a cleaned-up
387
+ ability.
388
+
389
+ **Tick-heavy tasks in non-instanced abilities:** If `InstancingPolicy` is `NonInstanced`, the
390
+ CDO runs the ability. Ticking tasks on a CDO can produce shared state issues. Use
391
+ `InstancedPerActor` or `InstancedPerExecution` when using ticking tasks.