zer0から始めるプログラミング生活

unreal EngineやUnityのTipsを書いていきます。

【Unreal C++】⑤Timer(Delay)【UE4】

BPのDelayに相当する処理をするにはTimerを使うようです。
他に方法があればコメントで教えて頂けると幸いです。

Timerの開始

Timerを開始するにはFTimerManagerのSetTimer 関数を用います。

World->GetTimerManager().SetTimer(_TimerHandle,Callback,Rate,bLoop,FirstDelay);


引数 説明
_TimerHandle FTimerHandle Timerを管理する変数
Callback TFunction 呼びたい関数
Rate float 関数を何秒ごとに呼ぶか
bLoop bool ループするかどうか
FirstDelay float 最初に何秒待つか


例(カウントタイマー)

hogeActor.h

UCLASS()
class HOGEPROJECT_API AhogeActor : public AActor
{
	GENERATED_BODY()
	
public:
	// Sets default values for this actor's properties
	AhogeActor();

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

	UFUNCTION()
	void Timer();

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

protected:
	UPROPERTY()
	UWorld* World;

public:
         UPROPERTY()
	int PlayTime;
};


hogeActor.cpp

void AhogeActor::BeginPlay()
{
World=GEngine->GameViewport->GetWorld();
FTimerHandle _TimerHandle;	
World->GetTimerManager().SetTimer(_TimerHandle, this, &AhogeActor::Timer,1.0f, true);
}

void AhogeActor::Timer()
{
PlayTime+=1;
}


Timerの停止

Timerを停止するにはFTimerManagerのClearTimer 関数を用います。
また、もう一度同じTimerHadleでSetTimerを呼ぶと既存のものが破棄され、新しいものに置き換えられます。
ClearしたTimerHandleは新しいTimerを管理するために再利用することが出来ます。

World->GetTimerManager().ClearTimer(_TimerHandle);
引数 説明
_TimerHandle FTimerHandle Timerを管理する変数


Timerの一時停止

Timerによる関数呼び出しを一時的に実行しないようにするにはFTimerManagerのPauseTimer 関数を用います。

World->GetTimerManager().PauseTimer(_TimerHandle);


Timerの再開

一時停止したTimerを再開させるにはFTimerManagerのUnPauseTimer 関数を用います。

World->GetTimerManager().UnPauseTimer(SampleTimerHandle);  

Timerが一時停止状態の確認

Timerが一時停止しているかどうかを確認するためにはFTimerManagerのIsTimerPaused 関数を用います。bool値がreturnされます。

 if( World->GetTimerManager().IsTimerPaused(_TimerHandle) == true )  
{ 
}

反対にTimerがアクティブで一時停止していないことを確認するためにはFTimerManagerのIsTimerActive 関数を用います。bool値がreturnされます。

 if( World->GetTimerManager().IsTimerActive(_TimerHandle) == true )  
{ 
}

追記

(2018.01.10)

↓のドキュメントではループありのタイマーをClearTimer関数でタイマーのクリアを行っています。
これは実質、タイマーの停止も担っています。
ここで1つ疑問に思ったのが、ループなしのタイマーでは自動的に停止するのでタイマーの停止を目的としたClearTimer関数の使用は必要無くなりますが、クリアを目的としたClearTimerが必要なのかということです。
docs.unrealengine.com

APIにはIsTimerActive関数やTimerExists関数がありますので、こちらを用いてループなしのタイマーが自動停止した後にまだタイマーが存在しているかを調べてみたいと思います。
docs.unrealengine.com

調査

いろいろ調べ方はあると思いますが、簡単な方法で実装します。
bLoopをfalseとしたSetTimer関数をBeginPlayで呼びます。
IsTimerActive関数やTimerExists関数をTickで呼びます。


TimerAct.h

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Engine.h"
#include "TimerAct.generated.h"

UCLASS()
class HOGEPROJECT_API ATimerAct : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	ATimerAct();

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

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

protected:
	UWorld* World;
	FTimerHandle _TimerHandle;

protected:
	UFUNCTION()
	void Process();
};

