プログラミングBLOG

UE4,unityなどいろいろメモ

C++ エラー対処まとめ

C++のエラーの対処法をどんどん追加していきます。


不完全クラス型へのポインターは使用できません

インクルードを忘れている。

Unreal C++ まとめ

UE4のC++勉強中なので分かったことをここにどんどん追加していきます。
なにか間違いがあればご指摘お願いします。

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

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;

Log

OutputLog

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

GLog->Log("aaa");

出力:aaa

float value =1.0f;
GLog->Log(FString::SanitizeFloat(value));

出力:1.0f





FTimerManager

SetTimer(スタート)

.h

FTimerHandle _RateTimerHandle;
float CallRate = 0.1f;
bool Loop = true;

.cpp

UWorld* World = GetWorld();
	if (World)
	{
		if (mAim == true && mSprint == false) {
			World->GetTimerManager().SetTimer(_RateTimerHandle, this, &ACharacter::Fire(呼びたい処理), CallRate, Loop);
		}
	}

ClearTimer(ストップ)

.cpp

UWorld* World = GetWorld();
	World->GetTimerManager().ClearTimer(_RateTimerHandle);

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 TPSHOOTER_C14_API UAnimInst : public UAnimInstance
{
	GENERATED_UCLASS_BODY()
		
};


AnimInst.cpp

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

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

実装先

Character.h

UAnimMontage* Rifle_AnimMotage;
void Fire();


Character.cpp

#include "Animation/AnimInstance.h"

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

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

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

}

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;

PCで絵を書く方法

ペンタブを使って絵を書き始めたので紹介。

 PCで絵を描くには

①ペンタブor液タブ  (マウスで描けないこともないがあったほうがいい)

②ペイントソフト

が必要です。とりあえず自分が使っているのを紹介。

 

WACOM社のIntuos Draw  (ペンタブ)

価格とメジャーな会社の製品なので選びました。必要システムを下記に示します。ドライバのインストール方法も下に示します。

どれを選べばいいか分からないって方はとりあえずWACOM社のIntuous シリーズを選べばいいかと思います。

 

ペンタブの必要システム

OS:Windows7,8,10 もしくは Mac OS X 10.8.5 以降

USBポート搭載

インターネット接続

 

②Medibang paint pro

無料で割と機能もそろっているので選びました。有料ではPhotoshop,Illustrator,Clip Studio,SAIなどがあります。ここらへんはいろんな情報がネットに落ちているので

価格と情報量の多さを比べて好みで選んでください。無料はこちらから

www.gigafree.net

 

どちらかというとこっちの必要環境を気にしたほうがいいと思います。

 

 

ペンタブのドライバのインストール

そのままUSBで繋いでも使えないので使えるようにしてあげなければいけません。

付属のCDを使うかHPからダウンロードするかの2択です。付属のCDを使う場合は説明するほどではないと思うのでHPからダウンロードする方法を紹介します。

  1. https://tablet.wacom.co.jp/download/down1.html にアクセス

  2. 自分の買ったペンタブの型番をクリック→自分のOSを選択→検索をクリック

    f:id:bigden:20161227214925p:plain

  3. 最新(一番上)のドライバのダウンロードページへをクリック

    f:id:bigden:20161227215721p:plain

  4. 下にスクロールしていくと画像のようなダウンロードボタンがあるのでクリック

    f:id:bigden:20161227215835p:plain

  5. ドライバがダウンロードされるので開く
  6. 指示にしたがってインストール(同意するぐらいなので特に気にしなくてもいい)
  7. 再起動を促されるので再起動

で完了です。 

 

 

仮想キーボードの作り方(UE4.13~)

World内にキーボードとディスプレイを設置して文字を入力する方法をメモ。

VRでも利用可能みたいです。

 

①キャラクターの設定

