【转载】 UE4 C++ 的常用代码片段

1,575 阅读5分钟

Unreal 宏定义

UCLASS

最基础的 UCLASS 声明

// .h
UCLASS()
class PROJECTNAME_API MyClassName : public ParentClass
{
    GENERATED_BODY()
public:
    MyClassName();
protected:
private:
};

USTRUCT

最基础的 USTRUCT 声明

USTRUCT(BlueprintType)
struct FMyStruct
{
    GENERATED_BODY()

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=MyCategory)
    float MyFloat;
};

MyStruct 派生于数据表:

USTRUCT(BlueprintType)
struct FMyStruct : public FTableRowBase
{
    GENERATED_BODY()

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=MyCategory)
    float test;
};

UENUM

最基础的 UENUM 声明

UENUM(BlueprintType)
enum class EMyMovementStatus : uint8
{
    Idle UMETA(DisplayName="Idle"),
    Walking UMETA(DisplayName="Walking"),
    Running UMETA(DisplayName="Running")
};

UFUNCTION

基础的 UFUNCTION

UFUNCTION()
void MyFunctionName();

UFUNCTION()
void MyFunctionNameWithParameters(const FString& SomeString, int SomeInt);

带网络的 UFUNCTION

用于 AMyActorClass 的声明(.h)

UFUNCTION(Client, Unreliable)
void MyFunctionName();

UFUNCTION(Client, Unreliable)
void MyFunctionNameWithParameters(const FString& SomeString, int SomeInt);

UFUNCTION(NetMulticast, Reliable, WithValidation)
void MyMulticastFunctionName();
//
UFUNCTION(Server, Reliable, WithValidation)
void MyServerFunctionName(FRotator Rotation);

用于 AMyActorClass 的声明(.cpp)

void AMyActorClass::MyFunctionName() {}

void AMyActorClass::MyFunctionNameWithParameters(const FString& SomeString, int SomeInt) {}

void AMyActorClass::MyMulticastFunctionName() {}
bool AMyActorClass::MyMulticastFunctionName_Validate() { return true; }
void AMyActorClass::MyMulticastFunctionName_Implementation() {}

void AMyActorClass::MyServerFunctionName(FRotator Rotation) {} 
bool AMyActorClass::MyServerFunctionName_Validate(FRotator Rotation) { return true; }
void AMyActorClass::MyServerFunctionName_Implementation(FRotator Rotation) {}

UINTERFACE

UINTERFACE 头文件的基础例子

UINTERFACE()
class TASGAME_API UInteractable: public UInterface
{
    GENERATED_BODY()
};

class IInteractable
{
    GENERATED_BODY()
public:
    UFUNCTION(Category = "Interactable")
    virtual bool CanInteract();
    UFUNCTION(Category = "Interactable")
    virtual void PerformInteract();
};

组件

创建弹簧臂与相机

从一个 Actor 构造函数中创建一个摄像机组件

// .h
UPROPERTY(VisibleAnywhere)
USpringArmComponent *m_springArmComponent = nullptr;
UPROPERTY(VisibleAnywhere)
UCameraComponent *CameraComponent = nullptr;

// .cpp
SpringArmComponent = CreateDefaultSubobject(FName("SpringArmComponent"));
m_springArmComponent->SetupAttachment(RootComponent);
SpringArmComponent->TargetArmLength = 1000;

CameraComponent = CreateDefaultSubobject(FName("CameraComponent"));
CameraComponent->SetupAttachment(SpringArmComponent);

 重叠碰撞组件

一个 Actor 组件的重叠绑定

UShapeComponent* TriggerShapeCollisionComponent
TriggerShapeCollisionComponent->OnComponentBeginOverlap.AddDynamic(this, &UMyComponent::OnOverlapBegin);
TriggerShapeCollisionComponent->OnComponentEndOverlap.AddDynamic(this, &UMyComponent::OnOverlapEnd);
... 
UFUNCTION() 
void OnOverlapBegin(UPrimitiveComponent *OverlappedComponent,
                                    AActor *OtherActor,
                                    UPrimitiveComponent *OtherComp,
                                    int32 OtherBodyIndex,
                                    bool bFromSweep,
                                    const FHitResult &SweepResult);

UFUNCTION()
void OnOverlapEnd(UPrimitiveComponent *OverlappedComponent, AActor *OtherActor, UPrimitiveComponent *OtherComp, int32 OtherBodyIndex);

