在【模式】搜索Sound, 选择【环境音效】拖放到关卡中,在细节面板指定 WAV 的音效文件,即可播放BGM;
其他音乐格式转换的WAV的网站:
// 获取GameMode // UGameplayStatics 需要引入 #include "Kismet/GameplayStatics.h"
GameMode = Cast<APacManGameModeBase>(UGameplayStatics::GetGameMode(this));
// 使用 ConstructorHelpers 需要引入的头文件:#include "Public/UObject/ConstructorHelpers.h" 找到了想要的变成的球体
static ConstructorHelpers::FObjectFinder<UStaticMesh> Sphere(TEXT("StaticMesh'/Engine/BasicShapes/Sphere.Sphere'"));
// 使用GetCapsuleComponent,需要引入头文件:#include "Components/CapsuleComponent.h"
GetCapsuleComponent()->SetCapsuleRadius(40.0f);
GetCapsuleComponent()->SetCapsuleHalfHeight(50.0f);
// 使用GetCharacterMovement(),需要引入的头文件:#include "GameFramework/CharacterMovementComponent.h"
GetCharacterMovement()->MaxWalkSpeed = 50.0f;
// 使用 GetCapsuleComponent() ,需要引入的头文件:#include "Components/CapsuleComponent.h"
// 第一个参数是当前类,第二个参数是 要绑定的函数
// 注册碰撞函数
GetCapsuleComponent()->OnComponentBeginOverlap.AddDynamic(this, &APacManCharacter::OnCollision);
// EditDefaultsOnly 可以在编辑器里面编辑,EditDefaultsOnly 只能对其原型进行修改;Category 分类
// VisibleAnywhere 在任何地方都可以看到它,创建实例后,仍然可以修改它;不改成VisibleAneywhere,无法修改其材质
UPROPERTY(VisibleAnywhere, Category = Collectable)
UStaticMeshComponent* CollectableMesh;
// EditAnyWhere 不仅可以对其原型进行修改,还可以对其实例修改
UPROPERTY(EditAnywhere, Category = Collectable)
bool bIsSuperCollectable;
// UFont 字体,显示的文字,字体,为了寻找字体方便,修改字体方便,一个蓝图类来继承它,在蓝图中修改字体
// EditAnyWhere 在哪块都能修改
// BlueprintReadWrite 表示可以在蓝图中修改这个属性/定义
// Category 分类,分到 HUDFont 类中去
UPROPERTY(EditAnyWhere,BlueprintReadWrite,Category=HUDFont)
#include "Public/TimerManager.h"
GetWorldTimerManager().ClearTimer(TimeVulnerable);
AIEnemy.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "AIController.h"
#include "Enemy.h"
#include "PacManGameModeBase.h"
#include "AIEnemy.generated.h"
/**
*
*/
UCLASS()
class PACMAN_API AAIEnemy : public AAIController
{
GENERATED_BODY()
public:
// 要重写的函数
// 相当于beginplay,每当开启一个AI的时候调用,首先执行OnPossess
void OnPossess(class APawn* InPawn) override;
// 移动停止后调用
virtual void OnMoveCompleted(FAIRequestID RequestID, const FPathFollowingResult& Result) override;
void SearchNewPoint();
void GoHome();
void ReArm();
void StopMove();
private:
class AEnemy* Bot;
FVector HomeLocation;
FTimerHandle DeadTime;
APacManGameModeBase* GameMode;
};
AIEnemy.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "Public/AIEnemy.h"
#include "NavigationSystem.h"
#include "Public/TimerManager.h"
#include "Kismet/GameplayStatics.h"
void AAIEnemy::OnPossess(class APawn* InPawn)
{
Super::OnPossess(InPawn);
// 获得Enemy,肉体
Bot = Cast<AEnemy>(InPawn);
HomeLocation = Bot->GetActorLocation();
// 获取GameMode // UGameplayStatics 需要引入 #include "Kismet/GameplayStatics.h"
GameMode = Cast<APacManGameModeBase>(UGameplayStatics::GetGameMode(this));
SearchNewPoint();
}
void AAIEnemy::OnMoveCompleted(FAIRequestID RequestID, const FPathFollowingResult & Result)
{
// 当敌人不是死亡的时候 并且 游戏不是暂停的时候
if (!Bot->bIsDead &&GameMode->GetCurrentState() != EGameState::EPause)
{
// 找新的随机点
SearchNewPoint();
}
}
void AAIEnemy::SearchNewPoint()
{
// 判断导航网格在不在
UNavigationSystemV1* NavMesh = UNavigationSystemV1::GetCurrent(this);
// 如果在
if (NavMesh)
{
// 设置搜索半径
// 1000.0f 太小了,改成 10000.0f
const float SearchRadius = 10000.0f;
// 设置一个点
FNavLocation RandomPt;
// 以敌人的位置为中心,这个半径为范围,找一个点,
const bool bFound = NavMesh->GetRandomReachablePointInRadius(Bot->GetActorLocation(), SearchRadius, RandomPt);
// 如果能找到
if (bFound)
{
// 移动到这个点
MoveToLocation(RandomPt);
}
}
}
void AAIEnemy::GoHome()
{
MoveToLocation(HomeLocation);
GetWorldTimerManager().SetTimer(DeadTime, this, &AAIEnemy::ReArm, 5.0f, false);
}
void AAIEnemy::ReArm()
{
GetWorldTimerManager().ClearTimer(DeadTime);
Bot->ReArm();
}
void AAIEnemy::StopMove()
{
//StopMovement();
MoveToLocation(Bot->GetActorLocation());
}
Collectables.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Components/SphereComponent.h"
#include "Components/StaticMeshComponent.h"
#include "Collectables.generated.h"
UCLASS()
class PACMAN_API ACollectables : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
ACollectables();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
// EditDefaultsOnly 可以在编辑器里面编辑,EditDefaultsOnly 只能对其原型进行修改;Category 分类
// VisibleAnywhere 在任何地方都可以看到它,创建实例后,仍然可以修改它;不改成VisibleAneywhere,无法修改其材质
UPROPERTY(VisibleAnywhere, Category = Collectable)
UStaticMeshComponent* CollectableMesh;
UPROPERTY(EditDefaultsOnly, Category = Collectable)
USphereComponent* BaseCollisionComponent;
// EditAnyWhere 不仅可以对其原型进行修改,还可以对其实例修改
UPROPERTY(EditAnywhere, Category = Collectable)
bool bIsSuperCollectable;
};
Collectables.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "Public/Collectables.h"
#include "Public/UObject/ConstructorHelpers.h"
// Sets default values
ACollectables::ACollectables()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
// 等于true,会使得下面这个函数(Tick)每帧运行,这个是豆的,不需要这个,设置成false
PrimaryActorTick.bCanEverTick = false;
// 开启碰撞功能(默认不开启碰撞功能)
SetActorEnableCollision(true);
// 创建网格组件
CollectableMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("CollectableMesh"));
// 创建碰撞体组件
BaseCollisionComponent = CreateDefaultSubobject<USphereComponent>(TEXT("BaseCollisionComponent"));
// 将 碰撞体 和 网格 绑定到一起
CollectableMesh->AttachTo(BaseCollisionComponent);
// 使用 ConstructorHelpers 需要引入的头文件:#include "Public/UObject/ConstructorHelpers.h" 找到了想要的变成的球体
static ConstructorHelpers::FObjectFinder<UStaticMesh> Sphere(TEXT("StaticMesh'/Engine/BasicShapes/Sphere.Sphere'"));
if (Sphere.Succeeded())
{
CollectableMesh->SetStaticMesh(Sphere.Object);
}
// 指定球的大小和尺寸
CollectableMesh->SetWorldScale3D(FVector(0.3, 0.3, 0.3));
BaseCollisionComponent->SetSphereRadius(16);
}
// Called when the game starts or when spawned
void ACollectables::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void ACollectables::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
Enemy.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "Components/StaticMeshComponent.h"
#include "Enemy.generated.h"
UCLASS()
class PACMAN_API AEnemy : public ACharacter
{
GENERATED_BODY()
public:
// Sets default values for this character's properties
AEnemy();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
// Called to bind functionality to input
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
UPROPERTY(VisibleAnywhere,Category=Body)
UStaticMeshComponent* EnemyBody;
/*
Vulnerable adj. 易受攻击的;易受伤害的;脆弱的;有局方的;有身价的
InVulnerable adj. 不能伤害的;刀枪不入的;无懈可击的;不可攻破的
*/
// 易受攻击
void SetVulnerable();
// 不易受攻击
void SetInVulnerable();
// 是否移动
void SetMove(bool bMoveIt);
// 被杀死,回出生点
void Killed();
// 速度回到150
void ReArm();
// 敌人是否死亡
bool bIsDead;
UFUNCTION()
void OnCollision(class UPrimitiveComponent* HitComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult);
private:
// 默认材质
class UMaterialInterface* DefaultMaterial;
// 能被主角吃掉的时候的材质
// 容易收到主角攻击
class UMaterialInterface* VulnerableMaterial;
FTimerHandle TimeVulnerable;
// 定义一个变量来判断当前的状态
bool bIsVulnerable;
};
Enemy.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "Public/Enemy.h"
#include "UObject/ConstructorHelpers.h"
#include "Components/CapsuleComponent.h"
#include "Public/TimerManager.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "Public/PacManCharacter.h"
#include "Public/AIEnemy.h"
// Sets default values
AEnemy::AEnemy()
{
// Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
// 显示组件
EnemyBody = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Body"));
// 创建样子
// 找到对应的材质
static ConstructorHelpers::FObjectFinder<UStaticMesh> CylinderObj(TEXT("'/Game/StarterContent/Shapes/Shape_Cylinder'"));
// 成功找到就
// Succeeded()需要加括号
if (CylinderObj.Succeeded())
{
// 指定它的样子
EnemyBody->SetStaticMesh(CylinderObj.Object);
}
// 设置它的大小
EnemyBody->SetRelativeScale3D(FVector(0.7f, 0.7f, 1.0f));
// 使得碰撞体和圆柱体重合在一起
// CapsuleComponent 和 UStaticMeshComponent 重合
EnemyBody->SetRelativeLocation(FVector(0, 0, -50));
// 绑定到根组件上
// AttachTo 过时了,换成:SetupAttachment
EnemyBody->SetupAttachment(RootComponent);
// 设置碰撞体的大小
// 使用GetCapsuleComponent,需要引入头文件:#include "Components/CapsuleComponent.h"
GetCapsuleComponent()->SetCapsuleRadius(40.0f);
GetCapsuleComponent()->SetCapsuleHalfHeight(50.0f);
static ConstructorHelpers::FObjectFinder<UMaterial> VulnerableMat(TEXT("'/Game/Materials/M_Enemy_Vulnerable'"));
// 获得AI,设置好AIController
AIControllerClass = AAIEnemy::StaticClass();
// 启用碰撞函数
SetActorEnableCollision(true);
}
// Called when the game starts or when spawned
void AEnemy::BeginPlay()
{
Super::BeginPlay();
// 获得当前的材质
DefaultMaterial = EnemyBody->GetMaterial(0);
// 注册碰撞函数
GetCapsuleComponent()->OnComponentBeginOverlap.AddDynamic(this, &AEnemy::OnCollision);
// 刚开始的速度太大了,设定初始的速度小一些
GetCharacterMovement()->MaxWalkSpeed = 150.0f;
}
// Called every frame
void AEnemy::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
// Called to bind functionality to input
void AEnemy::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
}
void AEnemy::SetVulnerable()
{
// 吃到豆子可以增加10
// 过一段时间可以不受攻击
// 使用GetWorldTimerManager(),需要引入头文件:#include "Public/TimerManager.h"
// 第一个参数是TimeVulnerable;第二个参数:作用在哪个类;第三个参数:作用于哪个函数;第四个参数:时间间隔;第五个参数:是否循环
GetWorldTimerManager().SetTimer(TimeVulnerable, this, &AEnemy::SetInVulnerable, 10.0f, false);
if (bIsVulnerable)
{
return;
}
bIsVulnerable = true;
// 连续吃到豆子,敌人当前的状态已经设置成了易受攻击的状态
// 没必要执行 EnemyBody->SetMaterial(0, VulnerableMaterial);
// 定义一个变量来判断当前的状态,已经是易受到攻击的状态,没必要设置材质了
// 时间段可以从10秒变成20秒外,剩下的都不需要再改变了
EnemyBody->SetMaterial(0, VulnerableMaterial);
// 使用GetCharacterMovement(),需要引入的头文件:#include "GameFramework/CharacterMovementComponent.h"
GetCharacterMovement()->MaxWalkSpeed = 50.0f;
}
void AEnemy::SetInVulnerable()
{
GetWorldTimerManager().ClearTimer(TimeVulnerable);
bIsVulnerable = false;
EnemyBody->SetMaterial(0, DefaultMaterial);
GetCharacterMovement()->MaxWalkSpeed = 150.0f;
}
// 是否移动
void AEnemy::SetMove(bool bMoveIt)
{
// 获得AI
// 最后括号里面的AIControllerClass弃用 换成 GetController()
AAIEnemy* AI = Cast<AAIEnemy>(GetController());
// 移动
if (bMoveIt)
{
// 找下一个点
AI->SearchNewPoint();
}
else
{
// 停止移动
AI->StopMove();
}
}
void AEnemy::Killed()
{
if (bIsDead)
{
return;
}
bIsDead = true;
GetCharacterMovement()->MaxWalkSpeed = 300.0f;
// 获得AI
AAIEnemy* AI = Cast<AAIEnemy>(GetController());
// 让敌人回家
AI->GoHome();
}
void AEnemy::ReArm()
{
bIsDead = false;
GetCharacterMovement()->MaxWalkSpeed = 150.0f;
if (bIsVulnerable)
{
SetInVulnerable();
}
// 重新出来
SetMove(true);
}
void AEnemy::OnCollision(UPrimitiveComponent * HitComp, AActor * OtherActor, UPrimitiveComponent * OtherComp, int OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult)
{
// #include "Public/PacManCharacter.h"
if (OtherActor->IsA(APacManCharacter::StaticClass()))
{
if (bIsVulnerable)
{
Killed();
}
else
{
APacManCharacter* PacMan = Cast<APacManCharacter>(OtherActor);
PacMan->Killed();
}
}
}
PacManCharacter.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "PacManGameModeBase.h"
#include "PacManCharacter.generated.h"
UCLASS()
class PACMAN_API APacManCharacter : public ACharacter
{
GENERATED_BODY()
public:
// Sets default values for this character's properties
APacManCharacter();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
// Called to bind functionality to input
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
void MoveXAxis(float AxisValue);
void MoveYAxis(float AxisValue);
// 重启游戏
void ReStart();
// 重玩一局游戏
void NewGame();
// 暂停游戏
void Pause();
// 主角死亡
void Killed();
// 最后2个参数可写可不写
// 需要注意的是 class AActor* otherActor ,碰撞的物体是不是敌人or食物
// 使用了反射机制,需要添加关键字 UFUNCTION()
UFUNCTION()
void OnCollision(class UPrimitiveComponent* HitComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult);
// 下面这个2个,改成了Public可供PacManHUD显示调用
// 需要吃的 豆 的数量
int CollectablesToEat;
// 当前的生命值
int Lives;
private:
// 定义一个向量
FVector CurrentVelocity;
// 初始的位置
FVector StartPoint;
//
APacManGameModeBase* GameMode;
};
PacManCharacter.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "Public/PacManHUD.h"
#include "PacManGameModeBase.h"
#include "Kismet/GameplayStatics.h"
#include "Engine/Canvas.h"
#include "Public/PacManCharacter.h"
void APacManHUD::DrawHUD()
{
// 获得当前的游戏模式
class APacManGameModeBase* GameMode = Cast<APacManGameModeBase>(UGameplayStatics::GetGameMode(this));
// 根据不同的状态,显示不同的文字
switch (GameMode->GetCurrentState())
{
case EGameState::EMenu:
// 显示文字的函数,
// 第一个参数:需要显示的文字;
// 第二个参数:文字的颜色;
// 第三个参数:获得横的屏幕的宽度;
// 第四个参数:获得纵的屏幕的长度
// 第五个参数:显示的字体
// (Canvas->SizeX/2.0f) 就是在屏幕中间
// 使用 Canvas 需要引入头文件:#include "Engine/Canvas.h"
// 向下,向右为正方向,为了移动正中心,进行了减法运算到屏幕中间
DrawText(TEXT("Welcome To PacMan!\n\nN to start a new game \nP to pause the game"), FColor::White, (Canvas->SizeX / 2.0f) - 150.0f, (Canvas->SizeY / 2.0f) - 100.0f, HUDFont);
break;
case EGameState::EPlaying:
{// 这个括号需要
// 获得主角,0 表示第一个玩家,场景只有一个玩家
APacManCharacter* PacMan = Cast<APacManCharacter>(UGameplayStatics::GetPlayerPawn(this, 0));
if (PacMan)
{
// FString::FromInt() 将 int类型的变量转换成字符串
FString LiveString = TEXT("Lives: ") + FString::FromInt(PacMan->Lives);
DrawText(LiveString, FColor::Green, 50, 50, HUDFont);
FString CollectablesToEatString = TEXT("CollectablesToEat: ") + FString::FromInt(PacMan->CollectablesToEat);
DrawText(CollectablesToEatString, FColor::Green, Canvas->SizeX - 150, 50, HUDFont);
}
}// 这个括号需要
break;
case EGameState::EPause:
DrawText(TEXT("P To Continue"), FColor::White, (Canvas->SizeX / 2.0f) - 150.0f, (Canvas->SizeY / 2.0f) - 100.0f, HUDFont);
break;
case EGameState::EWin:
DrawText(TEXT("You Win!\n\n R for another"), FColor::White, (Canvas->SizeX / 2.0f) - 150.0f, (Canvas->SizeY / 2.0f) - 100.0f, HUDFont);
break;
case EGameState::EGameOver:
DrawText(TEXT("CameOver!\n\nR for another"), FColor::White, (Canvas->SizeX / 2.0f) - 150.0f, (Canvas->SizeY / 2.0f) - 100.0f, HUDFont);
break;
default:
break;
}
}
PacManGameModeBase.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/GameModeBase.h"
#include "Public/Enemy.h"
#include "PacManGameModeBase.generated.h"
/**
*
*/
enum class EGameState : short {
EMenu,
EPlaying,
EPause,
EWin,
EGameOver
};
UCLASS()
class PACMAN_API APacManGameModeBase : public AGameModeBase
{
GENERATED_BODY()
public:
// 但是由于我们的碰撞在,吃食物在,当前的状态是EPlaying,游戏中的时候才能吃食物,物体才会被销毁,把当前的状态设置成EPlaying,这样方便测试了
virtual void BeginPlay() override;
// 获得当前状态 加 const 不能修改我们的成员
EGameState GetCurrentState() const;
// 设置当前状态
void SetCurrentState(EGameState value);
// 易受攻击的方法
void SetEnemyVulnerable();
private:
// 要知道当前状态,才能做出不同的反应
EGameState currentState;
// 定义一个数组,保存所有的敌人
TArray<class AEnemy*> Enemys;
};
// 为了程序更加快捷,定义一个 内联
// APcManGameModeBase 和 命名的项目名称一致,视频中的AMyPacManGameModeBase,项目名称为:MyPacMan
FORCEINLINE EGameState APacManGameModeBase::GetCurrentState() const
{
return currentState;
};
PacManGameModeBase.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "PacManGameModeBase.h"
#include "Public/EngineUtils.h"
// 设置当前状态
void APacManGameModeBase::SetCurrentState(EGameState value)
{
currentState = value;
// 判断暂停等状态
// 输入switch,Tab 两下,在switch_on中按住Tab输入value,然后回车,自动补全
switch (value)
{
case EGameState::EPlaying:
// 遍历所有的敌人
for (auto Iter(Enemys.CreateIterator()); Iter; Iter++)
{
// 可以移动
(*Iter)->SetMove(true);
}
break;
case EGameState::EPause:
// 遍历所有的敌人
for (auto Iter(Enemys.CreateIterator()); Iter; Iter++)
{
// 不可以移动
(*Iter)->SetMove(false);
}
break;
case EGameState::EWin:
// 遍历所有的敌人
for (auto Iter(Enemys.CreateIterator()); Iter; Iter++)
{
// 销毁敌人
(*Iter)->Destroy();
}
break;
case EGameState::EGameOver:
// 遍历所有的敌人
for (auto Iter(Enemys.CreateIterator()); Iter; Iter++)
{
// 销毁敌人
(*Iter)->Destroy();
}
break;
default:
break;
}
}
// 易受攻击的事情,用 GameMode 来处理所有的敌人,在 Character 中直接调用 GameMode 的这个方法,就可以把所有的敌人都设置成易受到攻击的状态,而不必分别设置了
// 设置成易受攻击,被主角吃的行为就好了
void APacManGameModeBase::SetEnemyVulnerable()
{
// 遍历所有的Enemy,调用它身上的SetVulnerable方法就可以了
// Iter 表示存在的话,Iter++
for (auto Iter(Enemys.CreateIterator()); Iter; Iter++)
{
// 调用它身上的SetVulnerable方法
(*Iter)->SetVulnerable();
}
}
void APacManGameModeBase::BeginPlay()
{
// 设置成菜单模式,开局有UI提示
SetCurrentState(EGameState::EMenu);
// 使用迭代器,需要引入头文件:Public/EngineUtils.h
// 获得所有的敌人 ;起个名字:enemyItr; GetWorld():从世界得到; enemyItr 存在的话就去遍历
for (TActorIterator<AEnemy> enemyItr(GetWorld()); enemyItr; ++enemyItr)
{
// 强制转化成 AEnemy
AEnemy* enemy = Cast<AEnemy>(*enemyItr);
// 转化后,看存不存在
if (enemy)
{
// 如果存在的话,就添加到数组里面
Enemys.Add(enemy);
}
}
}
使用 UGameplayStatics 需要引入头文件 #include "Kismet/GameplayStatics.h"
使用 UNavigationSystemV1* 需要引入头文件 #include "NavigationSystem.h"
使用 GetWorldTimerManager() 需要引入头文件 #include "Public/TimerManager.h"
使用 ConstructorHelpers 需要引入头文件:#include "Public/UObject/ConstructorHelpers.h"
使用 ConstructorHelpers 需要引入头文件 #include "UObject/ConstructorHelpers.h"
使用 GetCapsuleComponent,需要引入头文件:#include "Components/CapsuleComponent.h"
使用 GetCharacterMovement(),需要引入头文件:#include "GameFramework/CharacterMovementComponent.h"
使用 GetWorld() 需要引入头文件:#include "Engine/World.h"
使用 TActorIterator 需要引入头文件:#include "Public/EngineUtils.h"
使用 InputComponent.BindAxis() 和 BindAction() 需要引入头文件:#include "Components/InputComponent.h"
使用 Canvas 需要引入头文件:#include "Engine/Canvas.h"
使用 USphereComponent* 需要引入头文件:#include "Components/SphereComponent.h"
使用 UStaticMeshComponent* 需要引入头文件:#include "Components/StaticMeshComponent.h"
UPROPERTY(VisibleAnywhere, Category = Collectable)
UPROPERTY(EditDefaultsOnly, Category = Collectable)
UPROPERTY(EditAnywhere, Category = Collectable)
UPROPERTY(VisibleAnywhere,Category=Body)
UFUNCTION()
void OnCollision(class UPrimitiveComponent* HitComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult);
UPROPERTY(EditAnyWhere,BlueprintReadWrite,Category=HUDFont)