游戏对象与组件
在Unreal Engine中,游戏对象和组件是构建游戏的基础。游戏对象(Actor)是游戏世界中的实体,可以是静态的环境物体、动态的角色、触发器等。组件(Component)则是游戏对象的构建块,每个游戏对象可以包含多个组件,这些组件负责游戏对象的不同方面,例如视觉表现、物理属性、碰撞检测等。
1. 游戏对象(Actor)
游戏对象是Unreal Engine中的基本单元,它们存在于游戏世界中,可以被移动、旋转、缩放等。每个游戏对象都是AActor类的实例。AActor类提供了一些基本的功能,例如位置、旋转和缩放属性,以及生命周期管理方法。
1.1 创建游戏对象
创建游戏对象可以通过继承AActor类来实现。以下是一个简单的例子,创建一个自定义的游戏对象:
// MyActor.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyActor.generated.h"
UCLASS()
class MYGAME_API AMyActor : public AActor
{
GENERATED_BODY()
public:
// 构造函数
AMyActor();
protected:
// 事件当Actor被添加到关卡时调用
virtual void BeginPlay() override;
public:
// 事件每帧调用
virtual void Tick(float DeltaTime) override;
};
// MyActor.cpp
#include "MyActor.h"
#include "Components/StaticMeshComponent.h"
AMyActor::AMyActor()
{
// 设置该Actor是否以固定帧率进行Tick
PrimaryActorTick.bCanEverTick = true;
// 创建一个静态网格组件并添加到Actor
UStaticMeshComponent* MeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("MeshComponent"));
MeshComponent->SetupAttachment(RootComponent);
}
void AMyActor::BeginPlay()
{
Super::BeginPlay();
// 在游戏开始时输出一条消息
UE_LOG(LogTemp, Warning, TEXT("MyActor has begun play!"));
}
void AMyActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
// 每帧移动Actor
FVector NewLocation = GetActorLocation();
NewLocation.X += 100.0f * DeltaTime;
SetActorLocation(NewLocation);
}
在这个例子中,我们创建了一个名为AMyActor的游戏对象,它包含一个静态网格组件。在BeginPlay方法中,我们输出了一条消息,表示游戏对象已经开始运行。在Tick方法中,我们每帧移动游戏对象的位置。
1.2 游戏对象的生命周期
游戏对象的生命周期包括以下阶段:
-
构造:在游戏对象实例化时调用。
-
BeginPlay:在游戏对象被添加到关卡时调用。
-
Tick:每帧调用,用于更新游戏对象的状态。
-
Destroy:在游戏对象被销毁时调用。
以下是一个更详细的例子,展示了游戏对象的生命周期:
// MyActor.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyActor.generated.h"
UCLASS()
class MYGAME_API AMyActor : public AActor
{
GENERATED_BODY()
public:
AMyActor();
protected:
virtual void BeginPlay() override;
public:
virtual void Tick(float DeltaTime) override;
virtual void Destroyed() override;
};
// MyActor.cpp
#include "MyActor.h"
#include "Components/StaticMeshComponent.h"
AMyActor::AMyActor()
{
PrimaryActorTick.bCanEverTick = true;
UStaticMeshComponent* MeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("MeshComponent"));
MeshComponent->SetupAttachment(RootComponent);
}
void AMyActor::BeginPlay()
{
Super::BeginPlay();
UE_LOG(LogTemp, Warning, TEXT("MyActor has begun play!"));
}
void AMyActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
FVector NewLocation = GetActorLocation();
NewLocation.X += 100.0f * DeltaTime;
SetActorLocation(NewLocation);
// 如果Actor移动到屏幕外,则销毁
if (NewLocation.X > 10000.0f)
{
Destroy();
}
}
void AMyActor::Destroyed()
{
Super::Destroyed();
UE_LOG(LogTemp, Warning, TEXT("MyActor has been destroyed!"));
}
在这个例子中,我们添加了Destroyed方法,在游戏对象被销毁时输出一条消息。同时,我们在Tick方法中添加了一个条件,当游戏对象移动到屏幕外时,自动销毁。
2. 组件(Component)
组件是游戏对象的构建块,每个游戏对象可以包含多个组件,这些组件负责游戏对象的不同方面。常见的组件类型包括:
-
静态网格组件(StaticMeshComponent):用于显示静态的3D模型。
-
骨骼网格组件(SkeletalMeshComponent):用于显示动画的3D模型。
-
相机组件(CameraComponent):用于控制视角。
-
光源组件(LightComponent):用于添加光源。
-
碰撞组件(CollisionComponent):用于处理碰撞检测。
2.1 静态网格组件
静态网格组件用于显示静态的3D模型。以下是一个例子,创建一个静态网格组件并附加到游戏对象:
// MyActor.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyActor.generated.h"
UCLASS()
class MYGAME_API AMyActor : public AActor
{
GENERATED_BODY()
public:
AMyActor();
protected:
virtual void BeginPlay() override;
public:
virtual void Tick(float DeltaTime) override;
private:
UPROPERTY(VisibleAnywhere)
UStaticMeshComponent* MeshComponent;
};
// MyActor.cpp
#include "MyActor.h"
#include "Components/StaticMeshComponent.h"
AMyActor::AMyActor()
{
PrimaryActorTick.bCanEverTick = true;
MeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("MeshComponent"));
MeshComponent->SetupAttachment(RootComponent);
// 设置默认的静态网格
static ConstructorHelpers::FObjectFinder<UStaticMesh> MeshAsset(TEXT("/Game/Models/MyModel"));
if (MeshAsset.Succeeded())
{
MeshComponent->SetStaticMesh(MeshAsset.Object);
}
}
void AMyActor::BeginPlay()
{
Super::BeginPlay();
UE_LOG(LogTemp, Warning, TEXT("MyActor has begun play!"));
}
void AMyActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
// 每帧旋转网格
FRotator NewRotation = GetActorRotation();
NewRotation.Yaw += 10.0f * DeltaTime;
SetActorRotation(NewRotation);
}
在这个例子中,我们创建了一个静态网格组件,并在构造函数中设置了默认的静态网格。在Tick方法中,我们每帧旋转网格。
2.2 骨骼网格组件
骨骼网格组件用于显示动画的3D模型。以下是一个例子,创建一个骨骼网格组件并附加到游戏对象:
// MyCharacter.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "MyCharacter.generated.h"
UCLASS()
class MYGAME_API AMyCharacter : public ACharacter
{
GENERATED_BODY()
public:
AMyCharacter();
protected:
virtual void BeginPlay() override;
public:
virtual void Tick(float DeltaTime) override;
private:
UPROPERTY(VisibleAnywhere)
USkeletalMeshComponent* SkeletalMeshComponent;
};
// MyCharacter.cpp
#include "MyCharacter.h"
#include "Components/SkeletalMeshComponent.h"
AMyCharacter::AMyCharacter()
{
PrimaryActorTick.bCanEverTick = true;
SkeletalMeshComponent = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("SkeletalMeshComponent"));
SkeletalMeshComponent->SetupAttachment(RootComponent);
// 设置默认的骨骼网格
static ConstructorHelpers::FObjectFinder<USkeletalMesh> SkeletalMeshAsset(TEXT("/Game/Models/MyCharacterMesh"));
if (SkeletalMeshAsset.Succeeded())
{
SkeletalMeshComponent->SetSkeletalMesh(SkeletalMeshAsset.Object);
}
// 设置默认的动画
static ConstructorHelpers::FObjectFinder<UAnimationAsset> AnimationAsset(TEXT("/Game/Animations/MyAnimation"));
if (AnimationAsset.Succeeded())
{
SkeletalMeshComponent->SetAnimationMode(EAnimationMode::AnimationSingleNode);
SkeletalMeshComponent->SetAnimation(AnimationAsset.Object);
}
}
void AMyCharacter::BeginPlay()
{
Super::BeginPlay();
UE_LOG(LogTemp, Warning, TEXT("MyCharacter has begun play!"));
}
void AMyCharacter::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
// 每帧更新角色的位置
FVector NewLocation = GetActorLocation();
NewLocation.X += 100.0f * DeltaTime;
SetActorLocation(NewLocation);
}
在这个例子中,我们创建了一个骨骼网格组件,并在构造函数中设置了默认的骨骼网格和动画。在Tick方法中,我们每帧更新角色的位置。
2.3 相机组件
相机组件用于控制游戏的视角。以下是一个例子,创建一个相机组件并附加到游戏对象:
// MyPlayerController.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/PlayerController.h"
#include "MyPlayerController.generated.h"
UCLASS()
class MYGAME_API AMyPlayerController : public APlayerController
{
GENERATED_BODY()
public:
AMyPlayerController();
protected:
virtual void BeginPlay() override;
public:
virtual void Tick(float DeltaTime) override;
private:
UPROPERTY(VisibleAnywhere)
UCameraComponent* CameraComponent;
};
// MyPlayerController.cpp
#include "MyPlayerController.h"
#include "Components/CameraComponent.h"
AMyPlayerController::AMyPlayerController()
{
PrimaryActorTick.bCanEverTick = true;
CameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("CameraComponent"));
CameraComponent->SetupAttachment(RootComponent);
// 设置相机的初始位置
CameraComponent->SetRelativeLocation(FVector(0.0f, 0.0f, 100.0f));
}
void AMyPlayerController::BeginPlay()
{
Super::BeginPlay();
UE_LOG(LogTemp, Warning, TEXT("MyPlayerController has begun play!"));
}
void AMyPlayerController::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
// 每帧旋转相机
FRotator NewRotation = CameraComponent->GetRelativeRotation();
NewRotation.Yaw += 10.0f * DeltaTime;
CameraComponent->SetRelativeRotation(NewRotation);
}
在这个例子中,我们创建了一个相机组件,并在构造函数中设置了相机的初始位置。在Tick方法中,我们每帧旋转相机。
2.4 光源组件
光源组件用于添加光源到游戏世界。以下是一个例子,创建一个光源组件并附加到游戏对象:
// MyLight.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyLight.generated.h"
UCLASS()
class MYGAME_API AMyLight : public AActor
{
GENERATED_BODY()
public:
AMyLight();
protected:
virtual void BeginPlay() override;
public:
virtual void Tick(float DeltaTime) override;
private:
UPROPERTY(VisibleAnywhere)
UPointLightComponent* PointLightComponent;
};
// MyLight.cpp
#include "MyLight.h"
#include "Components/PointLightComponent.h"
AMyLight::AMyLight()
{
PrimaryActorTick.bCanEverTick = true;
PointLightComponent = CreateDefaultSubobject<UPointLightComponent>(TEXT("PointLightComponent"));
PointLightComponent->SetupAttachment(RootComponent);
// 设置光源的颜色
PointLightComponent->SetLightColor(FLinearColor::Red);
// 设置光源的强度
PointLightComponent->SetIntensity(1000.0f);
}
void AMyLight::BeginPlay()
{
Super::BeginPlay();
UE_LOG(LogTemp, Warning, TEXT("MyLight has begun play!"));
}
void AMyLight::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
// 每帧改变光源的颜色
FLinearColor NewColor = PointLightComponent->GetLightColor();
NewColor.R = FMath::Fmod(NewColor.R + 0.01f, 1.0f);
PointLightComponent->SetLightColor(NewColor);
}
在这个例子中,我们创建了一个点光源组件,并在构造函数中设置了光源的颜色和强度。在Tick方法中,我们每帧改变光源的颜色。
2.5 碰撞组件
碰撞组件用于处理游戏对象之间的碰撞检测。以下是一个例子,创建一个碰撞组件并附加到游戏对象:
// MyCollisionActor.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyCollisionActor.generated.h"
UCLASS()
class MYGAME_API AMyCollisionActor : public AActor
{
GENERATED_BODY()
public:
AMyCollisionActor();
protected:
virtual void BeginPlay() override;
public:
virtual void Tick(float DeltaTime) override;
private:
UPROPERTY(VisibleAnywhere)
UBoxComponent* BoxComponent;
UPROPERTY(VisibleAnywhere)
UStaticMeshComponent* MeshComponent;
void OnComponentHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit);
};
// MyCollisionActor.cpp
#include "MyCollisionActor.h"
#include "Components/BoxComponent.h"
#include "Components/StaticMeshComponent.h"
AMyCollisionActor::AMyCollisionActor()
{
PrimaryActorTick.bCanEverTick = true;
BoxComponent = CreateDefaultSubobject<UBoxComponent>(TEXT("BoxComponent"));
BoxComponent->SetupAttachment(RootComponent);
MeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("MeshComponent"));
MeshComponent->SetupAttachment(BoxComponent);
// 设置默认的静态网格
static ConstructorHelpers::FObjectFinder<UStaticMesh> MeshAsset(TEXT("/Game/Models/MyBoxMesh"));
if (MeshAsset.Succeeded())
{
MeshComponent->SetStaticMesh(MeshAsset.Object);
}
// 启用碰撞
BoxComponent->SetCollisionProfileName(UCollisionProfile::BlockAllDynamic_ProfileName);
// 绑定碰撞事件
BoxComponent->OnComponentHit.AddDynamic(this, &AMyCollisionActor::OnComponentHit);
}
void AMyCollisionActor::BeginPlay()
{
Super::BeginPlay();
UE_LOG(LogTemp, Warning, TEXT("MyCollisionActor has begun play!"));
}
void AMyCollisionActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
// 每帧移动Actor
FVector NewLocation = GetActorLocation();
NewLocation.X += 100.0f * DeltaTime;
SetActorLocation(NewLocation);
}
void AMyCollisionActor::OnComponentHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit)
{
// 当发生碰撞时输出一条消息
UE_LOG(LogTemp, Warning, TEXT("MyCollisionActor hit by %s"), *OtherActor->GetName());
}
在这个例子中,我们创建了一个碰撞盒组件和一个静态网格组件,并将静态网格组件附加到碰撞盒组件上。我们启用了碰撞,并绑定了碰撞事件。当发生碰撞时,我们输出一条消息。
3. 组件的组合
游戏对象通常包含多个组件,这些组件协同工作以实现复杂的行为。以下是一个例子,创建一个包含多个组件的游戏对象:
// MyComplexActor.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyComplexActor.generated.h"
UCLASS()
class MYGAME_API AMyComplexActor : public AActor
{
GENERATED_BODY()
public:
AMyComplexActor();
protected:
virtual void BeginPlay() override;
public:
virtual void Tick(float DeltaTime) override;
private:
UPROPERTY(VisibleAnywhere)
UStaticMeshComponent* MeshComponent;
UPROPERTY(VisibleAnywhere)
UBoxComponent* BoxComponent;
UPROPERTY(VisibleAnywhere)
UPointLightComponent* PointLightComponent;
void OnComponentHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit);
};
// MyComplexActor.cpp
#include "MyComplexActor.h"
#include "Components/StaticMeshComponent.h"
#include "Components/BoxComponent.h"
#include "Components/PointLightComponent.h"
AMyComplexActor::AMyComplexActor()
{
PrimaryActorTick.bCanEverTick = true;
// 创建静态网格组件
MeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("MeshComponent"));
MeshComponent->SetupAttachment(RootComponent);
// 创建碰撞盒组件
BoxComponent = CreateDefaultSubobject<UBoxComponent>(TEXT("BoxComponent"));
BoxComponent->SetupAttachment(MeshComponent);
// 创建点光源组件
PointLightComponent = CreateDefaultSubobject<UPointLightComponent>(TEXT("PointLightComponent"));
PointLightComponent->SetupAttachment(BoxComponent);
// 设置默认的静态网格
static ConstructorHelpers::FObjectFinder<UStaticMesh> MeshAsset(TEXT("/Game/Models/MyComplexMesh"));
if (MeshAsset.Succeeded())
{
MeshComponent->SetStaticMesh(MeshAsset.Object);
}
// 启用碰撞
BoxComponent->SetCollisionProfileName(UCollisionProfile::BlockAllDynamic_ProfileName);
// 绑定碰撞事件
BoxComponent->OnComponentHit.AddDynamic(this, &AMyComplexActor::OnComponentHit);
// 设置光源的颜色
PointLightComponent->SetLightColor(FLinearColor::Green);
// 设置光源的强度
PointLightComponent->SetIntensity(500.0f);
}
void AMyComplexActor::BeginPlay()
{
Super::BeginPlay();
UE_LOG(LogTemp, Warning, TEXT("MyComplexActor has begun play!"));
}
void AMyComplexActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
// 每帧移动Actor
FVector NewLocation = GetActorLocation();
NewLocation.X += 100.0f * DeltaTime;
SetActorLocation(NewLocation);
// 每帧改变光源的颜色
FLinearColor NewColor = PointLightComponent->GetLightColor();
NewColor.G = FMath::Fmod(NewColor.G + 0.01f, 1.0f);
PointLightComponent->SetLightColor(NewColor);
}
void AMyComplexActor::OnComponentHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit)
{
// 当发生碰撞时输出一条消息
UE_LOG(LogTemp, Warning, TEXT("MyComplexActor hit by %s"), *OtherActor->GetName());
// 当发生碰撞时改变光源的颜色
PointLightComponent->SetLightColor(FLinearColor::Red);
}
在这个例子中,我们创建了一个包含多个组件的游戏对象 AMyComplexActor,这些组件包括:
-
静态网格组件(StaticMeshComponent):用于显示静态的3D模型。
-
碰撞盒组件(BoxComponent):用于处理碰撞检测。
-
点光源组件(PointLightComponent):用于添加光源。
3.1 静态网格组件
静态网格组件 MeshComponent 被创建并附加到游戏对象的根组件 RootComponent。我们还设置了一个默认的静态网格模型,使其在游戏开始时显示。
3.2 碰撞盒组件
碰撞盒组件 BoxComponent 被创建并附加到静态网格组件 MeshComponent。我们启用了碰撞,并绑定了碰撞事件 OnComponentHit,当发生碰撞时,会输出一条消息并改变光源的颜色。
3.3 点光源组件
点光源组件 PointLightComponent 被创建并附加到碰撞盒组件 BoxComponent。我们设置了光源的颜色为绿色,并在每帧改变其颜色,使其产生动画效果。
4. 游戏对象与组件的交互
游戏对象和组件之间可以通过各种方式交互,以实现更复杂的游戏逻辑。以下是一些常见的交互方式:
-
设置组件属性:在游戏对象的代码中直接设置组件的属性。
-
调用组件方法:调用组件的方法来改变其行为。
-
事件绑定:将组件的事件绑定到游戏对象的方法上,以便在事件发生时执行特定的逻辑。
4.1 设置组件属性
设置组件属性是最常见的交互方式之一。以下是一个例子,展示如何在游戏对象中设置组件的属性:
// MyActor.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyActor.generated.h"
UCLASS()
class MYGAME_API AMyActor : public AActor
{
GENERATED_BODY()
public:
AMyActor();
protected:
virtual void BeginPlay() override;
public:
virtual void Tick(float DeltaTime) override;
private:
UPROPERTY(VisibleAnywhere)
UStaticMeshComponent* MeshComponent;
UPROPERTY(VisibleAnywhere)
UPointLightComponent* PointLightComponent;
};
// MyActor.cpp
#include "MyActor.h"
#include "Components/StaticMeshComponent.h"
#include "Components/PointLightComponent.h"
AMyActor::AMyActor()
{
PrimaryActorTick.bCanEverTick = true;
MeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("MeshComponent"));
MeshComponent->SetupAttachment(RootComponent);
PointLightComponent = CreateDefaultSubobject<UPointLightComponent>(TEXT("PointLightComponent"));
PointLightComponent->SetupAttachment(MeshComponent);
// 设置默认的静态网格
static ConstructorHelpers::FObjectFinder<UStaticMesh> MeshAsset(TEXT("/Game/Models/MyModel"));
if (MeshAsset.Succeeded())
{
MeshComponent->SetStaticMesh(MeshAsset.Object);
}
// 设置光源的颜色
PointLightComponent->SetLightColor(FLinearColor::Blue);
// 设置光源的强度
PointLightComponent->SetIntensity(500.0f);
}
void AMyActor::BeginPlay()
{
Super::BeginPlay();
UE_LOG(LogTemp, Warning, TEXT("MyActor has begun play!"));
}
void AMyActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
// 每帧改变光源的颜色
FLinearColor NewColor = PointLightComponent->GetLightColor();
NewColor.B = FMath::Fmod(NewColor.B + 0.01f, 1.0f);
PointLightComponent->SetLightColor(NewColor);
}
在这个例子中,我们创建了一个静态网格组件和一个点光源组件,并在构造函数中设置了它们的属性。在 Tick 方法中,我们每帧改变光源的颜色。
4.2 调用组件方法
调用组件的方法可以改变其行为或状态。以下是一个例子,展示如何在游戏对象中调用组件的方法:
// MyCharacter.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "MyCharacter.generated.h"
UCLASS()
class MYGAME_API AMyCharacter : public ACharacter
{
GENERATED_BODY()
public:
AMyCharacter();
protected:
virtual void BeginPlay() override;
public:
virtual void Tick(float DeltaTime) override;
UFUNCTION()
void MoveForward(float Value);
private:
UPROPERTY(VisibleAnywhere)
USkeletalMeshComponent* SkeletalMeshComponent;
UPROPERTY(VisibleAnywhere)
UCameraComponent* CameraComponent;
};
// MyCharacter.cpp
#include "MyCharacter.h"
#include "Components/SkeletalMeshComponent.h"
#include "Components/CameraComponent.h"
#include "GameFramework/CharacterMovementComponent.h"
AMyCharacter::AMyCharacter()
{
PrimaryActorTick.bCanEverTick = true;
SkeletalMeshComponent = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("SkeletalMeshComponent"));
SkeletalMeshComponent->SetupAttachment(RootComponent);
CameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("CameraComponent"));
CameraComponent->SetupAttachment(RootComponent);
CameraComponent->SetRelativeLocation(FVector(0.0f, 0.0f, 100.0f));
// 设置默认的骨骼网格
static ConstructorHelpers::FObjectFinder<USkeletalMesh> SkeletalMeshAsset(TEXT("/Game/Models/MyCharacterMesh"));
if (SkeletalMeshAsset.Succeeded())
{
SkeletalMeshComponent->SetSkeletalMesh(SkeletalMeshAsset.Object);
}
// 设置默认的动画
static ConstructorHelpers::FObjectFinder<UAnimationAsset> AnimationAsset(TEXT("/Game/Animations/MyAnimation"));
if (AnimationAsset.Succeeded())
{
SkeletalMeshComponent->SetAnimationMode(EAnimationMode::AnimationSingleNode);
SkeletalMeshComponent->SetAnimation(AnimationAsset.Object);
}
}
void AMyCharacter::BeginPlay()
{
Super::BeginPlay();
UE_LOG(LogTemp, Warning, TEXT("MyCharacter has begun play!"));
}
void AMyCharacter::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
// 每帧更新角色的位置
FVector NewLocation = GetActorLocation();
NewLocation.X += 100.0f * DeltaTime;
SetActorLocation(NewLocation);
}
void AMyCharacter::MoveForward(float Value)
{
if (Value != 0.0f)
{
// 调用CharacterMovementComponent的方法来移动角色
AddMovementInput(GetActorForwardVector(), Value);
}
}
在这个例子中,我们创建了一个骨骼网格组件和一个相机组件。我们还定义了一个 MoveForward 方法,该方法调用 CharacterMovementComponent 的 AddMovementInput 方法来移动角色。
4.3 事件绑定
事件绑定允许你将组件的事件与游戏对象的方法关联起来,以便在事件发生时执行特定的逻辑。以下是一个例子,展示如何在游戏对象中绑定组件的事件:
// MyTriggerActor.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyTriggerActor.generated.h"
UCLASS()
class MYGAME_API AMyTriggerActor : public AActor
{
GENERATED_BODY()
public:
AMyTriggerActor();
protected:
virtual void BeginPlay() override;
public:
virtual void Tick(float DeltaTime) override;
private:
UPROPERTY(VisibleAnywhere)
UBoxComponent* TriggerComponent;
UPROPERTY(VisibleAnywhere)
UStaticMeshComponent* MeshComponent;
void OnTriggerOverlapBegin(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);
void OnTriggerOverlapEnd(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);
};
// MyTriggerActor.cpp
#include "MyTriggerActor.h"
#include "Components/BoxComponent.h"
#include "Components/StaticMeshComponent.h"
AMyTriggerActor::AMyTriggerActor()
{
PrimaryActorTick.bCanEverTick = true;
// 创建触发器组件
TriggerComponent = CreateDefaultSubobject<UBoxComponent>(TEXT("TriggerComponent"));
TriggerComponent->SetupAttachment(RootComponent);
TriggerComponent->SetCollisionProfileName(UCollisionProfile::OverlapAllDynamic_ProfileName);
// 创建静态网格组件
MeshComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("MeshComponent"));
MeshComponent->SetupAttachment(TriggerComponent);
// 绑定触发器事件
TriggerComponent->OnComponentBeginOverlap.AddDynamic(this, &AMyTriggerActor::OnTriggerOverlapBegin);
TriggerComponent->OnComponentEndOverlap.AddDynamic(this, &AMyTriggerActor::OnTriggerOverlapEnd);
// 设置默认的静态网格
static ConstructorHelpers::FObjectFinder<UStaticMesh> MeshAsset(TEXT("/Game/Models/MyTriggerMesh"));
if (MeshAsset.Succeeded())
{
MeshComponent->SetStaticMesh(MeshAsset.Object);
}
}
void AMyTriggerActor::BeginPlay()
{
Super::BeginPlay();
UE_LOG(LogTemp, Warning, TEXT("MyTriggerActor has begun play!"));
}
void AMyTriggerActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
// 每帧更新Actor的位置
FVector NewLocation = GetActorLocation();
NewLocation.X += 100.0f * DeltaTime;
SetActorLocation(NewLocation);
}
void AMyTriggerActor::OnTriggerOverlapBegin(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
// 当其他Actor进入触发器区域时输出一条消息
UE_LOG(LogTemp, Warning, TEXT("MyTriggerActor triggered by %s"), *OtherActor->GetName());
// 改变触发器的颜色
MeshComponent->SetMaterial(0, nullptr); // 假设你有一个材料可以改变颜色
}
void AMyTriggerActor::OnTriggerOverlapEnd(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
// 当其他Actor离开触发器区域时输出一条消息
UE_LOG(LogTemp, Warning, TEXT("MyTriggerActor untriggered by %s"), *OtherActor->GetName());
// 恢复触发器的颜色
MeshComponent->SetMaterial(0, nullptr); // 假设你有一个默认材料
}
在这个例子中,我们创建了一个触发器组件 TriggerComponent 和一个静态网格组件 MeshComponent。我们启用了触发器的碰撞,并绑定了 OnComponentBeginOverlap 和 OnComponentEndOverlap 事件。当其他游戏对象进入或离开触发器区域时,我们会输出一条消息并改变触发器的颜色。
5. 总结
在Unreal Engine中,游戏对象和组件是构建游戏的基础。游戏对象是游戏世界中的实体,可以包含多个组件,这些组件负责游戏对象的不同方面。通过设置组件属性、调用组件方法和绑定组件事件,你可以实现复杂的交互和行为。组件的组合使得游戏对象能够执行多种功能,从而构建出丰富多样的游戏世界。
希望这些例子能帮助你更好地理解和使用Unreal Engine中的游戏对象和组件。如果你有任何问题或需要进一步的帮助,请随时查阅Unreal Engine的官方文档或社区资源。
1230

被折叠的 条评论
为什么被折叠?