自分の操作するキャラクター(ここではFirstPersonCharacter)にWidgetInteractionを追加します。そこからデバッグラインが出るので違和感ない場所に移動して「詳細→Debugging→Show Debug」をオンにします。

以下の画像ではSphereの下に追加していますが、FP_Gunの下でもいいようです。

f:id:bigden:20161128033313p:plain

 

②入力の設定

FirstPersonCharacterのイベントグラフに仮想キーボードのボタンを押下する動作を割り当てたい入力イベントを出します。そして、①で追加したWidget Interactionをドラックしグラフに持っていき、そこから Press Pointer KeyとRelease Pointer Keyを追加します。Keyは両方ともLeft Mouse Buttonにします。(ここでは右クリックが左クリックとみなされ、仮想キーボードのボタンを押下したことになります。)

f:id:bigden:20161128034251p:plain

 

 ③ブループリントの準備

Actorとwidgetブループリントを2つずつ作成します。(KeyPadはキーボード、Displayは入力した文字、値が表示されるディスプレイです。)

 

④Display_WB 1

Display用のWidgetブループリント(Display_WB)を開き、Canvas PanelをText Boxに置き換え、「右クリック→Wrap with...→Size Box」をクリックします。

 

f:id:bigden:20161204024618p:plain

 

⑤Display_WB 2

Size BoxをDesired on Screenにし、Width overrideとHeight overrideを好きな値に設定します。

f:id:bigden:20161204025200p:plain

 

⑥Display_WB 3

Hint Textにはここに入力してほしいことを書きます。よくログイン画面に見る「パスワード」などの薄く表示される文字です。ここはなくてもかまいませんが、ないとここに何を表示させたいのか分からなくなります。

f:id:bigden:20161206034621p:plain

 

⑦KeyPad_WB 1

KeyPad用のWidgetブループリント(KeyPad_WB)を開き、Buttonにtextを親子づけして追加して、「Detail→Content→text」には送りたい文字を書きます。他にBackSpace用とEnter用のボタンも用意します。その後、全てのボタンで 「Detail→Interaction→Is Focusable」のチェックを外します。

f:id:bigden:20161206040323p:plain

 

⑧KeyPad_WB 2

KeyPad_WBのグラフに行き、全てのボタンの「OnClicked」イベントを出します。

 

⑨KeyPad_WB 3

String型とWidgetInteractionComponent型の2つの変数を追加します。(String型をChar To Send、WidgetInteractionComponent型をWidgetInteractionと名づけました。)

f:id:bigden:20161206041040p:plain

 

⑩KeyPad_WB 4

BackSpaceとEnter以外の「OnClicked」イベントにChar To Sendをセットしつなげ、送りたい文字をセットします。アルファベットはもちろん、数字やひらがな、カタカナ、漢字も大丈夫みたいです。

f:id:bigden:20161206041252p:plain

 

⑪KeyPad_WB 5

Send Key Charを出し、ターゲットにはWidgetInteraction、CharctersにはChar To Sendを繋げます。

f:id:bigden:20161206041604p:plain

 

⑫KeyPad_WB 6

BackSpaceの「OnClicked」イベントにPress and Release Keyをつなげ、ターゲットにWidgetInteractionを繋げ、KeyをBackSpaceにします。 

f:id:bigden:20161206041611p:plain

 

⑬KeyPad_WB 7

イベントディスパーチャー(ここではEnterPressedと名付けました)を追加し、呼び出します。グラフ上までドラックしてドロップするとアクションを選べるので「呼び出す」を選択するか、右クリックで検索して出してください。

f:id:bigden:20161206041617p:plain

 

⑭Display_Actor 1

Display_Actor(Display用のアクター)を開き、Add componentからWidgetを出します。Widget Class にDisplay_WBを選択し、Draw at Desired Sizeにチェックを入れます。

モザイクをかけてますが気にしないでください。(新しく用意するのめんどくさかった)

f:id:bigden:20161210004739p:plain

 

⑮KeyPad_Actor 1

