组件
- 组件 是一种特殊类型的对象,Actor可以将组件作为子对象附加到自身。
- 组件适用于共享相同的行为,例如显示表现、播放声音。
- 举例,用户可控制车辆、飞机和船只。可以通过更改载具Actor所使用的组件来实现载具控制和移动的差异。
- 组件是渲染网格体和图像、实现碰撞和播放音频的唯一方法
- 因此玩家游戏期间在场景中看到或进行交互的一切都是某一类组件的成果。
组件的分类
- Actor组件 (UActorComponent类)可用于实现一些抽象行为,例如移动、物品栏、属性管理以及其他非物理概念。
- Actor组件没有变换(Transform)属性,这意味着它们在场景中没有物理位置或旋转。
- 场景组件 (USceneComponent类,UActorComponent的子类)支持基于位置相关的行为,并且此类行为不需要表现几何体。
- 场景组件包括弹簧臂、摄像机、物理力和约束(非物理对象)以及音频。
- 图元组件 (UPrimitiveComponent类,USceneComponent的子类)是一种能够显示几何体的场景组件,通常用于渲染视觉元素,或用于与物理对象发生碰撞或重叠。
- 图元组件包括静态或骨骼网格体、Sprite、公告板和粒子系统以及盒体、胶囊体和球体碰撞体积。
组件的更新
- 组件能够以类似于Actor的方法逐帧更新: TickComponent函数
- PrimaryComponentTick.bCanEverTick 设置为 true 来启用tick。默认False
- 必须调用 PrimaryComponentTick.SetTickFunctionEnable(true)
image.png
UActorComponent 组件基类
- 所有组件的基类,继承 public UObject
- PS: 前缀U:继承自UObject
- 主要的类:Actor组件、Scene组件 和 Primitive组件。
- 适用于抽象行为,例如移动、物品栏或属性管理,以及其他非物理概念。
- Actor组件没有变换,即它们在场景中不存在任何物理位置或旋转。
- 主要的函数有: Activate,RegisterComponent,BeginPlay等虚函数
Actor 和 UActorComponent 的关系
- Actor 管理组件: 增删改查等操作
- TSet<TObjectPtr<UActorComponent>> OwnedComponents:Actor拥有的所有组件
- RootComponent: 根节点
- 三个便捷数组:ReplicatedComponents,BlueprintCreatedComponents,InstanceComponents
- UActorComponent 则有mutable AActor* OwnerPrivate; 关联Actor
- 其他联系: 位置,联网同步,初始化,销毁,Tick等
- 功能小,不复杂 写在Actor中
- 功能适中:比如 背包,武器等相对独立,就写组件挂角色上
继承UActorComponent 的子组件类
- UInputComponent: 输入组件:定义如何处理输入数据的组件。
- UMovementComponent: 移动组件:用于管理和控制物体的移动行为。
- USceneComponent:场景组件:存在于场景中特定物理位置处的Actor组件.
- UPawnSensingComponent:快速帮助我们构建Actor的感官(视觉和听觉,在编写AI时非常有用)
- UPawnNoiseEmitterComponent:用于在游戏中模拟角色或对象发出的噪音信号。
USceneComponent
USceneComponent组件类
- 场景组件是指存在于场景中特定物理位置处的Actor组件。
- Actor将单个场景组件指定为"根",意味着Actor的场景位置、旋转和缩放都根据此组件来绘制。
- 包括弹簧臂、摄像机、物理力和约束(但不包括物理对象),甚至音频。
- 只有场景组件(及其子类)可以彼此附加,因为需要变换来描述子项和父组件之间的空间关系。
UPrimitiveComponents组件类(继承USceneComponent)
- 拥有几何表示的场景组件,通常用于渲染视觉元素或与物理对象发生碰撞或重叠。
- 包括静态或骨架网格体、Sprite或公告板、粒子系统以及盒体、胶囊体和球体碰撞体积。
- 继承SceneComponents 主要子类:
- 1 ShapeComponents:生成用于碰撞检测但不渲染的几何体
- 2 StaticMeshComponent:包含渲染的预构建几何体,但也可以用于碰撞检测。
- 3 SkeletalMeshComponent:包含渲染的预构建几何体,但也可以用于碰撞检测。
UInputComponent组件类
- 它使Actor能够绑定各种形式的输入事件来委托函数。
- 输入组件从PlayerController管理的堆栈中处理,并由PlayerInput处理。
- 可以将InputComponent附加到想要接收输入的参与者上。
UMovementComponent组件类
- 提供了一系列方法和属性,用于处理物体的位置、旋转和速度等相关操作
- 可以应用于各种类型的物体,如角色、车辆、道具等。
- 控制移动速度, 处理位置和旋转,碰撞检测和响应,物理模拟,导航和路径移动.
- 实现物体的移动和运动行为,无论是基于玩家输入、AI控制还是其他因素。
SensingComponent组件类
- 封装了一个Actor的感官(即视觉和听觉)设置和功能
- 允许Actor看到/听到世界中的棋子。
PawnNoiseEmitterComponent 组件类
- PawnNoiseEmitterComponent 用于侦听 Pawn 的噪声事件数据。
- 此组件存在于 Pawn 或其控制器上。由SensingComponents使用
- 函数: MakeNoise, GetLastNoiseVolume, GetLastNoiseTime
示例代码
- 实现了一个通过随时修改绑定Actor,达到上下浮动效果的组件
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class UMySceneComponent : public USceneComponent
{
GENERATED_BODY()
public:
UMySceneComponent();
protected:
// Called when the game starts
virtual void BeginPlay() override;
public:
// Called every frame
virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
// 原始Z点
UPROPERTY(VisibleAnywhere, Category = "Floating")
float OriginalZ;
// 当前方向
UPROPERTY(VisibleAnywhere, Category = "Floating")
float CurDirection;
};
// Called when the game starts
void UMySceneComponent::BeginPlay()
{
Super::BeginPlay();
// 获取组件所属的Actor
AActor* OwnerActor = GetOwner();
if (OwnerActor)
{
// 获取当前Actor的位置
FVector CurrentLocation = OwnerActor->GetActorLocation();
// 设置递增或递减方向
OriginalZ = CurrentLocation.Z;
}
}
// Called every frame
void UMySceneComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
// 获取组件所属的Actor
AActor* OwnerActor = GetOwner();
if (OwnerActor)
{
// 获取当前Actor的位置
FVector CurrentLocation = OwnerActor->GetActorLocation();
float NewZ;
// 设置递增或递减方向
float MaxFloatingValue = 200.0f;
if (CurrentLocation.Z > OriginalZ + MaxFloatingValue)
{
CurDirection = -1.0f;
NewZ = OriginalZ + MaxFloatingValue - 1.0f;
UE_LOG(LogTemp, Warning, TEXT("> CurrentLocation.Z = %f"), CurrentLocation.Z);
}
else if (CurrentLocation.Z < OriginalZ)
{
CurDirection = 1.0f;
NewZ = OriginalZ + 1.0f;
UE_LOG(LogTemp, Warning, TEXT("< CurrentLocation.Z = %f"), CurrentLocation.Z);
}
else
{
// 计算新的Z轴位置
NewZ = CurrentLocation.Z + 100.0f * DeltaTime * CurDirection;
}
// 设置Actor的新位置
OwnerActor->SetActorLocation(FVector(CurrentLocation.X, CurrentLocation.Y, NewZ));
}
}
// 自定义组件
UPROPERTY(VisibleAnywhere, Category = "Switch Components")
class UMySceneComponent* MySceneComponent1;
AMyActor::AMyActor()
{
// 添加自定义组件
MySceneComponent1 = CreateDefaultSubobject<UMySceneComponent>(TEXT("MySceneComponent1"));
MySceneComponent1->SetupAttachment(RootComponent);
}
网友评论