claude-code-arcane 2.3.0 → 2.4.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.
- package/CHANGELOG.md +15 -0
- package/README.md +54 -6
- package/agents/game/ue-blueprint-specialist.md +125 -0
- package/agents/game/ue-gas-specialist.md +133 -0
- package/agents/game/ue-umg-specialist.md +131 -0
- package/dist/cli.js +5 -0
- package/docs/SKILLS-CATALOG.md +42 -3
- package/docs/USER-GUIDE.md +2 -2
- package/hooks/detect-unreal.sh +90 -0
- package/package.json +1 -1
- package/profiles/unreal-dev.yaml +97 -0
- package/rules/gamedev/unreal-code.md +125 -0
- package/skills/install-mcp/SKILL.md +135 -46
- package/skills/install-mcp/references/unreal-operations.md +55 -0
- package/skills/ue-actor-component-architecture/SKILL.md +509 -0
- package/skills/ue-actor-component-architecture/references/actor-lifecycle.md +301 -0
- package/skills/ue-actor-component-architecture/references/component-types.md +592 -0
- package/skills/ue-ai-navigation/SKILL.md +526 -0
- package/skills/ue-ai-navigation/references/behavior-tree-patterns.md +392 -0
- package/skills/ue-ai-navigation/references/behavior-tree-workflow.md +107 -0
- package/skills/ue-ai-navigation/references/custom-bttask.md +104 -0
- package/skills/ue-ai-navigation/references/eqs-reference.md +423 -0
- package/skills/ue-animation-system/SKILL.md +521 -0
- package/skills/ue-animation-system/references/anim-notify-reference.md +486 -0
- package/skills/ue-animation-system/references/locomotion-setup.md +550 -0
- package/skills/ue-async-threading/SKILL.md +433 -0
- package/skills/ue-async-threading/references/thread-safety-guide.md +213 -0
- package/skills/ue-async-threading/references/threading-patterns.md +345 -0
- package/skills/ue-audio-system/SKILL.md +527 -0
- package/skills/ue-audio-system/references/audio-setup-patterns.md +700 -0
- package/skills/ue-blueprints/SKILL.md +134 -0
- package/skills/ue-blueprints/references/communication.md +82 -0
- package/skills/ue-character-movement/SKILL.md +475 -0
- package/skills/ue-character-movement/references/cmc-extension-patterns.md +335 -0
- package/skills/ue-character-movement/references/movement-pipeline.md +189 -0
- package/skills/ue-cpp-foundations/SKILL.md +533 -0
- package/skills/ue-cpp-foundations/references/components-and-gc.md +107 -0
- package/skills/ue-cpp-foundations/references/container-patterns.md +544 -0
- package/skills/ue-cpp-foundations/references/delegate-patterns.md +497 -0
- package/skills/ue-cpp-foundations/references/gameplay-classes-cpp.md +136 -0
- package/skills/ue-cpp-foundations/references/property-specifiers.md +306 -0
- package/skills/ue-data-assets-tables/SKILL.md +527 -0
- package/skills/ue-data-assets-tables/references/asset-loading-patterns.md +306 -0
- package/skills/ue-data-assets-tables/references/data-driven-design.md +378 -0
- package/skills/ue-editor-tools/SKILL.md +523 -0
- package/skills/ue-editor-tools/references/detail-customization-patterns.md +395 -0
- package/skills/ue-editor-tools/references/editor-module-setup.md +480 -0
- package/skills/ue-game-features/SKILL.md +477 -0
- package/skills/ue-game-features/references/experience-system.md +222 -0
- package/skills/ue-game-features/references/game-feature-patterns.md +308 -0
- package/skills/ue-gameplay-abilities/SKILL.md +518 -0
- package/skills/ue-gameplay-abilities/references/ability-task-reference.md +391 -0
- package/skills/ue-gameplay-abilities/references/gameplay-effect-reference.md +397 -0
- package/skills/ue-gameplay-abilities/references/gas-setup-patterns.md +369 -0
- package/skills/ue-gameplay-framework/SKILL.md +466 -0
- package/skills/ue-gameplay-framework/references/framework-class-map.md +243 -0
- package/skills/ue-input-system/SKILL.md +394 -0
- package/skills/ue-input-system/references/cpp-setup.md +131 -0
- package/skills/ue-input-system/references/enhanced-input-workflow.md +117 -0
- package/skills/ue-input-system/references/input-action-reference.md +731 -0
- package/skills/ue-mass-entity/SKILL.md +476 -0
- package/skills/ue-mass-entity/references/mass-entity-patterns.md +319 -0
- package/skills/ue-mass-entity/references/mass-fragment-reference.md +119 -0
- package/skills/ue-materials-rendering/SKILL.md +526 -0
- package/skills/ue-materials-rendering/references/material-parameter-reference.md +216 -0
- package/skills/ue-materials-rendering/references/post-process-settings.md +383 -0
- package/skills/ue-module-build-system/SKILL.md +487 -0
- package/skills/ue-module-build-system/references/build-cs-reference.md +418 -0
- package/skills/ue-module-build-system/references/common-build-errors.md +381 -0
- package/skills/ue-naming-conventions/SKILL.md +142 -0
- package/skills/ue-naming-conventions/references/asset-name-modifiers.md +233 -0
- package/skills/ue-naming-conventions/references/content-structure.md +83 -0
- package/skills/ue-networking-replication/SKILL.md +452 -0
- package/skills/ue-networking-replication/references/replication-patterns.md +526 -0
- package/skills/ue-networking-replication/references/rpc-decision-guide.md +393 -0
- package/skills/ue-niagara-effects/SKILL.md +531 -0
- package/skills/ue-niagara-effects/references/niagara-data-interfaces.md +491 -0
- package/skills/ue-niagara-effects/references/niagara-parameter-types.md +153 -0
- package/skills/ue-niagara-effects/references/niagara-workflow.md +115 -0
- package/skills/ue-packaging/SKILL.md +116 -0
- package/skills/ue-physics-collision/SKILL.md +423 -0
- package/skills/ue-physics-collision/references/collision-channel-setup.md +218 -0
- package/skills/ue-physics-collision/references/trace-patterns.md +499 -0
- package/skills/ue-procedural-generation/SKILL.md +505 -0
- package/skills/ue-procedural-generation/references/pcg-node-reference.md +381 -0
- package/skills/ue-procedural-generation/references/procedural-mesh-patterns.md +940 -0
- package/skills/ue-project-context/SKILL.md +305 -0
- package/skills/ue-sequencer-cinematics/SKILL.md +506 -0
- package/skills/ue-sequencer-cinematics/references/sequencer-patterns.md +629 -0
- package/skills/ue-serialization-savegames/SKILL.md +524 -0
- package/skills/ue-serialization-savegames/references/save-system-architecture.md +705 -0
- package/skills/ue-state-trees/SKILL.md +489 -0
- package/skills/ue-state-trees/references/state-tree-mass-integration.md +184 -0
- package/skills/ue-state-trees/references/state-tree-patterns.md +321 -0
- package/skills/ue-testing-debugging/SKILL.md +520 -0
- package/skills/ue-testing-debugging/references/automation-test-patterns.md +387 -0
- package/skills/ue-testing-debugging/references/profiling-commands.md +357 -0
- package/skills/ue-ui-umg-slate/SKILL.md +431 -0
- package/skills/ue-ui-umg-slate/references/common-ui-setup.md +484 -0
- package/skills/ue-ui-umg-slate/references/widget-types.md +487 -0
- package/skills/ue-world-level-streaming/SKILL.md +518 -0
- package/skills/ue-world-level-streaming/references/streaming-patterns.md +414 -0
- package/templates/gamedev/unreal-project-context.md +107 -0
|
@@ -0,0 +1,486 @@
|
|
|
1
|
+
# Anim Notify Reference
|
|
2
|
+
|
|
3
|
+
Source headers:
|
|
4
|
+
- `Engine/Source/Runtime/Engine/Classes/Animation/AnimNotifies/AnimNotify.h`
|
|
5
|
+
- `Engine/Source/Runtime/Engine/Classes/Animation/AnimNotifies/AnimNotifyState.h`
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Class Hierarchy
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
UObject
|
|
13
|
+
├── UAnimNotify (point-in-time event)
|
|
14
|
+
└── UAnimNotifyState (duration event: Begin / Tick / End)
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### UAnimNotify — Key Virtual Methods
|
|
18
|
+
|
|
19
|
+
```cpp
|
|
20
|
+
// UE5 signature (always override this one; UE4 signature is deprecated)
|
|
21
|
+
virtual void Notify(
|
|
22
|
+
USkeletalMeshComponent* MeshComp,
|
|
23
|
+
UAnimSequenceBase* Animation,
|
|
24
|
+
const FAnimNotifyEventReference& EventReference);
|
|
25
|
+
|
|
26
|
+
// Fires synchronously during Montage_Advance (only when bIsNativeBranchingPoint = true)
|
|
27
|
+
virtual void BranchingPointNotify(FBranchingPointNotifyPayload& BranchingPointPayload);
|
|
28
|
+
|
|
29
|
+
// Display name shown in the editor timeline
|
|
30
|
+
virtual FString GetNotifyName_Implementation() const;
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### UAnimNotifyState — Key Virtual Methods
|
|
34
|
+
|
|
35
|
+
```cpp
|
|
36
|
+
// UE5 signatures
|
|
37
|
+
virtual void NotifyBegin(USkeletalMeshComponent* MeshComp,
|
|
38
|
+
UAnimSequenceBase* Animation, float TotalDuration,
|
|
39
|
+
const FAnimNotifyEventReference& EventReference);
|
|
40
|
+
|
|
41
|
+
virtual void NotifyTick(USkeletalMeshComponent* MeshComp,
|
|
42
|
+
UAnimSequenceBase* Animation, float FrameDeltaTime,
|
|
43
|
+
const FAnimNotifyEventReference& EventReference);
|
|
44
|
+
|
|
45
|
+
virtual void NotifyEnd(USkeletalMeshComponent* MeshComp,
|
|
46
|
+
UAnimSequenceBase* Animation,
|
|
47
|
+
const FAnimNotifyEventReference& EventReference);
|
|
48
|
+
|
|
49
|
+
// Branching point variants (synchronous during Montage_Advance)
|
|
50
|
+
virtual void BranchingPointNotifyBegin(FBranchingPointNotifyPayload& Payload);
|
|
51
|
+
virtual void BranchingPointNotifyTick(FBranchingPointNotifyPayload& Payload, float DeltaTime);
|
|
52
|
+
virtual void BranchingPointNotifyEnd(FBranchingPointNotifyPayload& Payload);
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Built-In Notifies (Engine-Provided)
|
|
58
|
+
|
|
59
|
+
### UAnimNotify_PlaySound
|
|
60
|
+
|
|
61
|
+
**Header**: `AnimNotify_PlaySound.h`
|
|
62
|
+
|
|
63
|
+
Plays a `USoundBase` at a socket location when the notify fires.
|
|
64
|
+
|
|
65
|
+
Key properties:
|
|
66
|
+
```cpp
|
|
67
|
+
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="AnimNotify")
|
|
68
|
+
TObjectPtr<USoundBase> Sound;
|
|
69
|
+
|
|
70
|
+
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="AnimNotify")
|
|
71
|
+
float VolumeMultiplier = 1.f;
|
|
72
|
+
|
|
73
|
+
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="AnimNotify")
|
|
74
|
+
float PitchMultiplier = 1.f;
|
|
75
|
+
|
|
76
|
+
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="AnimNotify")
|
|
77
|
+
uint32 bFollow : 1; // if true, sound component follows the socket
|
|
78
|
+
|
|
79
|
+
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="AnimNotify",
|
|
80
|
+
meta=(EditCondition="bFollow"))
|
|
81
|
+
FName AttachName; // socket or bone to attach to
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Use for: footsteps, impacts, voice barks, weapon sounds.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
### UAnimNotify_PlayParticleEffect
|
|
89
|
+
|
|
90
|
+
**Header**: `AnimNotify_PlayParticleEffect.h`
|
|
91
|
+
|
|
92
|
+
Spawns a `UParticleSystem` at a socket location.
|
|
93
|
+
|
|
94
|
+
Key properties:
|
|
95
|
+
```cpp
|
|
96
|
+
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="AnimNotify")
|
|
97
|
+
TObjectPtr<UParticleSystem> PSTemplate;
|
|
98
|
+
|
|
99
|
+
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="AnimNotify")
|
|
100
|
+
FName SocketName;
|
|
101
|
+
|
|
102
|
+
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="AnimNotify")
|
|
103
|
+
FVector LocationOffset;
|
|
104
|
+
|
|
105
|
+
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="AnimNotify")
|
|
106
|
+
FRotator RotationOffset;
|
|
107
|
+
|
|
108
|
+
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="AnimNotify")
|
|
109
|
+
bool bAttached; // false = spawned at socket, not parented
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Use for: muzzle flashes, hit sparks, ability cast effects.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
### UAnimNotifyState_TimedParticleEffect
|
|
117
|
+
|
|
118
|
+
**Header**: `AnimNotifyState_TimedParticleEffect.h`
|
|
119
|
+
|
|
120
|
+
Activates a looping `UParticleSystem` for the duration of the notify state.
|
|
121
|
+
Deactivates (or destroys) on end.
|
|
122
|
+
|
|
123
|
+
Key properties:
|
|
124
|
+
```cpp
|
|
125
|
+
UPROPERTY(EditAnywhere, Category=ParticleSystem)
|
|
126
|
+
TObjectPtr<UParticleSystem> PSTemplate;
|
|
127
|
+
|
|
128
|
+
UPROPERTY(EditAnywhere, Category=ParticleSystem)
|
|
129
|
+
FName SocketName;
|
|
130
|
+
|
|
131
|
+
UPROPERTY(EditAnywhere, Category=ParticleSystem)
|
|
132
|
+
FVector LocationOffset;
|
|
133
|
+
|
|
134
|
+
UPROPERTY(EditAnywhere, Category=ParticleSystem)
|
|
135
|
+
FRotator RotationOffset;
|
|
136
|
+
|
|
137
|
+
UPROPERTY(EditAnywhere, Category=ParticleSystem,
|
|
138
|
+
meta=(DisplayName="Destroy Immediately"))
|
|
139
|
+
bool bDestroyAtEnd; // false = allow particles to complete their cycle
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Use for: weapon trails, aura effects, charged attack indicators.
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
### UAnimNotifyState_DisableRootMotion
|
|
147
|
+
|
|
148
|
+
**Header**: `AnimNotifyState_DisableRootMotion.h`
|
|
149
|
+
|
|
150
|
+
Suppresses root motion extraction for the duration of the notify state.
|
|
151
|
+
Internally calls `PushDisableRootMotion()` on `FAnimMontageInstance` and
|
|
152
|
+
`PopDisableRootMotion()` at end.
|
|
153
|
+
|
|
154
|
+
Use for: ragdoll transitions, ability phases where motion is physics-driven.
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
### UAnimNotifyState_Trail
|
|
159
|
+
|
|
160
|
+
**Header**: `AnimNotifyState_Trail.h`
|
|
161
|
+
|
|
162
|
+
Spawns and manages a particle trail between two sockets. Used for sword trails,
|
|
163
|
+
cape effects, etc.
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Custom Notify Patterns
|
|
168
|
+
|
|
169
|
+
### Pattern 1 — Footstep with Surface Detection
|
|
170
|
+
|
|
171
|
+
```cpp
|
|
172
|
+
// FootstepNotify.h
|
|
173
|
+
#pragma once
|
|
174
|
+
#include "Animation/AnimNotifies/AnimNotify.h"
|
|
175
|
+
#include "FootstepNotify.generated.h"
|
|
176
|
+
|
|
177
|
+
UCLASS(meta=(DisplayName="Footstep"))
|
|
178
|
+
class MYGAME_API UFootstepNotify : public UAnimNotify
|
|
179
|
+
{
|
|
180
|
+
GENERATED_BODY()
|
|
181
|
+
|
|
182
|
+
public:
|
|
183
|
+
UFootstepNotify()
|
|
184
|
+
{
|
|
185
|
+
bIsNativeBranchingPoint = false; // queued, not synchronous
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
virtual void Notify(
|
|
189
|
+
USkeletalMeshComponent* MeshComp,
|
|
190
|
+
UAnimSequenceBase* Animation,
|
|
191
|
+
const FAnimNotifyEventReference& EventReference) override;
|
|
192
|
+
|
|
193
|
+
virtual FString GetNotifyName_Implementation() const override
|
|
194
|
+
{
|
|
195
|
+
return FString::Printf(TEXT("Footstep_%s"), *FootSocket.ToString());
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Footstep")
|
|
199
|
+
FName FootSocket = FName("foot_l");
|
|
200
|
+
|
|
201
|
+
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Footstep")
|
|
202
|
+
float TraceDistance = 75.f;
|
|
203
|
+
};
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
```cpp
|
|
207
|
+
// FootstepNotify.cpp
|
|
208
|
+
#include "FootstepNotify.h"
|
|
209
|
+
#include "Components/SkeletalMeshComponent.h"
|
|
210
|
+
#include "PhysicalMaterials/PhysicalMaterial.h"
|
|
211
|
+
#include "Kismet/GameplayStatics.h"
|
|
212
|
+
|
|
213
|
+
void UFootstepNotify::Notify(
|
|
214
|
+
USkeletalMeshComponent* MeshComp,
|
|
215
|
+
UAnimSequenceBase* Animation,
|
|
216
|
+
const FAnimNotifyEventReference& EventReference)
|
|
217
|
+
{
|
|
218
|
+
Super::Notify(MeshComp, Animation, EventReference);
|
|
219
|
+
|
|
220
|
+
if (!MeshComp || !MeshComp->GetWorld()) return;
|
|
221
|
+
|
|
222
|
+
const FVector SocketLoc = MeshComp->GetSocketLocation(FootSocket);
|
|
223
|
+
const FVector TraceStart = SocketLoc + FVector(0.f, 0.f, 20.f);
|
|
224
|
+
const FVector TraceEnd = SocketLoc - FVector(0.f, 0.f, TraceDistance);
|
|
225
|
+
|
|
226
|
+
FHitResult Hit;
|
|
227
|
+
FCollisionQueryParams Params(SCENE_QUERY_STAT(FootstepTrace), true);
|
|
228
|
+
Params.AddIgnoredActor(MeshComp->GetOwner());
|
|
229
|
+
Params.bReturnPhysicalMaterial = true;
|
|
230
|
+
|
|
231
|
+
if (MeshComp->GetWorld()->LineTraceSingleByChannel(
|
|
232
|
+
Hit, TraceStart, TraceEnd, ECC_Visibility, Params))
|
|
233
|
+
{
|
|
234
|
+
EPhysicalSurface Surface = UGameplayStatics::GetSurfaceType(Hit);
|
|
235
|
+
// Dispatch footstep event to a surface manager or audio system
|
|
236
|
+
// e.g. UFootstepSubsystem::Get(World)->PlayFootstep(Surface, Hit.ImpactPoint);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
### Pattern 2 — Weapon Collision Window (NotifyState)
|
|
244
|
+
|
|
245
|
+
```cpp
|
|
246
|
+
// WeaponCollisionNotifyState.h
|
|
247
|
+
#pragma once
|
|
248
|
+
#include "Animation/AnimNotifies/AnimNotifyState.h"
|
|
249
|
+
#include "WeaponCollisionNotifyState.generated.h"
|
|
250
|
+
|
|
251
|
+
UCLASS(meta=(DisplayName="Weapon Collision Window"))
|
|
252
|
+
class MYGAME_API UWeaponCollisionNotifyState : public UAnimNotifyState
|
|
253
|
+
{
|
|
254
|
+
GENERATED_BODY()
|
|
255
|
+
|
|
256
|
+
public:
|
|
257
|
+
virtual void NotifyBegin(
|
|
258
|
+
USkeletalMeshComponent* MeshComp,
|
|
259
|
+
UAnimSequenceBase* Animation,
|
|
260
|
+
float TotalDuration,
|
|
261
|
+
const FAnimNotifyEventReference& EventReference) override;
|
|
262
|
+
|
|
263
|
+
virtual void NotifyEnd(
|
|
264
|
+
USkeletalMeshComponent* MeshComp,
|
|
265
|
+
UAnimSequenceBase* Animation,
|
|
266
|
+
const FAnimNotifyEventReference& EventReference) override;
|
|
267
|
+
|
|
268
|
+
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Weapon")
|
|
269
|
+
FName WeaponComponentTag = FName("PrimaryWeapon");
|
|
270
|
+
};
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
```cpp
|
|
274
|
+
// WeaponCollisionNotifyState.cpp
|
|
275
|
+
#include "WeaponCollisionNotifyState.h"
|
|
276
|
+
#include "Components/SkeletalMeshComponent.h"
|
|
277
|
+
#include "GameFramework/Actor.h"
|
|
278
|
+
|
|
279
|
+
void UWeaponCollisionNotifyState::NotifyBegin(
|
|
280
|
+
USkeletalMeshComponent* MeshComp,
|
|
281
|
+
UAnimSequenceBase* Animation,
|
|
282
|
+
float TotalDuration,
|
|
283
|
+
const FAnimNotifyEventReference& EventReference)
|
|
284
|
+
{
|
|
285
|
+
Super::NotifyBegin(MeshComp, Animation, TotalDuration, EventReference);
|
|
286
|
+
|
|
287
|
+
if (!MeshComp) return;
|
|
288
|
+
AActor* Owner = MeshComp->GetOwner();
|
|
289
|
+
if (!Owner) return;
|
|
290
|
+
|
|
291
|
+
// Enable weapon collision via interface or component lookup
|
|
292
|
+
// IWeaponInterface::Execute_EnableCollision(WeaponActor);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
void UWeaponCollisionNotifyState::NotifyEnd(
|
|
296
|
+
USkeletalMeshComponent* MeshComp,
|
|
297
|
+
UAnimSequenceBase* Animation,
|
|
298
|
+
const FAnimNotifyEventReference& EventReference)
|
|
299
|
+
{
|
|
300
|
+
Super::NotifyEnd(MeshComp, Animation, EventReference);
|
|
301
|
+
|
|
302
|
+
if (!MeshComp) return;
|
|
303
|
+
AActor* Owner = MeshComp->GetOwner();
|
|
304
|
+
if (!Owner) return;
|
|
305
|
+
|
|
306
|
+
// Disable weapon collision
|
|
307
|
+
}
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
---
|
|
311
|
+
|
|
312
|
+
### Pattern 3 — BranchingPoint Notify (Synchronous, Montage)
|
|
313
|
+
|
|
314
|
+
Use when you need to jump sections or stop a montage at a precise frame:
|
|
315
|
+
|
|
316
|
+
```cpp
|
|
317
|
+
// ComboBranchNotify.h
|
|
318
|
+
#pragma once
|
|
319
|
+
#include "Animation/AnimNotifies/AnimNotify.h"
|
|
320
|
+
#include "ComboBranchNotify.generated.h"
|
|
321
|
+
|
|
322
|
+
UCLASS(meta=(DisplayName="Combo Branch Point"))
|
|
323
|
+
class MYGAME_API UComboBranchNotify : public UAnimNotify
|
|
324
|
+
{
|
|
325
|
+
GENERATED_BODY()
|
|
326
|
+
|
|
327
|
+
public:
|
|
328
|
+
UComboBranchNotify()
|
|
329
|
+
{
|
|
330
|
+
// Marks this notify as always synchronous on montages
|
|
331
|
+
bIsNativeBranchingPoint = true;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
virtual void BranchingPointNotify(
|
|
335
|
+
FBranchingPointNotifyPayload& BranchingPointPayload) override;
|
|
336
|
+
|
|
337
|
+
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Combo")
|
|
338
|
+
FName NextSection = FName("ComboEnd");
|
|
339
|
+
};
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
```cpp
|
|
343
|
+
// ComboBranchNotify.cpp
|
|
344
|
+
#include "ComboBranchNotify.h"
|
|
345
|
+
#include "Animation/AnimMontage.h"
|
|
346
|
+
#include "Animation/AnimInstance.h"
|
|
347
|
+
#include "Components/SkeletalMeshComponent.h"
|
|
348
|
+
|
|
349
|
+
void UComboBranchNotify::BranchingPointNotify(
|
|
350
|
+
FBranchingPointNotifyPayload& Payload)
|
|
351
|
+
{
|
|
352
|
+
Super::BranchingPointNotify(Payload);
|
|
353
|
+
|
|
354
|
+
if (!Payload.SkelMeshComponent) return;
|
|
355
|
+
|
|
356
|
+
UAnimInstance* AnimInst =
|
|
357
|
+
Payload.SkelMeshComponent->GetAnimInstance();
|
|
358
|
+
if (!AnimInst) return;
|
|
359
|
+
|
|
360
|
+
// Redirect the montage timeline to a different section synchronously
|
|
361
|
+
AnimInst->Montage_JumpToSection(NextSection);
|
|
362
|
+
}
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
---
|
|
366
|
+
|
|
367
|
+
### Pattern 4 — Named Notify + AnimInstance Delegate
|
|
368
|
+
|
|
369
|
+
For gameplay events (enabling abilities, triggering GAS effects) tied to
|
|
370
|
+
animation timing, use a **PlayMontageNotify** Blueprint node or the
|
|
371
|
+
`FPlayMontageAnimNotifyDelegate`:
|
|
372
|
+
|
|
373
|
+
```cpp
|
|
374
|
+
// From AnimInstance.h:
|
|
375
|
+
// DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FPlayMontageAnimNotifyDelegate,
|
|
376
|
+
// FName, NotifyName, const FBranchingPointNotifyPayload&, BranchingPointPayload);
|
|
377
|
+
|
|
378
|
+
// Bind in C++ to receive named notify events:
|
|
379
|
+
void UMyAbilityComponent::BindMontageNotifies(UAnimInstance* AnimInst)
|
|
380
|
+
{
|
|
381
|
+
AnimInst->OnPlayMontageNotifyBegin.AddDynamic(
|
|
382
|
+
this, &UMyAbilityComponent::HandleNotifyBegin);
|
|
383
|
+
AnimInst->OnPlayMontageNotifyEnd.AddDynamic(
|
|
384
|
+
this, &UMyAbilityComponent::HandleNotifyEnd);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
void UMyAbilityComponent::HandleNotifyBegin(
|
|
388
|
+
FName NotifyName,
|
|
389
|
+
const FBranchingPointNotifyPayload& Payload)
|
|
390
|
+
{
|
|
391
|
+
if (NotifyName == FName("EnableHitbox"))
|
|
392
|
+
{
|
|
393
|
+
ActivateHitDetection();
|
|
394
|
+
}
|
|
395
|
+
else if (NotifyName == FName("ApplyGameplayEffect"))
|
|
396
|
+
{
|
|
397
|
+
ApplyDamageEffect();
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
void UMyAbilityComponent::HandleNotifyEnd(
|
|
402
|
+
FName NotifyName,
|
|
403
|
+
const FBranchingPointNotifyPayload& Payload)
|
|
404
|
+
{
|
|
405
|
+
if (NotifyName == FName("EnableHitbox"))
|
|
406
|
+
{
|
|
407
|
+
DeactivateHitDetection();
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
---
|
|
413
|
+
|
|
414
|
+
## Tick Type Summary
|
|
415
|
+
|
|
416
|
+
| Tick Type | Synchronous? | Use Case |
|
|
417
|
+
|-----------------|-------------|-----------------------------------------------|
|
|
418
|
+
| Queued | No | VFX, SFX, gameplay events (safe, no re-entry) |
|
|
419
|
+
| BranchingPoint | Yes | Montage section jumps, precise loop control |
|
|
420
|
+
|
|
421
|
+
Set in the montage editor per-notify, or via `bIsNativeBranchingPoint = true`
|
|
422
|
+
in the C++ constructor for native notifies.
|
|
423
|
+
|
|
424
|
+
---
|
|
425
|
+
|
|
426
|
+
## Notify Firing on Linked Instances
|
|
427
|
+
|
|
428
|
+
By default, notifies fire only on the AnimInstance that owns the animation.
|
|
429
|
+
To propagate across linked layers:
|
|
430
|
+
|
|
431
|
+
```cpp
|
|
432
|
+
// Main instance receives notifies from linked layers
|
|
433
|
+
AnimInst->SetReceiveNotifiesFromLinkedInstances(true);
|
|
434
|
+
|
|
435
|
+
// Linked layer propagates its notifies to the main instance
|
|
436
|
+
AnimInst->SetPropagateNotifiesToLinkedInstances(true);
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
Also controllable per-node in the `FAnimNode_LinkedAnimGraph` properties:
|
|
440
|
+
```cpp
|
|
441
|
+
// AnimNode_LinkedAnimGraph.h
|
|
442
|
+
uint8 bReceiveNotifiesFromLinkedInstances : 1;
|
|
443
|
+
uint8 bPropagateNotifiesToLinkedInstances : 1;
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
---
|
|
447
|
+
|
|
448
|
+
## Receiving Montage Notify Events Outside AnimInstance
|
|
449
|
+
|
|
450
|
+
To react to named montage notifies from code outside the `AnimInstance`, bind to the
|
|
451
|
+
`OnPlayMontageNotifyBegin` and `OnPlayMontageNotifyEnd` delegates exposed on
|
|
452
|
+
`UAnimInstance`:
|
|
453
|
+
|
|
454
|
+
```cpp
|
|
455
|
+
// In your owning actor / component — called after obtaining the AnimInstance.
|
|
456
|
+
AnimInst->OnPlayMontageNotifyBegin.AddDynamic(
|
|
457
|
+
this, &AMyCharacter::HandleMontageNotifyBegin);
|
|
458
|
+
|
|
459
|
+
AnimInst->OnPlayMontageNotifyEnd.AddDynamic(
|
|
460
|
+
this, &AMyCharacter::HandleMontageNotifyEnd);
|
|
461
|
+
|
|
462
|
+
// Callback signature (must be UFUNCTION):
|
|
463
|
+
UFUNCTION()
|
|
464
|
+
void HandleMontageNotifyBegin(FName NotifyName,
|
|
465
|
+
const FBranchingPointNotifyPayload& Payload)
|
|
466
|
+
{
|
|
467
|
+
if (NotifyName == FName("WeaponCollisionEnable"))
|
|
468
|
+
{
|
|
469
|
+
EnableWeaponCollision();
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
UFUNCTION()
|
|
474
|
+
void HandleMontageNotifyEnd(FName NotifyName,
|
|
475
|
+
const FBranchingPointNotifyPayload& Payload)
|
|
476
|
+
{
|
|
477
|
+
if (NotifyName == FName("WeaponCollisionEnable"))
|
|
478
|
+
{
|
|
479
|
+
DisableWeaponCollision();
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
These delegates fire for every branching-point or standard notify on any montage
|
|
485
|
+
playing on the instance, so always filter by `NotifyName`. Unbind with
|
|
486
|
+
`RemoveDynamic` when the listener is destroyed.
|