常用函数使用方法总结
Delay 函数的使用
FLatentActionInfo LatentInfo;
LatentInfo.CallbackTarget = this;
LatentInfo.ExecutionFunction = "此处输入之后要调用的函数名";
LatentInfo.Linkage = 1;
LatentInfo.UUID = 100;
UKismetSystemLibrary::Delay(this, 间隔时间, LatentInfo);
FTimerHandle 用法
在C++里面也有实现类似Delay的函数:
GetWorld()->GetTimerManager().SetTimer(TH_StanceAction, this, &AALSVLearnDemoCharacter::ResetStanceActionCount, .3f);
相比之下这个函数比Delay更好用也更容易记住。
他的函数定义是这样的:
void SetTimer(FTimerHandle& InOutHandle, UserClass* InObj, typename FTimerDelegate::TUObjectMethodDelegate< UserClass >::FMethodPtr InTimerMethod, float InRate, bool InbLoop = false, float InFirstDelay = -1.f);
各个参数的意义:
/**
* 设置一个计时器在设定的时间间隔调用给定的本机函数。
* 如果已经设置了计时器,对于这个句柄,它将替换当前计时器。
* @param inouthandle如果传入的句柄指向一个已经存在的计时器,它将在添加新的计时器之前被清除。在这两种情况下都会返回新计时器的新句柄。
* @param inobj对象调用计时器函数。
* @param indermethod定时器触发时调用的方法。
* @param inrate设置和触发之间的时间(秒)。如果 <= 0.f,清除现有的计时器。
* @param inbloop true表示按Rate间隔触发,false表示只触发一次。
* @param infirstdelay循环计时器第一次迭代的时间(以秒为单位)。如果 < 0.f将使用InRate。
* /
对当前计时器清零:
GetWorld()->GetTimerManager().ClearTimer(TH_StanceAction);
获取触发时间:
GetWorld()->GetTimerManager().GetTimerRate(TH_StanceAction)
获取剩余时间:
GetWorld()->GetTimerManager().GetTimerRemaining(TH_StanceAction)
输出枚举变量名称
const UEnum* CompileModeEnum = StaticEnum<枚举类型>();
if (CompileModeEnum)
{
UE_LOG(LogTemp, Warning, TEXT("枚举变量名 : %s"),
*CompileModeEnum->GetDisplayNameTextByValue(static_cast<uint8>(枚举变量)).ToString());
}
任意按键绑定函数
使用 BindKey 的时候需要添加 Slate 模块!
InputComponent->BindKey(EKeys::T, IE_Pressed, this, &AALS_Player_Controller::SwitchShowTraces);
在游戏运行中生成某个Actor
.h
TSubclassOf<生成的类型的基类名> PawnToSpawn;
.cpp
GetWorld()->SpawnActor<生成的Actor类型>(生成的Actor对应的类, 出生地址, 出生旋转角度)
在游戏中生成AI控制的Actor
SpawnAIFromClass能够在生成actor的同时生成AI控制器
UAIBlueprintHelperLibrary::SpawnAIFromClass(GetWorld(), EnemyClass, nullptr, FVector(-198.f, -27.f, 95.f),
FRotator(0.f, 0.f, 0.f), false, nullptr);
使用委托函数进行碰撞检测
.h
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="XXXX")
USphereComponent* DetectSphere;
// 委托函数
UFUNCTION()
void OnDetectSphereOverlapBegin(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep,
const FHitResult& SweepResult);
UFUNCTION()
void OnDetectSphereOverlapEnd(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);
.cpp
// 绑定委托函数
// 开始重叠的时候才会调用OnDetectSphereOverlapBegin函数
DetectSphere->OnComponentBeginOverlap.AddDynamic(this, &AXXXX::OnDetectSphereOverlapBegin);
// 结束重叠的时候才会调用OnDetectSphereOverlapBegin函数
DetectSphere->OnComponentEndOverlap.AddDynamic(this, &AXXXX::OnDetectSphereOverlapEnd);
让Actor自动按照指定的方向移动
FTransform Transform = GetActorTransform();
Transform.SetLocation(GetActorLocation() + UKismetMathLibrary::Normal(Direction) * DeltaSeconds * Speed);
SetActorTransform(Transform);
AI 自动寻路
EnemyController = GetController<AAIController>(); // 使用前要先获取AI控制器
FAIMoveRequest MoveRequest;
MoveRequest.SetGoalActor(TargetCharacter);
MoveRequest.SetAcceptanceRadius(0.f); // 之间相差多少算是移动停止了
FNavPathSharedPtr NavPath;
EnemyController->MoveTo(MoveRequest, &NavPath);
需要在地图中添加Nav Mesh Bounds Bolume
来规划AI的行走路线,添加之后按下P键就可以看到绿颜色,绿色的就是代表AI可以心走的区域,可以使用Nav Modifier Volume
进行修剪AI的行走区域。
AI 停止或者继续移动
EnemyController->PauseMove(RequestID); // AI 停止移动
nemyController->ResumeMove(RequestID); // AI 继续运动
将UI加载到屏幕中
- 变量声明
// 运行游戏时的UI静态资源
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="UI")
TSubclassOf<UUserWidget> GameRunHUDAsset;
// 保存UI的变量
UPROPERTY()
UUserWidget* GameRunHUD;
- 函数调用
先在BeginPlaye中初始化数据:
if (GameRunHUDAsset)
{
GameRunHUD = CreateWidget<UUserWidget>(this, GameRunHUDAsset);
}
在展示它的地方使用:
if (GameRunHUD)
{
GameRunHUD->AddToViewport();
}
在销毁它的地方使用:
if (GameRunHUD)
{
GameRunHUD->RemoveFromViewport();
}
更新摄像机管理器中摄像机的位置
void UpdateViewTargetInternal(FTViewTarget& OutVT, float DeltaTime)
{
if (OutVT.Target)
{
FVector OutLocation;
FRotator OutRotation;
float OutFOV;
// 判断该变量是否是 基类角色的子类 并且 已经获取到了控制的角色
if (判断条件 && 自定义函数更新属性 : CustomCameraBehavior(DeltaTime, OutLocation, OutRotation, OutFOV))
{
// ……
}
else
{
// 否则就用原来的
OutVT.Target->CalcCamera(DeltaTime, OutVT.POV);
}
}
}
判断y是否是Y的子类
y->IsA<Y>()
射线检测的写法
建议不要直接调用KismetSystemLibrary
库里面的射线检测,直接按照下面的形式写即可。
- 球体射线检测
FVector TraceOrigin; // 起始点
float TraceRadius; // 射线半径
ECollisionChannel TraceChannel; // 射线通道
// …… 这里进行对应的逻辑处理
// 获取当前世界
UWorld* World = GetWorld();
check(World);
// 配置射线检测参数
FCollisionQueryParams Params;
Params.AddIgnoredActor(this);
Params.AddIgnoredActor(ControlledCharacter);
// 储存碰撞结果
FHitResult HitResult;
// 说明 射线检测的形状
const FCollisionShape SphereCollisionShape = FCollisionShape::MakeSphere(TraceRadius);
const bool bHit = World->SweepSingleByChannel(HitResult, TraceOrigin, TargetCameraLocation, FQuat::Identity, TraceChannel, SphereCollisionShape, Params);
a类中是否包含B类组件并返回该组件
UActorComponent* Comp = a->GetComponentByClass(B::StaticClass());
从数据表中读取行名为RowName的数据
FDataTableRowHandle MovementModel;
// 打印Actor当前的文件地址
const FString ContextString = GetFullName();
/*
* UE_LOG(LogTemp, Warning, TEXT("GetFullName: %s"), *ContextString);
* 输出 GetFullName: ALS_CharacterBP_C /Game/Maps/UEDPIE_0_M_Level1.M_Level1:PersistentLevel.ALS_CharacterBP_C_0
* 前面是名字,后面是地址。
*/
// 从数据表中读取 行名为RowName的数据,记得要初始化。
FALSMovementStateSettings* OutRow =
MovementModel.DataTable->FindRow<FALSMovementStateSettings>(MovementModel.RowName, ContextString);
check(OutRow);
MovementData = *OutRow;