一个 Actor 的重叠绑定

OnActorBeginOverlap.AddDynamic(this, &UMyActor::OnActorBeginOverlap);
OnActorEndOverlap.AddDynamic(this, &UMyActor::OnActorEndOverlap);
...
UFUNCTION()
void OnActorBeginOverlap(AActor* OverlappedActor, AActor* OtherActor);
UFUNCTION()
void OnActorEndOverlap(AActor* OverlappedActor, AActor*, AActor* OtherActor);

其他杂项

日志

GEngine->AddOnScreenDebugMessage(0, 0.f, FColor::Red, FString::Printf(TEXT("TEXT")));
// 简单
UE_LOG(LogTemp, Display, TEXT("Your message"));
// 带格式化的 
// (const TCHAR* Message, int64 SomeInt)
UE_LOG(LogTemp, Display, TEXT("Your message string %s with a number %d"), Message, SomeInt);
// (const FString& Message, float SomeFloat)
UE_LOG(LogTemp, Display, TEXT("Your message string %s with a number %f"), *Message, SomeFloat);
// (const FName& Message, bool SomeBool)
UE_LOG(LogTemp, Display, TEXT("Your message string %s with a bool %d"), *Message.ToString(), SomeBool);

获取

获得所有的 Actor (警告: 昂贵的操作)

// TArray ActorArray; FName SearchTag; ...
UGameplayStatics::GetAllActorsOfClass(GetWorld(), AMyClass::StaticClass(), ActorArray);
UGameplayStatics::GetAllActorsWithTag(GetWorld(), SearchTag, ActorArray)
UGameplayStatics::GetAllActorsOfClassWithTag(GetWorld(), APlayerCharacterBase::StaticClass(), SearchTag, ActorArray)

从 Actor 内部获取组件

UActorComponent* myComponent = GetComponentByClass(USomeActorComponent::StaticClass());

从 Actor 内部获取组件并类型转换

USomeActorComponent* myComponent = Cast(GetComponentByClass(USomeActorComponent::StaticClass()));

从 Actor 内部获取所有指定的组件

TSet myComponents = GetComponents();
TArray components = GetComponentsByTag(UActorComponent::StaticClass(), SearchTag);
TArray components = GetComponentsByInterface(UMyInterface::StaticClass());

输入

InputComponent->BindAction("Button", EInputEvent::IE_Pressed, this, &MyClass::ButtonPressed);
...
void MyClass::ButtonPressed() {}
InputComponent->BindAxis("MoveForward", this, &MyClass::MoveForward);
...
void MyClass::MoveForward(float axisValue)

保存

保存游戏以便稍后加载。 创建一个继承自 USaveGame 的类。 添加一些成员属性,如 float HighScore

UMySaveGame* Instance = Cast(UGameplayStatics::CreateSaveGameObject(UMySaveGame::StaticClass()));
Instance.HighScore = 100;
UGameplayStatics::SaveGameToSlot(Instance, SaveSlotName, UserIndex);

从保存中加载并设置适当的值。

UMySaveGame* Instance = Cast(UGameplayStatics::LoadGameFromSlot(SaveSlotName, UserIndex));
MyGameInstance.HighScore = Instance.HighScore;

派生 Actor

Actor 是可以放置或派生到一个世界中的基类。 参阅 Actor

在世界当中简单派生 Actor

// (FVector Location, FRotator Rotation)
AMyClass* ActorName = GetWorld()->SpawnActor(Location, Rotation);

延迟一个生成的 actor ,允许你延迟对象的实际生成,因此 BeginPlay 将在这个 actor 上被延迟。 这将允许你在构建之后但在 BeginPlay 发生之前进行更改。

// 调用以获取构造的 actor 的实例
AMyClass* ActorName = GetWorld()->SpawnActorDeferred(UClass, ActorTransform, Owner, Instigator, ESpawnActorCollisionHandlingMethod::AlwaysSpawn);
// 做些事
...
// 需要被调用来真正完成并在给定 Actor 上开始 BeginPlay  
UGameplayStatics::FinishSpawningActor(ActorName, ActorTransform);

音频

这里有各种各样的对话框和声音,你可以生成和播放它们。  

如果你想做一个火并忘记声音(do a fire and forget sound),你应该使用 PlaySound 函数,而不是 Spawn 的函数。