TimerAct.cpp

void ATimerAct::BeginPlay()
{
World=GEngine->GameViewport->GetWorld();
FTimerHandle _TimerHandle;	
World->GetTimerManager().SetTimer(_TimerHandle, this, &ATimerAct::HogeProcess,1.0f, false); //bLoop=false
}

void ATimerAct::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	if (World->GetTimerManager().IsTimerActive(_TimerHandle))
	{
		GEngine->AddOnScreenDebugMessage(-1, 2.0f, FColor::Green, "Active");
	}
	if (World->GetTimerManager().TimerExists(_TimerHandle))
	{
		GEngine->AddOnScreenDebugMessage(-1, 2.0f, FColor::Red, "Exist");
	}
}

void ATimerAct::HogeProcess()
{
}
結果

プレイ開始からHogeProcessが呼ばれるまでタイマーが存在し、その後は自動的にクリアされ、存在しなくなっているようです。


※何か間違えがあればコメントよろしくお願い致します。

【Unreal C++】④Log【UE4】

OutputLogへの出力

「ウィンドウ→デベロッパーツール→アウトプットログ」でウィンドウを出せます。

UE_LOG

UE_LOG(CategoryName, Verbosity, Message);
パラメータ 説明
CategoryName カテゴリ名(カテゴリを自作することも可能、デフォルトはLogTemp)
Verbosity ログレベル(種類)
Message メッセージ



「CategoryName」の自作方法

①ヘッダファイルでDECLARE_LOG_CATEGORY_EXTERN マクロを用いてカテゴリを宣言

DECLARE_LOG_CATEGORY_EXTERN(NewCategoryName, Log, All);

第1引数はカテゴリ名、第2引数はデフォルトのVerbosity、第3引数はコンパイル時で有効化するVerbosityです。


「Verbosity」の種類
Verbosity ログレベル 備考
Fatal 致命的なエラー ログ出力とともにクラッシュ。
Error エラー
Warning 警告
Display ログ(詳細度:最低) 灰色 コンソールとログファイルに出力
Log ログ(詳細度:低) 灰色 ログファイルに出力、アウトプットログに出力可
Verbose ログ(詳細度:高) 灰色 コンソールとログファイルに出力
VeryVerbose ログ(詳細度:最高) 灰色 コンソールとログファイルに出力



Message

文字列の他にフォーマット指定子(%d、%f)などを用いて変数を出力することが可能です。
その際は第4引数に変数を追加します。


Logコマンド

プレイ中に「@」キー(デフォルト)やOutputLogの「Enter Console command」の部分に以下のコマンドを打ち込むことでログカテゴリのVerbosity を変更することが出来ます。

log CategoryName Verbosity 



また、以下のコマンドで各カテゴリのVerbosity の設定を確認出来ます。

log list




画面への出力

AddOnScreenDebugMessage

BPでいうPrintStringです。

GEngine->AddOnScreenDebugMessage(Key, TimeToDisplay, Color, Message);
パラメータ 説明
Key int 同じメッセージが複数回追加されないようにするユニークなキー。一時的なものには-1
TimeToDisplay float 表示する秒数
Color FColor テキストを表示する色
Message FString 表示する文字
追記(2018.1.19)

HMDを被った状態でPrintStringによって表示された文字列を確認しようとすると、確認しづらい箇所に表示されるため位置を変更したかったのですが、ver4.18現在、PrintStringやAddOnScreenDebugMessageの表示位置は左上から変更できないようです。
OutputLogにも残るのでそちらを確認するか、どうしても別の位置に表示させたい場合にはTextRenderやUMGを用いて空間上に表示させるしかないようです。

追記(2018.1.21)

AddOnScreenDebugMessageの第4引数(Message)はFString型なので、他の型からFString型へ変換する必要があります。

変換元の型 変換元の変数 変換
int intValue FString::FromInt(intValue);
float floatValue FString::SanitizeFloat(floatValue);
FVector VectorValue VectorValue.ToString();
FVector2D Vector2DValue Vector2DValue.ToString();
FRotator RotatorValue RotatorValue.ToString();
FLinearColor LinearColorValue LinearColorValue.ToString();



