[UE5][C++]Python からブループリント関数を呼び出すことはできますか?

現時点では、Python はブループリント関数にアクセスできませんが、C++ メソッドにはアクセスできます。したがって
、解決策としては、C++ でブループリント関数を として宣言しBlueprintImplementableEvent、ブループリントでそれをオーバーライドします。

BlueprintImplementableEvent先に進む前に、を C++ から呼び出して、それが機能するかどうかを確認することをお勧めします。
次に、 を呼び出すための 2 番目の C++ 関数を作成しますBlueprintImplementableEvent。この関数は、Python に公開されるものであるため、
として実装する必要があります。BlueprintCallable

最後に、C++ とブループリントがコンパイルされたら、Python から呼び出し元関数を呼び出すだけです。
C++ クラスは、次のように通常の C++ モジュールとして表示されます。unreal.YourClassName.yourCallerFunctionName(yourClassInstance, args)
引数と戻り値は、期待どおりに処理されます。
関数を実行するクラス インスタンスを関数に渡す必要があります。特定の AActor インスタンスを操作するときに非常に便利です。


最後にもう 1 つ注意点があります。関数を、私が行ったようにブループリントイベントではなくブループリント関数として実装する必要がある場合は、関数を定数にするか、戻り値 (使用しない場合でも) を指定する必要があります。そうしないと、ブループリントのオーバーライドにイベントとして表示されます。

私のユースケースからの画面。明らかに、ブループリント関数の実装の詳細は関係ありません。
ブループリント関数

.h

.cpp

.py

参考

https://forums.unrealengine.com/t/is-it-possible-to-call-a-blueprint-function-from-python/447078/3

[UnrealEngine]C++ シンプルなクラス構文

クラスの定義はヘッダファイルで行います。

#include <string>
using namespace std;
class Class1
{
// 
private:
	string name; //メンバ変数
// 
public:
	void print1(); //メンバ関数のプロトタイプ宣言
	void print2(); //メンバ関数のプロトタイプ宣言
// 
};

cppでのメソッドの実装

void クラス::実装するメソッド名()

#include "Class1.h"
#include <iostream>
using namespace std;

// 
void Class1::print1()
{
	name = "print1";
	cout << name << "が処理されました\n";

	return;
}
// 
void Class1::print2()
{
	name = "print2";
	cout << name << "が処理されました。どうしてニンニク味のガムってないんだろう?\n";

	return;
}

クラスからインスタンスを生成して利用するサンプルです。

Class1 *インスタンス名 = new Class1();

インスタンス名 – > 使用するメソッド名();

#include "Class1.h"

int main() {

	Class1 *cla2 = new Class1();
	cla2->print1(); //print1が処理されました
	cla2->print2(); //print2が処理されました
	delete cla2;

	return 0;
}

AmbitionEarlyHourSky

#アンリアルクエスト に出したゲームのクオリティをアップした。

キャラクターの作り直しを何度もやった。

ハイヒールのカラーをルブタンみたいにして

ニーアみたいなマスクをつけて
kawaiiphysicsでスカートをひらひらさせた。
kawaiiphysicsで胸も揺らした
kawaiiphysicsで髪をなびくようにジョイントを入れ

レベルデザインも少しちゃんとした。

#kawaiiphysics #UE4 #Unrealお兄さん と#塩谷さん と #おかず さん の おかげです。

ダウンロードはこちら

https://drive.google.com/file/d/1q6O0NIBkd-oH1zD50XCDv74sUi6QfIai/view?usp=sharing

最近開いてみたらこんなエラーが出た

This Project requires the ‘ShallowWater’ plugin whitch could not be found.Would you like to desable it continue?If you do you will no longer be able to open any assets created with it. if not the application will close.

このプロジェクトには、見つからなかった「ShallowWater」プラグインが必要です。引き続き無効にしますか?そうすると、それで作成されたアセットを開くことができなくなります。 そうでない場合、アプリケーションは終了します。

ビルドの必要がありそうなので

A案

