5595人加入学习
(18人评价)
【旧版】Unreal初级课程 - 3D吃豆人

旧版课程,制作完成于2018-03-29,基于Unreal 4.18

价格 免费

在【模式】搜索Sound, 选择【环境音效】拖放到关卡中,在细节面板指定 WAV 的音效文件,即可播放BGM;

其他音乐格式转换的WAV的网站:

https://www.media.io/

// 获取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)

[展开全文]

授课教师

SIKI学院老师

课程特色

图文(1)
下载资料(1)
视频(30)