【Unreal C++】③イテレータ【UE4】

今回はレベル内のActorやObjectを検索する方法を書いていきます。
BPではGet All Actors of Classを用いて検索していました。
docs.unrealengine.com

下準備

検索元をhoge、検索先のActorをhogeActorという名前でC++クラスを作成します。
例としてhogeActorのStaticMeshComponentの位置を取得してみたいと思います。
hoge.h

#include "CoreMinimal.h"
#include "hoge.generated.h"

UCLASS()
class HOGEPROJECT_API hoge : public AActor
{
GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	hoge();

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

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

protected:
	UPROPERTY(EditAnywhere)
		USceneComponent*Scene;
	
         UPROPERTY(EditAnywhere)
		UStaticMeshComponent* StaticMesh;
};

.cpp

#include "hoge.h"

//Set default values
hoge::hoge()
{
	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;
        
        Scene = CreateDefaultSubobject<USceneComponent>(TEXT("Scene"));
	RootComponent = Scene;
        StaticMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh"));
	StaticMesh->SetupAttachment(RootComponent);

	
}

hogeActor.h

#include "CoreMinimal.h"
#include "hogeActor.generated.h"

UCLASS()
class HOGEPROJECT_API hogeActor : public AActor
{
GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	hogeActor();

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

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

hogeActor.cpp

#include "hogeActor.h"

//Set default values
hogeActor::hogeActor()
{
	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;
}

Iterators

UE4イテレータにはActorIteratorとObjectIteratorがあります。

ActorIterator


hoge.h

#include "CoreMinimal.h"
#include "EngineUtils.h" //TActorIterator
#include "hoge.generated.h"

UCLASS()
class HOGEPROJECT_API hoge: public AActor
{
GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	hogeActor();

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

        UPROPERTY()
        AhogeActor* hogeAct;

       UPROPERTY()
       FVector Loc;

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

TActorIteratorを使用するためにEngineUtils.hをインクルードします。
UWorld型とAhogeActor型とFVector型の変数を宣言します。


hoge.cpp

// Called when the game starts or when spawned
void Ahoge::BeginPlay()
{
	Super::BeginPlay();
	
	World = GEngine->GameViewport->GetWorld();

	for (TActorIterator<AhogeActor>hogeActorItr(World); hogeActorItr; ++hogeActorItr)
	{
		hogeAct = *hogeActorItr;
                Loc=hogeAct->StaticMesh->GetComponentLocation();
	}
}

GetWorld()でビューポート内のコンテンツを返します。
よく World=GetWorld(); だけなのを見ますが、
ver4.18現在では GEngine->GameViewport->GetWorld(); でないとダメみたいです。

BeginPlay時にWorld内に存在していれば、ヘッダファイルで宣言し、BeginPlayで検索することによって使い回せます。

	for (TActorIterator<AhogeActor>hogeActorItr(World); hogeActorItr; ++hogeActorItr)
	{
	AhogeActor* hogeAct = *hogeActorItr;
	}

のようにするとfor文の間でしか使えないので注意です。

ObjectIterator

使い方はActorIteratorと同様です。

for ( TObjectIterator<UStaticMeshComponent> Itr; Itr; ++Itr )
{
	// Access the subclass instance with the * or -> operators.
	UStaticMeshComponent *StaticMesh = *Itr;

}

配列要素のイタレーション

EpicさんのおすすめはC++のranged-for機能を使う方法だそうです。
↓ではFstringの場合ですが、Actorの配列でも同様に出来ましたのでそちらで書いていきます。
Unreal Engine | TArray:アンリアル エンジンの配列

TArray<AActor*>ActArray;
for(auto& act:ActArray)
{
act->/* do something*/
}

範囲をループして、actという変数にActArrayの各要素を自動的に代入します。
autoを使うことで変数の型を推論してくれます。

【Unreal C++】②Overlapイベント【UE4】

今回はOverlapイベントについて書いていこうと思います。

分かりやすいようにTriggerBoxを作成し、そこに何かがオーバラップ(接触)したという例を示したいと思います。
docs.unrealengine.com

TriggerBoxの作成

TriggerBoxを親クラスにするとうまくいかなかったのでActorを親クラスにしてBoxコンポーネントを追加しました。
(TriggerBoxを親クラスにした場合のやり方を知ってる方は教えていただけると幸いです。)

hoge.h

#include "CoreMinimal.h"
#include "Components/BoxComponent.h"//UBoxComponent
#include "hoge.generated.h"


UCLASS()
class HOGEPROJECT_API hoge : public AActor
{
GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	hoge();

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

