UE4小游戏4
记录UE4小游戏
创建一个继承与AIController的AIEnemy用于控制Enemy,Enemy类负责做状态的转换。
Enemy.h
Enemy.cpp
// Fill out your copyright notice in the Description page of Project Settings.//#include "Enemy.h" #include "..\Public\Enemy.h" #include "UObject/ConstructorHelpers.h" #include "Components/CapsuleComponent.h" //#include "GameFramework/Actor.h" #include "TimerManager.h" #include "..\Public\AIEnemy.h" #include "GameFramework/CharacterMovementComponent.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;//创建bodyEnemyBody = CreateDefaultSubobject<UStaticMeshComponent> (TEXT("Body"));//用圆柱绑定外形static ConstructorHelpers::FObjectFinder<UStaticMesh> CylinderObj(TEXT("'/Game/StarterContent/Shapes/Shape_Cylinder'"));if (CylinderObj.Succeeded()){EnemyBody->SetStaticMesh(CylinderObj.Object);}//设置大小EnemyBody->SetWorldScale3D(FVector(0.7f, 0.7f, 1.0f));EnemyBody->SetRelativeLocation(FVector(0, 0, -50.0f));//为了和碰撞体适配下移动EnemyBody->SetupAttachment(RootComponent);//绑定为默认根组件//设置碰撞体大小GetCapsuleComponent()->SetCapsuleRadius(40.0f);GetCapsuleComponent()->SetCapsuleHalfHeight(50.0f); //绑定材质static ConstructorHelpers::FObjectFinder<UMaterial> VulnerableMat(TEXT("Material'/Game/Materials/M_Enemy_Vulnerable.M_Enemy_Vulnerable'"));if (VulnerableMat.Succeeded()){VulnerableMaterial = Cast<UMaterialInterface>(VulnerableMat.Object);}//BaseCollisionComponent->SetSphereRadius(16); //开启碰撞SetActorEnableCollision(true);AIControllerClass = AAIEnemy::StaticClass(); }// 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;//VulnerableMaterial//VulnerableMaterial = EnemyBody->GetMaterial(0, VulnerableMat);//SetVulnerable();}// 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() {GetWorldTimerManager().SetTimer(TimeVulnerable, this, &AEnemy::SetInVulnerable, 10.0f, false);//每隔TimeVulnerable时间变为SetInVulnerableif (bIsVulnerable)return;bIsVulnerable = true;EnemyBody->SetMaterial(0, VulnerableMaterial);GetCharacterMovement()->MaxWalkSpeed = 50.0f; }void AEnemy::SetInVulnerable() {//清楚TimeVulnerableGetWorldTimerManager().ClearTimer(TimeVulnerable);bIsVulnerable = false;EnemyBody->SetMaterial(0, DefaultMaterial);GetCharacterMovement()->MaxWalkSpeed = 150.0f; }void AEnemy::SetMove(bool bMoveIt) { //用AIEnemy来控制EnemyAAIEnemy* AI = Cast<AAIEnemy>(GetController());if (bMoveIt){AI->SearchNewPoint();}else {AI->StopMove();} }void AEnemy::Killed() {if (bIsDead) {return;}bIsDead = true;GetCharacterMovement()->MaxWalkSpeed = 300.0f;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) {if (OtherActor->IsA(APacManCharacter::StaticClass())){if (bIsVulnerable) {Killed();}else{APacManCharacter* PacMan = Cast<APacManCharacter>(OtherActor);PacMan->Killed();}} }AIEnemy.h
// Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h" #include "AIController.h" #include "..\Public\Enemy.h" #include "..\MypacmanGameModeBase.h" #include "..\Public\PacManCharacter.h" #include "AIEnemy.generated.h"/*** */ UCLASS() class MYPACMAN_API AAIEnemy : public AAIController {GENERATED_BODY()public:void OnPossess(class APawn* InPawn) override; //==beginplayvirtual void OnMoveCompleted(FAIRequestID RequestID, const FPathFollowingResult& Result) override;//移动停止做什么void SearchNewPoint();void GoHome();void ReArm();//void StopMove();private:class AEnemy* Bot;FVector HomeLocation;FTimerHandle DeadTime;AMypacmanGameModeBase* GameMode; };AIEnemy.cpp
// Fill out your copyright notice in the Description page of Project Settings.//#include "AIEnemy.h" #include "..\Public\AIEnemy.h" #include "NavigationSystem.h" #include "Kismet/GameplayStatics.h" #include "TimerManager.h"void AAIEnemy::OnPossess(class APawn* InPawn) {Super::OnPossess(InPawn);Bot = Cast<AEnemy>(InPawn);HomeLocation = Bot->GetActorLocation();SearchNewPoint();GameMode = Cast<AMypacmanGameModeBase>(UGameplayStatics::GetGameMode(this));}void AAIEnemy::OnMoveCompleted(FAIRequestID RequestID, const FPathFollowingResult & Result) {if (!Bot->bIsDead && GameMode->GetCurrentState()!=EGameState::Epause) {SearchNewPoint();} } //这个函数很重要,最好看下底层源码 void AAIEnemy::SearchNewPoint() {UNavigationSystemV1* NavMesh = FNavigationSystem::GetCurrent<UNavigationSystemV1>(this);if (NavMesh) {const float SearchRadius = 10000.0f;FNavLocation RandomPt;const bool bFound = NavMesh->GetRandomReachablePointInRadius(Bot->GetActorLocation(), SearchRadius, RandomPt);//const bool bFound = NavMesh->GetRandomReachablePointInRadius(myPacMan->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()); }这里还需要改个东西
MypacmanGameModeBase.h
AMypacmanGameModeBase.cpp
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.#include "MypacmanGameModeBase.h" #include "Public/Enemy.h" #include "EngineUtils.h"void AMypacmanGameModeBase::SetCurrentState(EGameState value) {currentState = 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::EGameOver:for (auto Iter(Enemys.CreateIterator()); Iter; ++Iter){(*Iter)->Destroy();}break;case EGameState::EWin:for (auto Iter(Enemys.CreateIterator()); Iter; ++Iter){(*Iter)->Destroy();}break;default:break;} } void AMypacmanGameModeBase::SetEnemyVulnerable() {for (auto Iter(Enemys.CreateIterator()); Iter; ++Iter){(*Iter)->SetVulnerable();} } void AMypacmanGameModeBase::BeginPlay() {Super::BeginPlay();SetCurrentState(EGameState::EMenu);for (TActorIterator<AEnemy> enemyIter(GetWorld()); enemyIter; ++enemyIter){AEnemy* enemy = Cast<AEnemy>(*enemyIter);if (enemy){Enemys.Add(enemy);}}}总结
- 上一篇: 上海车展观察:城市导航辅助驾驶进入落地阶
- 下一篇: 想通过培训转行软件测试可以吗