cd C:\Program Files\Epic Games\UE_5.0\Engine\Build\BatchFiles
Build.bat AmbitionEarlyHourSky Win64 Development "F:\Download\Game\AmbitionEarlyHourSky6.0NoCascade\AmbitionEarlyHourSky.uproject" -rocket

B案

cd C:\Program Files\Epic Games\UE_5.0\Engine\Binaries\DotNET\UnrealBuildTool
UnrealBuildTool.exe AmbitionEarlyHourSky Win64 Development "F:\Download\Game\AmbitionEarlyHourSky6.0NoCascade\AmbitionEarlyHourSky.uproject" -rocket

ERROR: Unable to find plugin ‘ShallowWater’ (referenced via AmbitionEarlyHourSky.uproject). Install it and try again, or remove it from the required plugin list.

と言われるので。

AmbitionEarlyHourSky.uprojectの Plugin から ShallowWaterを消す。

{
	"FileVersion": 3,
	"EngineAssociation": "5.0",
	"Category": "",
	"Description": "",
	"Modules": [
		{
			"Name": "AmbitionEarlyHourSky",
			"Type": "Runtime",
			"LoadingPhase": "Default",
			"AdditionalDependencies": [
				"Engine"
			]
		}
	],
	"Plugins": [
		{
			"Name": "ShallowWater",
			"Enabled": true
		},
		{
			"Name": "Water",
			"Enabled": true
		},
		{
			"Name": "PythonScriptPlugin",
			"Enabled": true
		},
		{
			"Name": "EditorScriptingUtilities",
			"Enabled": true
		},
		{
			"Name": "Bridge",
			"Enabled": true,
			"SupportedTargetPlatforms": [
				"Win64",
				"Mac",
				"Linux"
			]
		}
	]
}

Build.batできたっぽい


C:\Users\furcr>cd C:\Program Files\Epic Games\UE_5.0\Engine\Binaries\Win64\

C:\Program Files\Epic Games\UE_5.0\Engine\Binaries\Win64>cd ../../

C:\Program Files\Epic Games\UE_5.0\Engine>cd C:\Program Files\Epic Games\UE_5.0\Engine\Build\BatchFiles

C:\Program Files\Epic Games\UE_5.0\Engine\Build\BatchFiles>Build.bat AmbitionEarlyHourSky Win64 Development "F:\Download\Game\AmbitionEarlyHourSky6.0NoCascade\AmbitionEarlyHourSky.uproject" -rocket
Using bundled DotNet SDK
Log file: C:\Users\furcr\AppData\Local\UnrealBuildTool\Log.txt
Creating makefile for AmbitionEarlyHourSky (Build.version is newer)
ERROR: Unable to find plugin 'ShallowWater' (referenced via AmbitionEarlyHourSky.uproject). Install it and try again, or remove it from the required plugin list.

C:\Program Files\Epic Games\UE_5.0\Engine\Build\BatchFiles>Build.bat AmbitionEarlyHourSky Win64 Development "F:\Download\Game\AmbitionEarlyHourSky6.0NoCascade\AmbitionEarlyHourSky.uproject" -rocket
Using bundled DotNet SDK
Log file: C:\Users\furcr\AppData\Local\UnrealBuildTool\Log.txt
Creating makefile for AmbitionEarlyHourSky (Build.version is newer)
Parsing headers for AmbitionEarlyHourSky
  Running UnrealHeaderTool "F:\Download\Game\AmbitionEarlyHourSky6.0NoCascade\AmbitionEarlyHourSky.uproject" "F:\Download\Game\AmbitionEarlyHourSky6.0NoCascade\Intermediate\Build\Win64\AmbitionEarlyHourSky\Development\AmbitionEarlyHourSky.uhtmanifest" -LogCmds="loginit warning, logexit warning, logdatabase error" -Unattended -WarningsAsErrors -abslog="C:\Users\furcr\AppData\Local\UnrealBuildTool\Log_UHT.txt" -installed