	UPROPERTY()
		USceneComponent* Scene;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		UBoxComponent* BoxComp;

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


};

UBoxComponentを使用するにはBoxComponent.hをインクルードする必要があります。
ヘッダファイルの場所は(エンジンをインストールしたフォルダ)/Engine/Source/Runtime/Engine/Classes/Components/BoxComponent.hです。


.cpp

#include "hoge.h"

//Set default values
hoge::hoge()
{
	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;
	Scene = CreateDefaultSubobject<USceneComponent>(TEXT("Scene"));
	RootComponent = Scene;
	BoxComp = CreateDefaultSubobject<UBoxComponent>(TEXT("CollisionComp"));
	BoxComp->SetupAttachment(RootComponent);
}

Overlapイベント

OnComponentBeginOverlap

このイベントは対象のコンポーネントに何かがOverlap(接触する)と実行されます。
BPでは↓のようなノードです。
f:id:bigden:20171116225714p:plain

hoge.h

//OnComponentBeginOverlap
	UFUNCTION()
		void OnOverlapBegin(UPrimitiveComponent* OverlappedComponent,AActor* OtherActor,UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult &SweepResult);

OnOverlapBegin関数を追加し、Overlapした際に実行したいイベントを書いていきます。
ちなみにUFUNCTION()がないとクラッシュします。

hoge.cpp

hoge::hoge()
{
	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;
	Scene = CreateDefaultSubobject<USceneComponent>(TEXT("Scene"));
	RootComponent = Scene;
	BoxComp = CreateDefaultSubobject<UBoxComponent>(TEXT("CollisionComp"));
	BoxComp->SetupAttachment(RootComponent);
        //↓追加
        BoxComp->OnComponentBeginOverlap.AddDynamic(this, &Ahoge::OnOverlapBegin);
}

void Ahoge::OnOverlapBegin(UPrimitiveComponent* OverlappedComponent,AActor* OtherActor,UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult &SweepResult)
{
//Overlapした際に実行したいイベント
}

AddDynamicによってOnComponentBeginOverlapと呼びたい関数をバインディングします。
これによってOverlapするとOnOverlapBeginが呼ばれます。

docs.unrealengine.com

OnComponentEndOverlap

このイベントは対象のコンポーネントへのOverlapが終了すると実行されます。
BPでは↓のようなノードです。
f:id:bigden:20171117003654p:plain

基本的にはOnComponentBeginOverlapと実装方法は同じだと思います。
Overlapした際に実行したいイベントを書く関数の引数を次のように変更します。

OnComponentOverlapEnd(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);

OnActorBeginOverlap

このイベントは対象のActorに何かがOverlapすると実行されます。
BPでは↓のようなノードです。
f:id:bigden:20171117002843p:plain

基本的にはOnComponentBeginOverlapと実装方法は同じだと思います。
Overlapした際に実行したいイベントを書く関数の引数を次のように変更します。

OnActorOverlapBegin(AActor* OverlappedActor, AActor* OtherActor);

OnActorEndOverlap

このイベントは対象のActorへのOverlapが終了すると実行されます。
BPでは↓のようなノードです。
f:id:bigden:20171117003343p:plain

基本的にはOnComponentBeginOverlapと実装方法は同じだと思います。
Overlapした際に実行したいイベントを書く関数の引数を次のように変更します。

OnActorOverlapEnd(AActor* OverlappedActor, AActor* OtherActor);

【Unreal C++】①C++クラス作成&Component追加【UE4】

だいぶUnreal C++に慣れてきたので、備忘録として書いていこうと思います。
ver4.18を使用しています。

C++クラス作成

新しいC++クラスの追加は「コンテンツブラウザの新規追加→新しいC++クラスを追加→親クラスを選択→名前をつける→クラスを作成」で作成できます。

親クラスにActorを選択し、hogeActorと名前をつけました。

hoge.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "hogeActor.generated.h"

UCLASS()
class hogeProject_API AhogeActor : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	AhogeActor();

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

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

};

以上のコードは作成時に自動的に書いてくれています。

ちなみにver4.15からの仕様変更でCoreMinimal.hのincludeが必須に
詳しくは↓
miyahuji111.hatenablog.com


.cpp

#include "hogeActor.h"


// Sets default values
AhogeActor::AhogeActor()
{
 	// Set this actor 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 AhogeActor::BeginPlay()
{
	Super::BeginPlay();
	
}

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

}

cppの方も以上のコードが作成時に自動的に書いてくれています。

PrimaryActorTick.bCanEverTick をtrueにしておくと、Tick処理が呼び出されます。
必要ないときはfalseにしておいたほうが高速に動くようです。

コンポーネントはコンストラクタに書いていきます。
*BeginPlayなど他の場所に書くとクラッシュします。(error吐いてほしい...)

Component追加

.h

UPROPERTY(EditAnywhere)
USceneComponent* Scene;

UFUNCTION()
void hogeFunc();

UPROPERTY()は変数のオプションを指定できます。

オプション 説明
EditAnywhere エディタ(BP,Level)内で編集○
VisibleAnywhere エディタ内で表示○、編集☓
BlueprintReadWrite BPで読み取り○、変更○
BlueprintReadOnly BPで読み取り○、変更☓
Category=" " カテゴリを指定

他にもありますが、とりあえず良く使いそうなものだけ。

.cpp

Scene = CreateDefaultSubobject<USceneComponent>(TEXT("Scene"));
RootComponent = Scene;
Widget = CreateDefaultSubobject<UWidgetComponent>(TEXT("Widget"));
Widget->SetupAttachment(RootComponent);
WidgetInteraction = CreateDefaultSubobject<UWidgetInteractionComponent>(TEXT("WidgetInteraction"));
Widget->SetupAttachment(RootComponent);

CreateDefaultSubobjectでコンポーネントを作成します。<>内はクラス名。TEXT内の("")はエディタ内で表示される名前です。
RootComponentで最上層のコンポーネントに設定します。
SetupAttachment(hoge)でhogeの下の層に設定します。

何か間違っていることがあればご指摘頂けると幸いです。

C++ (Unreal C++)エラー対処まとめ

C++のエラーの対処法をどんどん追加していきます。
UE4を使ってるのでどちらかというとunreal C++での対処法かもしれません。

コード 説明 対処法
不完全クラス型へのポインターは使用できません インクルードを忘れている。
LINK2019 未解決の外部シンボル _hoge1 が関数 _hoge2 で参照されました。 _hoge1のDocumentにModuleが書いてあるのでそれをBuild.csのPublicDependencyModuleNames.AddRangeに追加
Circular dependency detected for filename .../hoge1.h hoge1.hでhoge2.hをinclude、hoge2.hでhoge1.hをincludeしている。(このエラーでue4のプロジェクト(ver4.17)がクラッシュした)

Unreal C++ まとめ

UE4C++勉強中なので分かったことをここにどんどん追加していきます。
なにか間違いがあればご指摘お願いします。
記事にまとめるとその記事に差し替えていきます。

AActor

TakeDamage(ダメージ受ける側)

.h

float Health;

.cpp

float AMyActor::TakeDamage(float Damage, struct FDamageEvent const& DamageEvent, class AController* EventInstigator, class AActor* DamageCauser)  
{  
    // Call the base class - this will tell us how much damage to apply  
    const float ActualDamage = Super::TakeDamage(Damage, DamageEvent, EventInstigator, DamageCauser);     
    if (ActualDamage > 0.f)  
    {  
        Health -= ActualDamage;    
        if (Health <= 0.f)  
        {  
           //体力が0以下になったときの処理
        }     
    }  

    return ActualDamage;  
}  

InflictDamage(ダメージを与える側)

.h

void InflictDamage();

.cpp

void AMyCharacter::InflictDamage()  
{  
    APlayerController* PlayerController = Cast<APlayerController>(GetController());  
    if (PlayerController != nullptr)  
    {  
        // Perform a trace @See LineTraceSingle  
        FHitResult TraceResult(ForceInit);  
        TraceHitForward(PlayerController, TraceResult);  

        // If the trace return an actor, inflict some damage to that actor  
        AActor* ImpactActor = TraceResult.GetActor();  //fResult(LineTraceSingleByChannelのFHitResultを使用してもいい)
        if ((ImpactActor != nullptr) && (ImpactActor != this))  
        {  
            // Create a damage event  
            TSubclassOf<UDamageType> const ValidDamageTypeClass = TSubclassOf<UDamageType>(UDamageType::StaticClass());  
            FDamageEvent DamageEvent(ValidDamageTypeClass);  

            const float DamageAmount = 25.0f; //ダメージ量  
            ImpactActor->TakeDamage(DamageAmount, DamageEvent, PlayerController, this);  
        }  
    }  
}  


BehaviorTree

Characterクラスのhoge_AICharacterとAIControllerクラスのhoge_AIControllerを作成

.h

UCLASS()
class hogeProject_API hoge_AIController : public AAIController
{
	GENERATED_BODY()

public:
	hoge_AIController(const class FObjectInitializer& ObjectInitializer);

