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

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

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