Reflection code generated for AmbitionEarlyHourSky in 6.3933034 seconds
Building AmbitionEarlyHourSky...
Using Visual Studio 2019 14.29.30141 toolchain (C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133) and Windows 10.0.18362.0 SDK (C:\Program Files (x86)\Windows Kits\10).
[Adaptive Build] Excluded from AmbitionEarlyHourSky unity file: MyBlueprintFunctionLibrary.cpp, SaveToText.cpp, TextFileToString.cpp, AmbitionEarlyHourSky.cpp, AmbitionEarlyHourSkyCharacter.cpp, AmbitionEarlyHourSkyGameMode.cpp
Distributing 23 actions to XGE
--------------------Build System Warning---------------------------------------
License is invalid:
    License information is invalid. Please try reloading your license file using the Coordinator Monitor application on the Coordinator machine, or reinstall IncrediBuild.
    This build will run in standalone mode.

-------------------------------------------------------------------------------

Build ID: {5E64F7BF-47B0-4AF8-8F9B-4464A50705EC}

--------------------Project: Default-------------------------------------------
[1/23] SharedPCH.Engine.ShadowErrors.cpp (0:51.37 at +0:00)
[2/23] OpenImageDenoise.dll (0:00.64 at +0:51)
[3/23] tbb.dll (0:00.26 at +0:52)
[4/23] d3d12SDKLayers.dll (0:00.31 at +0:52)
[5/23] D3D12Core.dll (0:00.28 at +0:52)
[6/23] tbb12.dll (0:00.31 at +0:52)
[7/23] AmbitionEarlyHourSkyCharacter.cpp (0:01.64 at +0:53)
[8/23] AmbitionEarlyHourSkyGameMode.cpp (0:01.01 at +0:54)
[9/23] SaveToText.cpp (0:00.60 at +0:55)
[10/23] MyBlueprintFunctionLibrary.gen.cpp (0:00.62 at +0:56)
[11/23] AmbitionEarlyHourSkyCharacter.gen.cpp (0:00.92 at +0:57)
[12/23] MyBlueprintFunctionLibrary.cpp (0:00.57 at +0:58)
[13/23] TextFileToString.gen.cpp (0:00.62 at +0:58)
[14/23] AmbitionEarlyHourSky.cpp (0:00.70 at +0:59)
[15/23] AmbitionEarlyHourSky.init.gen.cpp (0:00.64 at +1:00)
[16/23] TextFileToString.cpp (0:15.11 at +1:00)
[17/23] AmbitionEarlyHourSkyGameMode.gen.cpp (0:01.00 at +1:15)
[18/23] Default.rc2 (0:00.48 at +1:16)
[19/23] Module.KawaiiPhysics.cpp (0:03.53 at +1:17)
[20/23] Module.KawaiiPhysics.gen.cpp (0:03.40 at +1:20)
[21/23] SaveToText.gen.cpp (0:00.65 at +1:24)
[22/23] AmbitionEarlyHourSky.exe (0:26.03 at +1:24)
   Creating library F:\Download\Game\AmbitionEarlyHourSky6.0NoCascade\Binaries\Win64\AmbitionEarlyHourSky.lib and object F:\Download\Game\AmbitionEarlyHourSky6.0NoCascade\Binaries\Win64\AmbitionEarlyHourSky.exp
[23/23] AmbitionEarlyHourSky.target (0:00.34 at +1:50)
---------------------- Done ----------------------

    Rebuild All: 1 succeeded, 0 failed, 0 skipped

1 build system warning(s):
   - License is invalid

Total time in XGE executor: 111.50 seconds
Total execution time: 128.20 seconds

C:\Program Files\Epic Games\UE_5.0\Engine\Build\BatchFiles>

リビルドするか聞かれる。リビルドで、30秒後ぐらいに起動した!

スカートのリグなどを頑張ったオリジナル作品のAmbitionSkyWaterをUE5でビルドしなおして、ポスプロなどブラッシュアップして動画を取り直した #UE5 #UnrealEngine5 #スカート #リグ #Rig #skirts

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.26 Simple Shooterで自分なりに理解したこと。01200 ~AI Aimining~

Control + P でAIControllerと入力して