同じようにKeyPad_Actor(KeyPad用のアクター)を開き、Widget ClassにKeyPad_WBを選択します。そして、Window Focusableのチェックを外し、Draw at Desired sizeのチェックを入れます。

f:id:bigden:20161206041658p:plain

 

⑯KayPad_Actor 2

さらにAdd componentからWidget Interactionを追加し、Enable Hit Testingをオフにします。

f:id:bigden:20161206041710p:plain

 

⑰KeyPad_Actor 3

KeyPad_ActorのBegin PlayイベントにCast To KeyPad_WBを繋げ、WidgetとGet User Widget ObjectをObjectピンに繋げます。

f:id:bigden:20161206041727p:plain

 

⑱KeyPad_Actor 4

KeyPad_WBのWidgetInteractionをセットし、KeyPad_ActorのWidget Interactionを繋げます。その後、ノード検索で、EnterPressedを割り当てるを、選択するとBind Event to EnterPressedとカスタムイベントが出て来ます。

ひとつずつ、Bind Event to EnterPressedとカスタムイベントを出してもダメ。

カスタムイベントの先にはEnterを押した時にやって欲しい処理を、書きます。

f:id:bigden:20161206041746p:plain

 

⑲KeyPad_Actor 5

KeyPad_ActorにDisplay_Actor型の変数を追加します。

f:id:bigden:20161228005422p:plain

 

⑳KeyPad_Actor 6

world内にKeypadとDisplayを設置し、KeypadのTargetDisplayのところをDisplayにします。

f:id:bigden:20161210005018p:plain

 

以上です。

 

参考

docs.unrealengine.com

docs.unrealengine.com

docs.unrealengine.com

Leap motionを用いた物体移動

12/6にOculus Touchが発売されたということでおそらくもうLeap motion

代用することもないと思いますが、何かあったときのためにここにメモしておきます。

ちなみにUE4のver4.13だとなぜか出来なかったのでそれ以下をおすすめします。

(私は4.12を使用しました。)

 

 

手順

プラグインのダウンロード

以下のGithubからLeap motionプラグインをダウンロードします。

github.com

 

プラグインを使用可能に

「編集→Plugins→Input Devices」にあるLeap Motion PluginのEnabledのところにチェックを入れます。

f:id:bigden:20161118030533p:plain

 

③GameModeの作成

コンテンツブラウザの場所で右クリックメニューから「ブループリント→ブループリントクラス→Game Mode」を選択します。名前は適当に。(ここではLeapGameModeとします。)

 

④キャラクターを作成

「表示オプション→プラグインのコンテンツを表示」にチェックを入れます。その後、「LeapMotion コンテンツ→Blueprints→Rigging」からLeapRiggedCharacterをコピーし、自分のコンテンツブラウザに置きます。ここではLeapCharacterと呼びます。

 

⑤GameModeの設定

LeapGameModeを開き、Default Pawn Classを④のLeapCharacterにします。 f:id:bigden:20161118232400p:plain

 

インターフェイスの作成

右クリックメニューから「詳細なアセットを作成→ブループリント→ブループリントインターフェイス」を選択します。ここではPickup Interfaceとします。下の画像のようにインプットにスタティックメッシュアクタとVector変数を追加します。

f:id:bigden:20161118231521p:plain

 

⑦キャラクターにインターフェイスを設定

LeapCharacterを開き、クラス設定を選択し、インターフェイスの部分に⑤、⑥で作成したインターフェイスを追加します。

f:id:bigden:20161118233005p:plain

 

⑧関数の作成(キャラクター) 1

関数(ここではClosest Handという名前にします)を作成し、関数内を以下のようにします。インプットにVector型、アウトプットにName型を追加し、ローカル変数にName型変数を追加します。

f:id:bigden:20161118234512p:plain

 

 

⑨関数の作成(キャラクター) 2