	// UProperty 値が自動的に書き込みまたは読み出されることを許可しない
	UPROPERTY(Transient)
		class UBlackboardComponent* BlackboardComp;

	UPROPERTY(Transient)
		class UBehaviorTreeComponent* BehaviorComp;

	virtual void Possess(class APawn* InPawn);

	// BlackboardCompのKeyに対し値を設定する
	void SetEnemy(class APawn* InPawn);

	// BluePrint側でこの関数を呼び出せるように設定
	UFUNCTION(BlueprintCallable, Category = Behavior)
		void SearchForEnemy();

protected:
	uint8 EnemyKeyID;               // BlackBoardで定義したKeyID
	uint8 EnemyLocationID;  // BlackBoardで定義したKeyID
};

.cpp

hoge_AIController::hoge_AIController(const class FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
	BlackboardComp = ObjectInitializer.CreateDefaultSubobject<UBlackboardComponent>(this, TEXT("BlackBoardComp"));

	BehaviorComp = ObjectInitializer.CreateDefaultSubobject<UBehaviorTreeComponent>(this, TEXT("BehaviorComp"));
}

void hoge_AIController::Possess(class APawn* InPawn)
{
	Super::Possess(InPawn);

	AAICharacter* Bot = Cast<AAICharacter>(InPawn);

	if (Bot && Bot->AIBehavior)
	{
		BlackboardComp->InitializeBlackboard(*Bot->AIBehavior->BlackboardAsset);

		EnemyKeyID = BlackboardComp->GetKeyID("Enemy");
		EnemyLocationID = BlackboardComp->GetKeyID("Destination");

		BehaviorComp->StartTree(*Bot->AIBehavior);
	}
}

void hoge_AIController::SearchForEnemy()
{
	APawn* MyBot = GetPawn();
	if (MyBot == NULL)
		return;

	const FVector MyLoc = MyBot->GetActorLocation();
	float BestDistSq = MAX_FLT;
	hogeCharacter* BestPawn = NULL;

	//Get All pawm in the world
	for (FConstPawnIterator It = GetWorld()->GetPawnIterator(); It; ++It)
	{
		hoge_Character* TestPawn = Cast<hoge_Character>(*It);


		if (TestPawn)
		{
			//Calculate between player and AI
			const float DistSq = FVector::Dist(TestPawn->GetActorLocation(), MyLoc);

			if (DistSq < BestDistSq)
			{
				BestDistSq = DistSq;
				BestPawn = TestPawn; // Default: BestPawn=NULL
			}
		}
	}

	if (BestPawn)
	{
		SetEnemy(BestPawn);
	}
}

void hoge_AIController::SetEnemy(class APawn* InPawn)
{
	//Store player pointer
	BlackboardComp->SetValue<UBlackboardKeyType_Object>(EnemyKeyID, InPawn);
	//Store player Location
	BlackboardComp->SetValue<UBlackboardKeyType_Vector>(EnemyLocationID, InPawn->GetActorLocation());
}

FHitResult

.cpp

//変数一覧
	FVector_NetQuantize HitLocation = fHitResult.Location;
	FVector_NetQuantize HitImpactPoint = fHitResult.ImpactPoint;
	FVector_NetQuantizeNormal HitNormal = fHitResult.Normal;
	FVector_NetQuantizeNormal HitImpactNormal = fHitResult.ImpactNormal;
        TWeakObjectPtr<AActor> HitActor = fHitResult.Actor;
	TWeakObjectPtr<UPrimitiveComponent> HitComponent = fHitResult.Component;
	FName HitBoneName = fHitResult.BoneName;
	bool HitbBlockkingHIt = fHitResult.bBlockingHit;
	int32 HitbStartPenetraing = fHitResult.bStartPenetrating;
	float HitDistance = fHitResult.Distance;
	int32 HitFaceIndex = fHitResult.FaceIndex;
	int32 HitItem = fHitResult.Item;
	float HitPenetrationDepth = fHitResult.PenetrationDepth;
	TWeakObjectPtr<UPhysicalMaterial> HitPhysMaterial = fHitResult.PhysMaterial;//if you need it functional, set fCollisionQueryParams.bReturnPhysicalMaterial = true;
	float HitTime = fHitResult.Time;
	FVector_NetQuantize HitTraceEnd = fHitResult.TraceEnd;
	FVector_NetQuantize HitTraceStart = fHitResult.TraceStart;

FTimerManager

bigden.hatenablog.com

USoundWave

SoundWave(インポートした音源)

.h

USoundWave* FireSound;


.cpp

static ConstructorHelpers::FObjectFinder<USoundWave>FireSoundWave(TEXT("SoundWave'/Game/Sounds/Weapon_AssaultRifle/Stereo/AssaultRifle_Shot01_Stereo.AssaultRifle_Shot01_Stereo'"));
	FireSound = FireSoundWave.Object;

//FireSoundWaveの部分は適当な名前で結構です。
//パスは目的のものを右クリック→リファレンスをコピーでとれるのでそれをTEXT("ここ")の部分に貼り付けてください。

UAnimMotage

AnimInstanceを親クラスとしたものを作成

AnimInst.h

#include "Animation/AnimInstance.h"
#include "AnimInst.generated.h"

UCLASS(transient, Blueprintable, hideCategories = AnimInstance, BlueprintType)
class hogeProject_API UAnimInst : public UAnimInstance
{
	GENERATED_UCLASS_BODY()
		
};


AnimInst.cpp

#include "(プロジェクト名).h"
#include "AnimInst.h"

UAnimInst::UAnimInst(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
}

実装先

Character.h

UAnimMontage* hoge_AnimMotage;
void Fire();


Character.cpp

#include "Animation/AnimInstance.h"

ACharacter::ACharacter()
{
Mesh=CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("Mesh"));
static ConstructorHelpers::FObjectFinder<UObject>hogeMontage(TEXT("AnimMontage'(パス)'"));
	hoge_AnimMotage = (UAnimMontage*)hogeMontage.Object;
//FObjectFinder<UAnimMontage>ではエラーを吐くので、
//FObjectFinder<UObject>で取得してオブジェクトを作成するときにUAnimMontageに型を変換します。
}