UE_4.26\Engine\Source\Runtime\AIModule\Classes\AIController.h

を開きます。

    /* 特定の優先度にフォーカスアクター設定し、結果としてFocalPointを設定します。*/    virtual void SetFocus(AActor* NewFocus, EAIFocusPriority::Type InPriority = EAIFocusPriority::Gameplay);

/ *特定の優先度にフォーカスアクターを設定し、結果としてFocalPointを設定します。 * /
	/* Set Focus actor for given priority, will set FocalPoint as a result. */
	virtual void SetFocus(AActor* NewFocus, EAIFocusPriority::Type InPriority = EAIFocusPriority::Gameplay);

   

こっちは

指定された優先度のフォーカスをクリアし、結果としてFocalPointもクリアします@paramInPriorityフォーカス優先度をクリアします。 何を使用すればよいかわからない場合は、おそらくEAIFocusPriority :: Gameplay * /を意味します。

  virtual void ClearFocus(EAIFocusPriority::Type InPriority);

	/** 指定された優先度のフォーカスをクリアし、結果としてFocalPointもクリアします
* @paramInPriorityフォーカス優先度をクリアします。 何を使用すればよいかわからない場合は、おそらくEAIFocusPriority :: Gameplay * /を意味します。*/
	virtual void ClearFocus(EAIFocusPriority::Type InPriority);

フォーカスの優先度ってなによってなるので見てみると

その列挙型の定義を見てみると、デフォルトの動きMoveゲームプレイがあることがわかります

そしてそれらは基本的に優先順位の順にリストされています。

//これが通常の列挙型ではなく名前空間である理由は
//ゲーム固有のコードで拡張できるようにする
// @todoこれは少し面倒なので、リファクタリングする必要があります
namespace EAIFocusPriority
{
	typedef uint8 Type;

	const Type Default = 0;
	const Type Move = 1;
	const Type Gameplay = 2;

	const Type LastFocusPriority = Gameplay;
}

struct FFocusKnowledge
{
	struct FFocusItem
	{
		TWeakObjectPtr<AActor> Actor;
		FVector Position;

		FFocusItem()
		{
			Actor = nullptr;
			Position = FAISystem::InvalidLocation;
		}
	};
	
	TArray<FFocusItem> Priorities;
};

私たちは主にこのゲームプレイを使用するので、それらをあまり使用する必要はありませんでした

次に

UE_4.26\Engine\Source\Runtime\Engine\Classes\GameFramework\Actor.h

protected:
	/** Overridable native event for when play begins for this actor. */
	virtual void BeginPlay();

をコピーして

ShooterAIController.hにペーストしてオーバーライドします

// 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()
protected:
	virtual void BeginPlay() override;	
};

C:\Program Files\Epic Games\UE_4.26\Engine\Source\Runtime\Engine\Classes\Kismet\GameplayStatics.h

	/** 指定されたプレーヤーインデックスのプレーヤーポーンを返します */
	UFUNCTION(BlueprintPure, Category="Game", meta=(WorldContext="WorldContextObject", UnsafeDuringActorConstruction="true"))
	static class APawn* GetPlayerPawn(const UObject* WorldContextObject, int32 PlayerIndex);

をみると指定されたプレーヤーインデックスのプレーヤーポーンを返しますので

// 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);

}

できたのがこれ

Unreal Engine C++ Developer: Learn C++ and Make Video Games | Udemy UE4.25 Simple Shooterで自分なりに理解したこと。01100 ~AIコントローラーを作成してセットアップ~

新規C++クラスを作る 親クラスにAIコントローラーを選ぶ

名前は ShooterAIController

このクラスを使ってブループリントクラスを作る

名前を BP_ShooterAIController

BP_ShooterCharacterを開いて ポーンのAI ContrallerClassにBP_ShooterAIControllerを設定

実行してBP_ShooterAIControllerがポーンされてるか確認する。

#UE4 #UE4Study #UE5 #UE5Study #UnrealEngineのPythonScriptPluginのpython3へのPyside2のインストール方法