生成 2D 对话框:

UAudioComponent* MyDialog = UGameplayStatics::SpawnDialogue2D(GetWorld(), DialogWave, DialogContext, VolumeMultiplier, PitchMultiplier, StartTime, bAutoDestroy);

生成附着的对话框:

UAudioComponent* MyDialog = UGameplayStatics::SpawnDialogueAttached(GetWorld(), DialogWave, DialogContext, AttachToComponent, AttachPointName, Location, Rotation, EAttachLocation::KeepRelativeOffset, bStopWhenAttachedToDestroyed, VolumeMultiplier, PitchMultiplier, StartTime, Attenuation, bAutoDestroy);

在位置生成对话框:

UAudioComponent* MyDialog = UGameplayStatics::SpawnDialogueAtLocation(GetWorld(), DialogWave, DialogContext, Location, Rotation, VolumeMultiplier, PitchMultiplier, StartTime, Attenuation, bAutoDestroy);

生成 2D 声音:

UAudioComponent* MySound = UGameplayStatics::SpawnSound2D(GetWorld(), SoundBase, VolumeMultiplier, PitchMultiplier, StartTime, Concurrency, bPersistentAcrossLevelTransition, bAutoDestroy);

生成附着的声音:

UAudioComponent* MySound = UGameplayStatics::SpawnSoundAttached(SoundBase, AttachToComponent, AttachPointName, Location, Rotation, EAttachLocation::KeepRelativeOffset, bStopWhenAttachedToDestroyed, VolumeMultipler, PitchMultiplier, StartTime, Attenuation, Concurrency, bAutoDestroy);

在位置生成声音:

UAudioComponent* MySound = UGameplayStatics::SpawnSoundAtLocation(GetWorld(), SoundBase, Location, Rotation, VolumeMultiplier, PitchMultiplier, StartTime, Attenuation, Concurrency, bAutoDestroy);

播放声音:

UGameplayStatics::PlayDialogue2D(GetWorld(), DialogWave, DialogContext, VolumeMultiplier, PitchMultiplier, StartTime);
//
UGameplayStatics::PlayDialogueAtLocation(GetWorld(), DialogWave, DialogContext, Location, Rotation, VolumeMultiplier, PitchMultiplier, StartTime, Attenuation);
//
UGameplayStatics::PlayDialogue2D(GetWorld(), DialogWave, DialogContext, VolumeMultiplier, PitchMultiplier, StartTime);
//
UGameplayStatics::PlayDialogueAtLocation(GetWorld(), DialogWave, DialogContext, Location, Rotation, VolumeMultiplier, PitchMultiplier, StartTime, Attenuation);
//
UGameplayStatics::PlaySound2D(GetWorld(), SoundBase, VolumeMultiplier, PitchMultiplier, StartTime, Concurrency, Owner);
//
UGameplayStatics::PlaySoundAtLocation(GetWorld(), SoundBase, Location, Rotation, VolumeMultiplier, PitchMultiplier, StartTime, Attenuation, Concurrency, Owner);

射线跟踪和重叠

如果你不使用碰撞组件,并且想要进行 单射线跟踪(1-off line trace) 或重叠,这些函数就是为你准备的!

GetWorld()->LineTraceMultiByChannel(HitsArray, Start, End, ECC_Visibility, TraceParams);
GetWorld()->LineTraceMultiByObjectType(HitsArray, Start, End, ObjectQueryParams, TraceParams);
GetWorld()->LineTraceMultiByProfile(HitsArray, Start, End, "ProfileName", TraceParams);
GetWorld()->LineTraceSingleByChannel(Hit, Start, End, ECC_Visibility, TraceParams);
GetWorld()->LineTraceSingleByObjectType(Hit, Start, End, ObjectQueryParams, TraceParams);
GetWorld()->LineTraceSingleByProfile(Hit, Start, End, "ProfileName", TraceParams);
GetWorld()->OverlapMultiByChannel(OverlapsArray, Location, FQuat::Identity, ECC_Visibility, FCollisionShape::MakeSphere(Radius), TraceParams);
GetWorld()->OverlapMultiByObjectType(OverlapsArray, Location, FQuat::Identity, ObjectQueryParams, FCollisionShape::MakeSphere(Radius), TraceParams);
GetWorld()->OverlapMultiByProfile(OverlapsArray, Location, FQuat::Identity, "ProfileName", FCollisionShape::MakeSphere(Radius), TraceParams);