void ACharacter::Fire()
{
UAnimInst* AnimInst = Cast<UAnimInst>(Mesh->GetAnimInstance());
AnimInst->Montage_Play(hoge_AnimMotage, 1.0f);

//if(AnimInst->Montage_IsPlaying(hoge_AnimMotage)){}でAnimMontageが再生しているかどうか

}

USpringArm

h

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
class USpringArmComponent* CameraBoom;


Character.cpp

CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));
CameraBoom->SetupAttachment(RootComponent);
CameraBoom->TargetArmLength = 200.0f; //カメラがどのくらい後ろの位置で追従するか	
CameraBoom->bUsePawnControlRotation = true; // Rotate the arm based on the controller

UTimeline

.h

#include "Components/TimelineComponent.h"

UPROPERTY()
UTimelineComponent* ScoreTimeline;
UPROPERTY()
UCurveFloat* fCurve;
FOnTimelineFloat InterpFunction{};
UFUNCTION()
void TimelineFloatReturn(float val);


.cpp

#include "Components/TimelineComponent.h"

ACharacter::ACharacter(){
static ConstructorHelpers::FObjectFinder<UCurveFloat> Curvy(TEXT("CurveFloat'(パス)'"));
	if (Curvy.Object) {
		fCurve = Curvy.Object;
	}
	ScoreTimeline = CreateDefaultSubobject<UTimelineComponent>(TEXT("TimelineScore"));

	//Bind the Callbackfuntion for the float return value
	InterpFunction.BindUFunction(this, FName{ TEXT("TimelineFloatReturn") });
}