Pyside2はpipを使ってインストールするのが基本です。

https://forums.unrealengine.com/t/fyi-ue4-switching-to-python-3-7-7-by-default-4-26/151803

より

C:\Program Files\Epic Games\UE_4.26\Engine\Plugins\Experimental\PythonScriptPlugin\Source\PythonScriptPluginPreload\PythonScriptPluginPreload.Build.csで

// Copyright Epic Games, Inc. All Rights Reserved.
using UnrealBuildTool;

namespace UnrealBuildTool.Rules
{
	public class PythonScriptPluginPreload : ModuleRules
	{
		public PythonScriptPluginPreload(ReadOnlyTargetRules Target) : base(Target)
		{
			PublicDependencyModuleNames.AddRange(
				new string[] {
					"Core",
				}
			);

			if (Target.bBuildEditor)
			{
				PrivateIncludePathModuleNames.AddRange(
					new string[] {
						"Python3",
					}
				);
			}
			else
			{
				PrivateDefinitions.Add("WITH_PYTHON=0");
			}
		}
	}
}

となっているのでPython3を参照しているので

::python.exeへ移動して
cd C:\Program Files\Epic Games\UE_4.26\Engine\Binaries\ThirdParty\Python3\Win64
::pip install Pyside2というかんじで詳細はこのようにインストール
python -m pip install --target="C:\Program Files\Epic Games\UE_4.26\Engine\Binaries\ThirdParty\Python3\Win64\Lib\site-packages" Pyside2


するとローカルではうまく起動しました。

参考URL
https://qiita.com/7CIT/items/a480a84bb9d249544f5f

プラグインを有効にする感じのやり方もあります。
Python Editor¥3,177 これをインストールしてしまえば使えるようです。
https://www.unrealengine.com/marketplace/ja/product/python-editor?sessionInvalidated=true

参照

Unreal Engine C++ Developer: Learn C++ and Make Video Games | Udemy UE4.25 Simple Shooterで自分なりに理解したこと。01000 ~ブループリント純粋関数ノードを作る ~


彼が死ぬまでこのキャラクターを撃つことができるようになったので

アニメーションBPのこのブール値をゲームプレイから自動的に設定する必要があります。

UFUNCTION()マクロ
UFUNCTION(BluePrintCallable)//ブループリント呼び出し可能。
UFUNCTION(BluePrintPure)純粋ノード

それがブループリント呼び出し可能の実行ピンがある関数か、

それがブループリントピュア=純粋ノードで実行ピンが必要ない関数です。

ShooterCharacter.h

public:	
	UFUNCTION(BluePrintPure)
	bool IsDead() const;

ShooterCharacter.cpp

bool AShooterCharacter::IsDead() const
{
	return Health <= 0;
}

ブループリントで見てみると IsDead純粋関数としてノードが作られました。

ShooterCharacter.h 全文

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

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "ShooterCharacter.generated.h"

class AGun;


UCLASS()
class SIMPLESHOOTERCP2_API AShooterCharacter : public ACharacter
{
	GENERATED_BODY()

public:
	// Sets default values for this character's properties
	AShooterCharacter();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	UFUNCTION(BluePrintPure)
	bool IsDead() const;

	// Called every frame
	virtual void Tick(float DeltaTime) override;

	// Called to bind functionality to input
	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
	
	virtual float TakeDamage(float DamageAmount, struct FDamageEvent const& DamageEvent, class AController* EventInstigator, AActor* DamageCauser) override;

private:
	void MoveForward(float AxisValue);
	void MoveRight(float AxisValue);
	void LockUpRate(float AxisValue);
	void LockRightRate(float AxisValue);
	void Shoot();
	
	UPROPERTY(EditAnyWhere)
	float RotationRate = 10;

	UPROPERTY(EditDefaultsOnly)
	float MaxHealth=100;

	UPROPERTY(VisibleAnyWhere)
	float Health;

	UPROPERTY(EditDefaultsOnly)
	TSubclassOf<AGun> GunClass;

	UPROPERTY()
	AGun* Gun;


};

