【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では↓のようなノードです。
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が呼ばれます。
OnComponentEndOverlap
このイベントは対象のコンポーネントへのOverlapが終了すると実行されます。
BPでは↓のようなノードです。
基本的にはOnComponentBeginOverlapと実装方法は同じだと思います。
Overlapした際に実行したいイベントを書く関数の引数を次のように変更します。
OnComponentOverlapEnd(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);
OnActorBeginOverlap
このイベントは対象のActorに何かがOverlapすると実行されます。
BPでは↓のようなノードです。
基本的にはOnComponentBeginOverlapと実装方法は同じだと思います。
Overlapした際に実行したいイベントを書く関数の引数を次のように変更します。
OnActorOverlapBegin(AActor* OverlappedActor, AActor* OtherActor);
OnActorEndOverlap
このイベントは対象のActorへのOverlapが終了すると実行されます。
BPでは↓のようなノードです。
基本的には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++ まとめ
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));
Unityまとめ
Unityの関数などをまとめ。
時間関係
ポーズ
Time.timeScale==0;//ポーズ
Time.timeScale==1;//ポーズ解除
delay
---------180フレーム後に****の処理を行う---------
using UniRx;
Observable.TimerFrame(180).Subscribe(_ =>
{
****; //delay後の処理
}).AddTo(this);
---------0.2秒後に****の処理を行う---------
Observable.Timer(TimeSpan.FromSeconds(0.2)).Subscribe(_ =>
{
****; //delay後の処理
}).AddTo(this);
オーディオ関係
再生、停止
AudioSource BGM = GameObject.Find("****").GetComponent<AudioSource>();
BGM.Play();再生開始
BGM.Stop();一時停止
シーン移動
移動したいSceneを開き、「File→Build Setting→Add open scene」
SceneManager.LoadScene(1); //Build Settingのシーン番号
出現、消滅
******.enabled= true;
******.enabled= false;