ASC学习笔记0026:链接动画实例标签
中文注释:UrealEngine-5.2.1源码-AbilitySystemComponent.h
学习内容:
/** 此组件将在其中播放蒙太奇的链接动画实例。对主动画实例使用 NAME_None。 */UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Skills")FName AffectedAnimInstanceTag;
这是一个 Unreal Engine (UE) C++ 代码片段,定义了一个在技能系统中常用的属性。下面是对该代码的详细解释:
代码分析
各组成部分说明:
-
注释
-
/** 此组件将在其中播放蒙太奇的链接动画实例。对主动画实例使用 NAME_None。 */ -
说明这个属性的用途:指定要在哪个动画实例中播放蒙太奇动画
-
提示如果要使用主动画实例,应该设置为
NAME_None
-
-
UPROPERTY 宏
-
BlueprintReadWrite:在蓝图中可读可写 -
EditAnywhere:在编辑器的所有属性窗口中都可编辑 -
Category = "Skills":在编辑器属性面板中归类到 "Skills" 分类下
-
-
变量声明
-
FName AffectedAnimInstanceTag:变量类型为FName,用于存储动画实例的标签
-
功能用途
这个属性通常用于以下场景:
-
多动画实例系统:当角色有多个动画实例时(如主身体动画实例、武器动画实例等)
-
指定目标:确定蒙太奇动画应该在哪个具体的动画实例中播放
-
标签匹配:通过标签来识别和链接到特定的动画实例组件
使用示例
// 在代码中使用
if (AffectedAnimInstanceTag != NAME_None)
{// 查找具有指定标签的动画实例UAnimInstance* TargetAnimInstance = FindAnimInstanceByTag(AffectedAnimInstanceTag);if (TargetAnimInstance){// 在该动画实例中播放蒙太奇TargetAnimInstance->Montage_Play(MyMontage);}
}
else
{// 使用默认的主动画实例GetMainAnimInstance()->Montage_Play(MyMontage);
}
这个设计提供了灵活性,允许开发者在复杂的动画系统中精确控制蒙太奇的播放目标。
在UE项目实践中,AffectedAnimInstanceTag 属性在复杂的动画系统中有着广泛的应用。以下是几个实际项目中的应用场景和用法:
1. 分层动画系统
角色分层动画实例
// 角色拥有多个动画实例
UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
UAnimInstance* BodyAnimInstance;UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
UAnimInstance* UpperBodyAnimInstance;UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
UAnimInstance* FacialAnimInstance;
使用场景:
-
BodyAnimInstance标签:"Body" - 处理移动、跳跃等全身动画 -
UpperBodyAnimInstance标签:"UpperBody" - 处理武器瞄准、射击等上半身动画 -
FacialAnimInstance标签:"Face" - 处理面部表情动画
2. 武器系统应用
不同武器的动画实例分离
// 在角色蓝图中设置
AffectedAnimInstanceTag = FName("UpperBody");// 在武器技能中
UCLASS()
class AWeapon : public AActor
{GENERATED_BODY()public:UPROPERTY(EditAnywhere, BlueprintReadWrite)FName WeaponAnimInstanceTag; // 可设置为 "Weapon_Right" 或 "Weapon_Left"
};
实际用例:
// 双持武器系统
void ACharacter::PlayWeaponMontage(UAnimMontage* Montage, FName TargetTag)
{TArray<UActorComponent*> Comps;GetComponents(UAnimInstance::StaticClass(), Comps);for (UActorComponent* Comp : Comps){if (UAnimInstance* AnimInst = Cast<UAnimInstance>(Comp)){if (AnimInst->ComponentHasTag(TargetTag)){AnimInst->Montage_Play(Montage);break;}}}
}// 使用示例
PlayWeaponMontage(FireMontage, FName("Weapon_Right")); // 右手开火
PlayWeaponMontage(ReloadMontage, FName("UpperBody")); // 上半身换弹
3. 坐骑系统
角色在坐骑上的分层动画
UCLASS()
class AMountedCharacter : public ACharacter
{// 当骑乘坐骑时void OnMounted(){// 坐骑控制移动动画AffectedAnimInstanceTag = FName("MountBody");// 角色上半身控制攻击动画 UpperBodyAnimInstance->SetActive(true);}void OnDismounted(){// 恢复角色完整控制AffectedAnimInstanceTag = NAME_None;}
};
4. 技能系统实现
复杂技能的多层动画播放
UCLASS()
class USkillComponent : public UActorComponent
{
public:UFUNCTION(BlueprintCallable)void PlaySkillMontage(USkillData* SkillData){if (!SkillData) return;// 根据技能类型选择不同的动画实例FName TargetTag = NAME_None;switch (SkillData->SkillType){case ESkillType::FullBody:TargetTag = NAME_None; // 使用主动画实例break;case ESkillType::UpperBody:TargetTag = FName("UpperBody");break;case ESkillType::Weapon:TargetTag = FName("Weapon_Right");break;case ESkillType::Magic:TargetTag = FName("Magic_Hands");break;}PlayMontageOnTargetInstance(SkillData->SkillMontage, TargetTag);}private:void PlayMontageOnTargetInstance(UAnimMontage* Montage, FName InstanceTag){if (InstanceTag == NAME_None){// 使用主动画实例if (UAnimInstance* MainAnimInst = GetOwner()->FindComponentByClass<UAnimInstance>()){MainAnimInst->Montage_Play(Montage);}}else{// 查找特定标签的动画实例TArray<UActorComponent*> AnimInstances;GetOwner()->GetComponents(UAnimInstance::StaticClass(), AnimInstances);for (UActorComponent* Comp : AnimInstances){if (Comp->ComponentHasTag(InstanceTag)){if (UAnimInstance* AnimInst = Cast<UAnimInstance>(Comp)){AnimInst->Montage_Play(Montage);break;}}}}}
};
5. 动画蓝图中的实际配置
在角色蓝图中的设置
// 事件 BeginPlay
-> 创建动画实例 (Class: UpperBodyAnimInstance, Tag: "UpperBody")
-> 创建动画实例 (Class: WeaponAnimInstance, Tag: "Weapon_Right")
-> 创建动画实例 (Class: FacialAnimInstance, Tag: "Face")
技能蓝图中使用
// 播放射击蒙太奇
-> 设置 AffectedAnimInstanceTag = "Weapon_Right"
-> 播放蒙太奇 (Fire_Montage)// 播放受伤表情
-> 设置 AffectedAnimInstanceTag = "Face"
-> 播放蒙太奇 (Pain_Expression_Montage)
6. 性能优化考虑
按需激活动画实例
void AAdvancedCharacter::SetAnimationLayerActive(FName LayerTag, bool bActive)
{TArray<UActorComponent*> AnimInstances;GetComponents(UAnimInstance::StaticClass(), AnimInstances);for (UActorComponent* Comp : AnimInstances){if (Comp->ComponentHasTag(LayerTag)){Comp->SetActive(bActive);break;}}
}// 优化:只在需要时激活特定动画层
void AAdvancedCharacter::StartAiming()
{SetAnimationLayerActive("UpperBody", true);AffectedAnimInstanceTag = "UpperBody";
}void AAdvancedCharacter::StopAiming()
{SetAnimationLayerActive("UpperBody", false);AffectedAnimInstanceTag = NAME_None;
}
实际项目优势
-
模块化设计:不同动画逻辑分离,便于维护
-
性能控制:可以按需激活/禁用动画层
-
团队协作:动画师和程序员可以并行工作在不同动画层
-
扩展性:轻松添加新的动画层而不影响现有系统
-
调试友好:可以单独调试每个动画实例的状态
这种设计在大型项目中特别有用,特别是需要复杂动画交互的ARPG、FPS或动作游戏。