ShooterCharacter.cpp

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


#include "ShooterCharacter.h"
#include "Gun.h"
//#include "Engine/Engine.h"
// Sets default values
AShooterCharacter::AShooterCharacter()
{
 	// 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;

}

// Called when the game starts or when spawned
void AShooterCharacter::BeginPlay()
{
	Super::BeginPlay();
	
	Health = MaxHealth;

	Gun = GetWorld()->SpawnActor<AGun>(GunClass);
	GetMesh()->HideBoneByName(TEXT("weapon_r"),EPhysBodyOp::PBO_None );
	Gun->AttachToComponent(GetMesh(), FAttachmentTransformRules::KeepRelativeTransform, TEXT("weaponSocket"));
	Gun->SetOwner(this);
}
bool AShooterCharacter::IsDead() const
{
	return Health <= 0;
}
// Called every frame
void AShooterCharacter::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

void AShooterCharacter::Shoot()
{
	Gun->PullTrigger();
}

// Called to bind functionality to input
void AShooterCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

	PlayerInputComponent ->BindAxis(TEXT("MoveForward"),this,&AShooterCharacter::MoveForward);
	PlayerInputComponent ->BindAxis(TEXT("LockUp"),this,&APawn::AddControllerPitchInput);
	PlayerInputComponent ->BindAxis(TEXT("MoveRight"),this,&AShooterCharacter::MoveRight);
	PlayerInputComponent ->BindAxis(TEXT("LockRight"),this,&APawn::AddControllerYawInput);
	PlayerInputComponent ->BindAxis(TEXT("LockUpRate"),this,&AShooterCharacter::LockUpRate);
	PlayerInputComponent ->BindAxis(TEXT("LockRightRate"),this,&AShooterCharacter::LockRightRate);
	PlayerInputComponent ->BindAction(TEXT("Jump"),EInputEvent::IE_Pressed,this,&ACharacter::Jump);
	PlayerInputComponent ->BindAction(TEXT("Shoot"),EInputEvent::IE_Pressed,this,&AShooterCharacter::Shoot);
}

float AShooterCharacter::TakeDamage(float DamageAmount, struct FDamageEvent const& DamageEvent, class AController* EventInstigator, AActor* DamageCauser)
{
	float DamageToApply = Super::TakeDamage(DamageAmount,DamageEvent,EventInstigator,DamageCauser);
	DamageToApply = FMath::Min(Health,DamageToApply);
	Health -= DamageToApply;
	UE_LOG(LogTemp,Display,TEXT("Health Left %F"),Health);
	float TimeToDisplay =5.0f;
	FString Health_str = FString::SanitizeFloat(Health);
	FString TestHUDString =TEXT("Health Left")+	Health_str;
	GEngine->AddOnScreenDebugMessage(-1,TimeToDisplay,FColor::Green,TestHUDString);
	return DamageToApply;
}

void AShooterCharacter::MoveForward(float AxisValue)
{
	AddMovementInput(GetActorForwardVector() * AxisValue);
}
void AShooterCharacter::MoveRight(float AxisValue)
{
	AddMovementInput(GetActorRightVector() * AxisValue);
}

void AShooterCharacter::LockUpRate(float AxisValue)
{
	AddControllerPitchInput(AxisValue * RotationRate * GetWorld()->GetDeltaSeconds());
}
void AShooterCharacter::LockRightRate(float AxisValue)
{
	AddControllerYawInput(AxisValue * RotationRate * GetWorld()->GetDeltaSeconds());
}
// void AShooterCharacter::LockUp(float AxisValue)
// {
// 	AddControllerPitchInput(AxisValue);
// }

できたのがこれ

Unreal Engine C++ Developer: Learn C++ and Make Video Games | Udemy UE4.25 Simple Shooterで自分なりに理解したこと。00800 ~TakeDamageのオーバーライド ~

基本的にはデフォルトのTakeDamageが来た時に処理を追加したいのでオーバーライドします。

UE4/Engine/Sounce/Runtime/Engine/Classes/GameFramework/Actor.h