もう一つ関数(ここではPickup if Emptyという名前にします)を作成し、関数内を以下のようにします。インプットにスタティックメッシュアクタ変数とBoolean変数を作成します。Closest Handは⑧で作成したものです。

 

f:id:bigden:20161207041630p:plain

 

⑩関数の作成(キャラクター) 3

さらにもう一つ関数(ここではDrop if Not Emptyという名前にします)を作成します。

f:id:bigden:20161207042222p:plain

 

⑪キャラクターのイベントグラフ

LeapCharacterのイベントグラフを以下のようにします。イベントPickupは⑥で作ったものをコンパイルしておかないと出てきません。

f:id:bigden:20161208023049j:plain

 

⑫物体のブループリントを作成

 動かしたいスタティックメッシュをレベル上に出し、詳細からブループリントを作成します。

f:id:bigden:20161208023743p:plain

 

⑬物体のブループリントのイベントグラフ

Does Implement Interface と Pickup のインターフェイスをキャラクターに追加したインターフェイスと同じにします。

f:id:bigden:20161208024600p:plain

 

すべてコンパイルしてプレイすると物体移動できるようになります。

 

 物体を掴む条件として物体に手が当たっている(当たり判定がある)ことが条件で、グーのように握らないとGrabイベントが発生してくれません。また、手に強制的にひっつけている感じであり、実際に掴んでいるわけではないみたいです。

 

参考

UE4のLeap motionプラグイン製作者が以下の動画で説明していました。

www.youtube.com

www.youtube.com

www.youtube.com

 

ブループリントプロジェクトに C++ 関数を追加する方法

よく欲しい機能のノードがなかったりしますが、自分でノードを作ることができますのでその方法をメモしておきます。

動作環境は

  •     UE4: 4.12.5  と  4.14.0
  •     Widows8.1
  •     Visual Studio Community 2015

です。

 

手順

Visual StudioXCodeのインストール

Visual StudioXCodeをインストールしておきます。Visual Studio をインストールする際は Common Tools for Visual C++ 2015 も合わせてインストールする必要だそうです。

 

②Sourceフォルダの作成

エクスプローラーからやりたいプロジェクトのプロジェクトファイル(.uproject)がある階層に行き、新しいフォルダを作成し、名前をSourceにします。

f:id:bigden:20161206223939j:plain

C++プロジェクトファイルの作成

プロジェクトファイルを右クリックすると、Generate Visual Studio project files というのがあるのでクリックします。Mac の場合はメニューの下部にサービスという項目があるのでその中にある Generate Xcode Project を選びます。

f:id:bigden:20161206224207p:plain

 

 

④新規C++クラスの作成 1

レベルエディタのメニューから「ファイル→新規C++クラス」を選択します。

f:id:bigden:20161206225351p:plain

 

⑤新規C++クラスの作成 2

以下の画面が出てくるのでアクターを選択し、「次へ」をクリックします。

f:id:bigden:20161206225617p:plain

 

⑥新規C++クラスの作成 3

ファイル名を任意の名前に決めて、公開設定をパブリックにします。その後、「クラスを作成」をクリックします。すると、ヘッダファイル(.h)とソースファイル(.cpp)が作成され、visual studioXCodeが開きます。開いていない場合はコンテンツブラウザの C++ クラス(C++ Classes)フォルダ内にある 作成した名前のファイルをダブルクリックします。

※ヘッダorソースファイルを直接ダブルクリックで開かないほうがいいみたいです。

f:id:bigden:20161206230237j:plain

 

⑦ソースファイルとヘッダファイルを編集

ソースファイルとヘッダファイルを編集します。

※ソースファイルの「#include "(作成したファイル名).h"」は一番上でないとダメみたいです。

 

コンパイル

レベルエディタのツールバーコンパイルをクリックします。成功すると作ったものがブループリントで使えるようになります。

f:id:bigden:20161206231338p:plain

 

以上です。

 

参考

hiroyukitsuda.com