Unreal C++ まとめ
UE4のC++勉強中なので分かったことをここにどんどん追加していきます。
なにか間違いがあればご指摘お願いします。
記事にまとめるとその記事に差し替えていきます。
- AActor
- BehaviorTree
- FHitResult
- Iterator
- Log
- FTimerManager
- USoundWave
- UAnimMotage
- USpringArm
- UTimeline
- UWorld
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
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));