virtual float TakeDamage(float DamageAmount, struct FDamageEvent const& DamageEvent, class AController* EventInstigator, AActor* DamageCauser);
をコピーして

ShooterCharacter.h

にこれをペーストしてoverrideキーワードを追加しました。
    virtual float TakeDamage(float DamageAmount, struct FDamageEvent const& DamageEvent, class AController* EventInstigator, AActor* DamageCauser) override;

ShooterCharacter.cppはこうやって元のSuper::TakeDamegeを追加します

float AShooterCharacter::TakeDamage(float DamageAmount, struct FDamageEvent const& DamageEvent, class AController* EventInstigator, AActor* DamageCauser) ;
{
	float DamageApplied = Super::TakeDamage(DamageAmount,DamageEvent,EventInstigator,DamageCauser);
	
}

次に、ダメージを受けた時のヒットポイントを健康状態のとしてHealth変数を用意します。

ShooterCharacter.h

	UPROPERTY(EditDefaultsOnly)
	float MaxHealth=100;

	UPROPERTY(VisibleAnyWhere)
	float Health;

ShooterCharacter.cppでBeginPlayにHealth = MaxHealth;追加

void AShooterCharacter::BeginPlay()
{
	Super::BeginPlay();
	
	Health = MaxHealth;

	Gun = GetWorld()->SpawnActor<AGun>(GunClass);
	GetMesh()->HideBoneByName(TEXT("weapon_r"),EPhysBodyOp::PBO_None );
	Gun->AttachToComponent(GetMesh(), FAttachmentTransformRules::KeepRelativeTransform, TEXT("weaponSocket"));
	Gun->SetOwner(this);
}

ShooterCharacter.cppでTakeDamageに以下追加

DamageToApply = FMath::Min(Health,DamageToApply);   
Health -= DamageToApply;   
UE_LOG(LogTemp,Display,TEXT(“Health Left %F”),Health);

float TimeToDisplay =5.0f;   
FString Health_str = FString::SanitizeFloat(Health);   
(\UE_4.25\Engine\Source\Runtime\Core\Private\Containers\String.cppにある)
FString TestHUDString =TEXT(“Health Left”)+ Health_str;   

GEngine->AddOnScreenDebugMessage(-1,TimeToDisplay,FColor::Green,TestHUDString);
(\UE_4.25\Engine\Source\Runtime\Engine\Private\UnrealEngine.cppにある)
詳細は以下
FString | UnrealEngineのドキュメント

https://docs.unrealengine.com/4.27/ja/ProgrammingAndScripting/ProgrammingWithCPP/UnrealArchitecture/StringHandling/FString/

return DamageToApply;

float AShooterCharacter::TakeDamage(float DamageAmount, struct FDamageEvent const& DamageEvent, class AController* EventInstigator, AActor* DamageCauser)
{
	float DamageToApply = Super::TakeDamage(DamageAmount,DamageEvent,EventInstigator,DamageCauser);
	DamageToApply = FMath::Min(Health,DamageToApply);
	Health -= DamageToApply;
	UE_LOG(LogTemp,Display,TEXT("Health Left %F"),Health);
	float TimeToDisplay =5.0;
	FString Health_str = FString::SanitizeFloat(Health);
	FString TestHUDString =TEXT("Health Left")+	Health_str;
	GEngine->AddOnScreenDebugMessage(-1,TimeToDisplay,FColor::Green,TestHUDString);
	return DamageToApply;
}

ShooterCharacter.h 全文

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

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "ShooterCharacter.generated.h"

class AGun;


UCLASS()
class SIMPLESHOOTERCP2_API AShooterCharacter : public ACharacter
{
	GENERATED_BODY()

public:
	// Sets default values for this character's properties
	AShooterCharacter();

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;
	
	virtual float TakeDamage(float DamageAmount, struct FDamageEvent const& DamageEvent, class AController* EventInstigator, AActor* DamageCauser) override;

private:
	void MoveForward(float AxisValue);
	void MoveRight(float AxisValue);
	void LockUpRate(float AxisValue);
	void LockRightRate(float AxisValue);
	void Shoot();
	