粒子系统

粒子系统应用于各种各样的视觉效果,如从排出的烟雾,跑步踢起的灰尘,飞溅的水花,从松动的电线蹦出的火花。

粒子发射系统的生成

UParticleSystemComponent* MyParticles = UGameplayStatics::SpawnEmitterAttached(ParticleSystem, AttachToComponent, AttachPointName, Location, Rotation, Scale, EAttachLocation::KeepRelativeOffset, bAutoDestroy);
//
UParticleSystemComponent* MyParticles = UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), ParticleSystem, Location, Rotation, Scale, bAutoDestroy);
//
UParticleSystemComponent* MyParticles = UGameplayStatics::SpawnEmitterAttached(ParticleSystem, AttachToComponent, AttachPointName, Location, Rotation, Scale, EAttachLocation::KeepRelativeOffset, bAutoDestroy);
//
UParticleSystemComponent* MyParticles = UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), ParticleSystem, Location, Rotation, Scale, bAutoDestroy);

贴花(Decals)

贴花是指在关卡中投射到网格上的材质。 比如在墙上涂鸦,或者在干净的地板上留下肮脏的脚印。

UDecalComponent* MyDecal = UGameplayStatics::SpawnDecalAttached(GetWorld(), DecalMaterialInterface, Size, AttachToComponent, AttachPointName, Location, Rotation, EAttachLocation::KeepRelativeOffset, lifeSpan);
//
UDecalComponent* MyDecal = UGameplayStatics::SpawnDecalAtLocation(GetWorld(), DecalMaterialInterface, Size, Location, Rotation, lifeSpan);

定时器(Timers)

如果循环,计时器将在每个 DelayTime 间隔调用一个函数。

FTimerHandle TimerHandle;

// 开启定时器
GetWorld()->GetTimerManager().SetTimer(TimerHandle, this, &Class::Function, DelayTime, bLoop);
GetWorld()->GetTimerManager().SetTimer(TimerHandle, this, &Class::Function, DelayTime, bLoop, FirstDelay);

// 暂停/恢复定时器
GetWorld()->GetTimerManager().PauseTimer(TimerHandle);
GetWorld()->GetTimerManager().UnPauseTimer(TimerHandle);

// 停止/清理定时器
GetWorld()->GetTimerManager().ClearTimer(TimerHandle);
TimerHandle.Invalidate();

ConstructorHelpers 类

需包括头文件

#include "UObject/ConstructorHelpers.h"

应为静态加载只能在构造函数中添加

  • FObjectFinder 用于加载材质模型
  • FClassFinder 用于加载其他类,因格式问题需在复制地址后加入 _C 或者改成 /Game/Character/NewAnimBlueprint,否则会出 BUG 一开就崩溃
ABaseCharacter::ABaseCharacter()
{
    static ConstructorHelpers::FObjectFinder<USkeletalMesh>Skelel(TEXT("在蓝图中复制其地址"));
    static ConstructorHelpers::FClassFinder<UAnimInstance>BaseChaGameInstance(TEXT("/Game/Character/NewAnimBlueprint"));
    if (GameCharacterSkelel.Succeeded())
            {
                    GetMesh()->SetSkeletalMesh(GameCharacterSkelel.Object);
                    GetMesh()->SetAnimInstanceClass(BaseChaGameInstance.Class);
            }
}

ConstructorHelpers 内只有一个命名空间 ConstructorHelpersInternal 和一个 struct

GameplayStatics 类

需包括头文件

#include "Kismet/GameplayStatics.h"

我们一般在蓝图中调用 GetPlayerController 或者 GetPlayerCharacter 时,直接写就好了,而在 CPP 中 要使用 GameplayStatics:: 来调用,而 GameplayStatics 是一个函数库,调用起来也很方便

UGameplayStatics::GetPlayerController(GetWorld(), 0)->bShowMouseCursor = true;
UGameplayStatics::OpenLevel(GetWorld(), TEXT("/Game/MAP/ExeciseMap"));
ACharacter*BaseCharacter=UGameplayStatics::GetPlayerCharacter(this,0);

没事可以多 Alt+G 翻翻源码观看

参考

from : unrealcommunity.wiki/common-snip…

from:blog.csdn.net/weixin_4229…