在UE中,Tag用于给对象添加一个名称标记,之后可以通过标签来判断对象属于哪一类。
一、Actor Tag
用于给整个Actor添加标签。
AActor内部已经定义:
TArray<FName> Tags;
不需要自己重新声明 Tags。官方将它描述为用于对 Actor 进行分组和分类的 FName 数组。
1.在蓝图细节面板中添加Actor Tag
Details
→ Actor
→ Tags
2.在cpp中添加Actor Tag
一般构造函数中添加:
Tags.Add(TEXT("Interactable"));
不过更推荐用AddUnique():
Tags.AddUnique(TEXT("Interactable"));
前者会添加重名标签,后者不会。
3.检查Actor是否拥有Tag
ActorHasTag()
返回布尔值,例:
检查自身:
if (ActorHasTag(TEXT("Interactable"))) { UE_LOG(LogTemp, Warning, TEXT("当前 Actor 可以交互")); }检查其他对象:
void AMyActor::CheckActor(AActor* OtherActor) { if (OtherActor && OtherActor->ActorHasTag(TEXT("Enemy"))) { UE_LOG(LogTemp, Warning, TEXT("发现敌人")); } }ActorHasTag() 会检查该 Actor 的 Tags 数组中是否包含指定的 FName。
4.在碰撞事件中检查Tag
例如角色碰到不同物体时,根据 Tag 执行不同逻辑:
void AMyActor::OnBeginOverlap( UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult) { if (!OtherActor) { return; } if (OtherActor->ActorHasTag(TEXT("Enemy"))) { UE_LOG(LogTemp, Warning, TEXT("碰到了敌人")); } else if (OtherActor->ActorHasTag(TEXT("Pickup"))) { UE_LOG(LogTemp, Warning, TEXT("碰到了可拾取物")); } }5.在射线检测中检查Tag
FHitResult HitResult; bool bHit = GetWorld()->LineTraceSingleByChannel( HitResult, Start, End, ECC_Visibility ); if (bHit) { AActor* HitActor = HitResult.GetActor(); if (HitActor && HitActor->ActorHasTag(TEXT("Interactable"))) { UE_LOG( LogTemp, Warning, TEXT("射线检测到可交互物体:%s"), *HitActor->GetName() ); } }6.运行时添加和删除Tag
OtherActor->Tags.AddUnique(TEXT("Selected"));
OtherActor->Tags.Remove(TEXT("Selected"));
OtherActor->Tags.Empty();
7.查找所有拥有某个Tag的Actor
#include "Kismet/GameplayStatics.h" TArray<AActor*> EnemyActors; UGameplayStatics::GetAllActorsWithTag( GetWorld(), TEXT("Enemy"), EnemyActors ); for (AActor* EnemyActor : EnemyActors) { if (EnemyActor) { UE_LOG( LogTemp, Warning, TEXT("找到敌人:%s"), *EnemyActor->GetName() ); } }注意头文件;该操作属于较慢操作,不应该放在Tick()中没帧调用。
二、ComponentTag
一个Actor中通常包括多个组件:
Actor
├── BoxCollision
├── BodyMesh
├── HeadMesh
└── Camera
UActorComponent 自带:
TArray<FName> ComponentTags;
1.给组件添加Tag
AMyActor::AMyActor() { MyMesh = CreateDefaultSubobject<UStaticMeshComponent>( TEXT("MyMesh") ); SetRootComponent(MyMesh); MyMesh->ComponentTags.AddUnique(TEXT("Body")); }2.检查组件Tag
if (MyMesh->ComponentHasTag(TEXT("Body"))) { UE_LOG(LogTemp, Warning, TEXT("这个组件是身体网格")); }3.射线检测判断命中组件
HeadMesh->ComponentTags.AddUnique(TEXT("Head")); BodyMesh->ComponentTags.AddUnique(TEXT("Body")); LegMesh->ComponentTags.AddUnique(TEXT("Leg")); if (bHit) { AActor* HitActor = HitResult.GetActor(); UPrimitiveComponent* HitComponent = HitResult.GetComponent(); if (HitActor && HitActor->ActorHasTag(TEXT("Robot"))) { UE_LOG(LogTemp, Warning, TEXT("命中了机器人")); } if (HitComponent) { if (HitComponent->ComponentHasTag(TEXT("Head"))) { UE_LOG(LogTemp, Warning, TEXT("命中了机器人的头部")); } else if (HitComponent->ComponentHasTag(TEXT("Body"))) { UE_LOG(LogTemp, Warning, TEXT("命中了机器人的身体")); } else if (HitComponent->ComponentHasTag(TEXT("Leg"))) { UE_LOG(LogTemp, Warning, TEXT("命中了机器人的腿部")); } } }4.根据Tag查找Actor内的组件
FindComponentByTag()
UActorComponent* FoundComponent = FindComponentByTag( UStaticMeshComponent::StaticClass(), TEXT("Head") );三、Gameplay Tags
UE 官方将 Gameplay Tag 定义为一种用户自定义的、具有层级结构的概念标签,可以像布尔值或标志位一样驱动游戏逻辑。