	UPROPERTY(EditAnyWhere)
	float RotationRate = 10;

	UPROPERTY(EditDefaultsOnly)
	float MaxHealth=100;

	UPROPERTY(VisibleAnyWhere)
	float Health;

	UPROPERTY(EditDefaultsOnly)
	TSubclassOf<AGun> GunClass;

	UPROPERTY()
	AGun* Gun;


};

ShooterCharacter.cpp 全文

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


#include "ShooterCharacter.h"
#include "Gun.h"
//#include "Engine/Engine.h"
// Sets default values
AShooterCharacter::AShooterCharacter()
{
 	// 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;

}

// Called when the game starts or when spawned
void AShooterCharacter::BeginPlay()
{
	Super::BeginPlay();
	
	Health = MaxHealth;

	Gun = GetWorld()->SpawnActor<AGun>(GunClass);
	GetMesh()->HideBoneByName(TEXT("weapon_r"),EPhysBodyOp::PBO_None );
	Gun->AttachToComponent(GetMesh(), FAttachmentTransformRules::KeepRelativeTransform, TEXT("weaponSocket"));
	Gun->SetOwner(this);
}

// Called every frame
void AShooterCharacter::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

void AShooterCharacter::Shoot()
{
	Gun->PullTrigger();
}

// Called to bind functionality to input
void AShooterCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

	PlayerInputComponent ->BindAxis(TEXT("MoveForward"),this,&AShooterCharacter::MoveForward);
	PlayerInputComponent ->BindAxis(TEXT("LockUp"),this,&APawn::AddControllerPitchInput);
	PlayerInputComponent ->BindAxis(TEXT("MoveRight"),this,&AShooterCharacter::MoveRight);
	PlayerInputComponent ->BindAxis(TEXT("LockRight"),this,&APawn::AddControllerYawInput);
	PlayerInputComponent ->BindAxis(TEXT("LockUpRate"),this,&AShooterCharacter::LockUpRate);
	PlayerInputComponent ->BindAxis(TEXT("LockRightRate"),this,&AShooterCharacter::LockRightRate);
	PlayerInputComponent ->BindAction(TEXT("Jump"),EInputEvent::IE_Pressed,this,&ACharacter::Jump);
	PlayerInputComponent ->BindAction(TEXT("Shoot"),EInputEvent::IE_Pressed,this,&AShooterCharacter::Shoot);
}

float AShooterCharacter::TakeDamage(float DamageAmount, struct FDamageEvent const& DamageEvent, class AController* EventInstigator, AActor* DamageCauser)
{
	float DamageToApply = Super::TakeDamage(DamageAmount,DamageEvent,EventInstigator,DamageCauser);
	DamageToApply = FMath::Min(Health,DamageToApply);
	Health -= DamageToApply;
	UE_LOG(LogTemp,Display,TEXT("Health Left %F"),Health);
	float TimeToDisplay =5.0f;
	FString Health_str = FString::SanitizeFloat(Health);
	FString TestHUDString =TEXT("Health Left")+	Health_str;
	GEngine->AddOnScreenDebugMessage(-1,TimeToDisplay,FColor::Green,TestHUDString);
	return DamageToApply;
}

void AShooterCharacter::MoveForward(float AxisValue)
{
	AddMovementInput(GetActorForwardVector() * AxisValue);
}
void AShooterCharacter::MoveRight(float AxisValue)
{
	AddMovementInput(GetActorRightVector() * AxisValue);
}

void AShooterCharacter::LockUpRate(float AxisValue)
{
	AddControllerPitchInput(AxisValue * RotationRate * GetWorld()->GetDeltaSeconds());
}
void AShooterCharacter::LockRightRate(float AxisValue)
{
	AddControllerYawInput(AxisValue * RotationRate * GetWorld()->GetDeltaSeconds());
}
// void AShooterCharacter::LockUp(float AxisValue)
// {
// 	AddControllerPitchInput(AxisValue);
// }

こうなった。