void ACharacter::TimelineFloatReturn(float val)
{
//タイムラインの値がここに返るvoid ACharacter::PlayTimeLineFunc()
{
         ScoreTimeline->AddInterpFloat(fCurve, InterpFunction, FName{ TEXT("Floaty") });
	 ScoreTimeline->Play();
	}
}

void A4Character::ReverseTimeLineFunc()
{
	
		ScoreTimeline->AddInterpFloat(fCurve, InterpFunction, FName{ TEXT("Floaty") });
		ScoreTimeline->Reverse();
	
}

UWorld

LineTraceSingleByChannel

.h

public:
	UPROPERTY(EditAnywhere)
		float RayLineLength = 1000;
	UPROPERTY(EditAnywhere)
		FLinearColor fLineColor;

	FHitResult fHitResult;
	FVector fStartLocation;
	FVector fEndLocation;
	float Duration;
	float Thickness;


.cpp

//get Camera
        UCameraComponent* CameraComp = this->FindComponentByClass<UCameraComponent>();

//DebugLine
	fStartLocation = CameraComp->GetComponentLocation();//ラインの始まり
	fEndLocation = fStartLocation + (CameraComp->GetForwardVector() * RayLineLength);//ラインの終わり
        fLineColor = FLinearColor(0.0, 255.0, 0.0, 0.0); //ラインの色
	Duration = 0.5; //継続時間
	Thickness = 1.0f; //ラインの厚さ

	UKismetSystemLibrary::DrawDebugLine(GetWorld(), fStartLocation, fEndLocation, fLineColor, Duration, Thickness);

//LineTrace
	FCollisionQueryParams fCollisionQueryParams;

	fCollisionQueryParams.TraceTag = FName("");
	fCollisionQueryParams.OwnerTag = FName("");
	fCollisionQueryParams.bTraceAsyncScene = false;
	fCollisionQueryParams.bTraceComplex = false;
	fCollisionQueryParams.bFindInitialOverlaps = false;
	fCollisionQueryParams.bReturnFaceIndex = false;
	fCollisionQueryParams.bReturnPhysicalMaterial = false;
	fCollisionQueryParams.bIgnoreBlocks = false;
	fCollisionQueryParams.IgnoreMask = 0;
	fCollisionQueryParams.AddIgnoredActor(this);

	GetWorld()->LineTraceSingleByChannel(fHitResult, fStartLocation, fEndLocation, ECollisionChannel::ECC_Visibility, fCollisionQueryParams);

	if (fHitResult.Actor == nullptr)
	{
		return;
	}

//OutputLog
	GLog->Log("On Hit an Actor of " + fHitResult.Actor->GetName() + "   " + FString::SanitizeFloat(my_Distance));