Unreal Engine C++ Developer: Learn C++ and Make Video Games | Udemy UE4.26 Simple Shooterで自分なりに理解したこと。01300 ~NavMeshとAIの動き~

NavMeshを配置して

表示できるようにします。

表示されました。

ブラシセッティングで広げます。

BP_ShooterAIControllerを開いてPathFollowingComponentが作用しているからです。

C:\Program Files\Epic Games\UE_4.26\Engine\Source\Runtime\AIModule\Classes\AIController.h

MoveToを見ると

MoveToActor

MoveToLocation

MoveTo

の3つがあります。

	/** AIを指定されたゴールアクターに向けて移動させ(宛先は継続的に更新されます)、
次のアクティブなパスを中止します
* @ paramAcceptanceRadius-ポーンが十分に近づいたら移動を終了します
* @ parambStopOnOverlap-ポーンの半径をAcceptanceRadiusに追加します
* @param bUsePathfinding-ナビゲーションデータを使用してパスを計算します
(そうでない場合は直線になります)
* @param bCanStrafe-フォーカス関連フラグを設定します:bAllowStrafe
* @ paramFilterClass-パスファインディング調整用のナビゲーションフィルター。
指定されていない場合、DefaultNavigationFilterClassが使用されます
* @ parambAllowPartialPath-目標に到達できない場合は不完全なパスを使用します
* @note AcceptanceRadiusは、ヘッダーパーサーが
UPathFollowingComponent :: DefaultAcceptanceRadiusを認識できないため、
デフォルト値または-1になります。*/
	UFUNCTION(BlueprintCallable, Category = "AI|Navigation", Meta = (AdvancedDisplay = "bStopOnOverlap,bCanStrafe,bAllowPartialPath"))
	EPathFollowingRequestResult::Type MoveToActor(AActor* Goal, float AcceptanceRadius = -1, bool bStopOnOverlap = true,
		bool bUsePathfinding = true, bool bCanStrafe = true,
		TSubclassOf<UNavigationQueryFilter> FilterClass = NULL, bool bAllowPartialPath = true);

なので

\ShooterAIController.cpp

// Fill out your copyright notice in the Description page of Project Settings.


#include "ShooterAIController.h"

#include "Kismet\GameplayStatics.h"

void AShooterAIController::BeginPlay()
{
    Super::BeginPlay();
    APawn* PlayerPawn= UGameplayStatics::GetPlayerPawn(GetWorld(),0);

    SetFocus(PlayerPawn);
    MoveToActor(PlayerPawn,200);

}

これでプレイしてみると一度動きます。が一度しかついてきません。

C:\Program Files\Epic Games\UE_4.26\Engine\Source\Runtime\Engine\Classes\GameFramework\Actor.h

	virtual void Tick( float DeltaSeconds );

をコピーしてShooterAIController.hにTickをオーバーライドしてこうしました。

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "AIController.h"
#include "ShooterAIController.generated.h"

/**
 * 
 */
UCLASS()
class SIMPLESHOOTERCP2_API AShooterAIController : public AAIController
{
	GENERATED_BODY()
public:
	virtual void Tick( float DeltaSeconds ) override;

protected:
	virtual void BeginPlay() override;	
};

C:\Download\Game\SImpleShooter\SImpleShooterCp2 4.26\Source\SImpleShooterCp2\ShooterAIController.cpp

// Fill out your copyright notice in the Description page of Project Settings.


#include "ShooterAIController.h"

#include "Kismet\GameplayStatics.h"

void AShooterAIController::BeginPlay()
{
    Super::BeginPlay();
    //APawn* PlayerPawn= UGameplayStatics::GetPlayerPawn(GetWorld(),0);

    
}
void AShooterAIController::Tick(float DeltaSecond)
{
    APawn* PlayerPawn= UGameplayStatics::GetPlayerPawn(GetWorld(),0);
    SetFocus(PlayerPawn);
    MoveToActor(PlayerPawn,200);

}

NavMeshを広げておかないとAIキャラクターが歩きにくいみたいです

できたのがこれ、

AIキャラクターが回転しないバグは次のときに説明するみたい。

Unreal Engine C++ Developer: Learn C++ and Make Video Games | Udemy UE4.25 Simple Shooterで自分なりに理解したこと。00600 ~Actorにダメージを与える~

今回はアクターにダメージを与えるので
UE4/Engine/Source/Runtime/Engine/Classes/GameFramwork/Actor.h

が持っているTakeDamageを使う

/ **
*このアクターにダメージを与えます。
* @see https://www.unrealengine.com/blog/damage-in-ue4
* @paramDamageAmount適用するダメージの量
* @paramDamageEvent受けたダメージを完全に説明するデータパッケージ。
* @paramEventInstigator損傷の原因となったコントローラー。
* @param DamageCauserダメージを直接引き起こしたアクター(爆発した発射物、着地した岩など)
* @ return実際に適用されたダメージの量。
* /
/**
	 * Apply damage to this actor.
	 * @see https://www.unrealengine.com/blog/damage-in-ue4
	 * @param DamageAmount		How much damage to apply
	 * @param DamageEvent		Data package that fully describes the damage received.
	 * @param EventInstigator	The Controller responsible for the damage.
	 * @param DamageCauser		The Actor that directly caused the damage (e.g. the projectile that exploded, the rock that landed on you)
	 * @return					The amount of damage actually applied.
	 */
	virtual float TakeDamage(float DamageAmount, struct FDamageEvent const& DamageEvent, class AController* EventInstigator, AActor* DamageCauser);

で引数にあるDamageEventはたくさん種類あるみたい。

今回は銃なのでFPointDamageEventを使った。

FPointDamageEvent DamageEvent(Damage,Hit,ShotDirection,nullptr);

でアクターにヒットしたときTakeDamageを呼ぶというのはこうなる。

		AActor* HitActor= Hit.GetActor();
		if (HitActor!=nullptr)
		{
			FPointDamageEvent DamageEvent(Damage,Hit,ShotDirection,nullptr);
			HitActor->TakeDamage(Damage,DamageEvent,OwnerController,this);
		}

絵的にはなにもかわりません。