fc2ブログ

凛(kagring)のUE5/UE4とゲーム制作と雑記ブログ

2016 年から UE4 / 2021年から UE5 を触り始めました。勉強したもののメモ用ブログです。ゲーム制作に関するメモや雑記とか色々あります。C++ での Qt、Unity もほんの少しあります。

2022年09月 | ARCHIVE-SELECT | 2022年11月

| PAGE-SELECT | NEXT

≫ EDIT

UE5 「Json Blueprint Utilities」を使って構造体(Structure)を「Json」データとして外部ファイルに出力する(Convert Struct Json To String、Load Json from String、Save Json to File、Json Blueprint Utilities)

「Json Blueprint Utilities」を使って構造体(Structure)を「Json」データとして外部ファイルに出力する方法です。

「Json Blueprint Utilities」というプラグインを使うことで簡単に「Json」データを扱います。
「Json Blueprint Utilities」については下記を見てみてください。

・構造体(Structure)を「Json」文字列として出力する
http://kagring.blog.fc2.com/blog-entry-829.html

まずは構造体を「Convert Struct Json To String」ノードで「Json」文字列に変換します。
JsonStruct002.jpg
これで構造体のデータが「Json」文字列としてアウトプットされます。

次に「Json」文字列を「Load Json from String」ノードで「Json」データに変換します。
構造体をJsonファイルとしてに外部に出力する001
「Json String」は「Json」文字列とを指定します。
今回は「Convert Struct Json To String」で作成した「Json」文字列を指定します。
成功すると「Success」が「True」となり、「Json Object」を取得することができます。

「Json」データが作成できたので「Save Json to File」ノードを使って外部ファイルに保存します。
構造体をJsonファイルとしてに外部に出力する002
「Json Object」には「Json」データを指定します。
「File」には出力先のファイルパスを指定します。

というわけで上記をつかって構造体を「Json」データとして外部ファイルに保存する処理を書いてみました。
構造体をJsonファイルとしてに外部に出力する000

手元でも一応こんな感じで「Json」データのファイルを作成することができました。
読み込みも結構簡単にできるので、簡易的に使う分には十分なのではないかなと思います。

| UE5 | 10:00 | comments:0 | trackbacks:0 | TOP↑

≫ EDIT

UE5/UE4 C++でクリップボードに文字列をコピー(Copy)したり、クリップボードから文字列をペースト(Paste)する(FPlatformApplicationMisc::ClipboardCopy、FPlatformApplicationMisc::ClipboardPaste)

C++でクリップボードに文字列をコピー(Copy)したり、クリップボードから文字列をペースト(Paste)する方法です。

こちらを参考にさせていただきました。

・【UE4】クリップボードから文字列を取得、設定 Copy&Paste
https://shuntaendo.hatenablog.com/entry/2020/09/21/230000

まずはクリップボードに文字列をコピーする方法です。
文字列をコピーするには「FPlatformApplicationMisc::ClipboardCopy」関数を使います。

#include "HAL/PlatformApplicationMisc.h"

// クリップボードに指定文字列をコピー
FString aCopyString(TEXT("Clipboard Copy"));
FPlatformApplicationMisc::ClipboardCopy(*aCopyString);

「aCopyString」で指定した文字列をクリップボードにコピーします。

次にクリップボードから文字列をペーストする方法です。
文字列をペーストするには「FPlatformApplicationMisc::ClipboardPaste」関数を使います。

#include "HAL/PlatformApplicationMisc.h"

// クリップボードから文字列をペースト(取得)
FString aPasteString;
FPlatformApplicationMisc::ClipboardPaste(aPasteString);

クリップボードにある文字列を「aPasteString」に取得します。

上記関数を使うには「ApplicationCore」をモジュールに追加する必要があるので注意してください。

ペーストの方はともかくとして、コピーの方はエディタで何かをいろいろした場合に、
他の箇所に貼り付けられるようにクリップボードに文字列を渡すことがありそうなので覚えておきたいですね。

| UE5 | 10:00 | comments:0 | trackbacks:0 | TOP↑

≫ EDIT

UE5/UE4 C++で配列の領域をあらかじめ確保(事前割り当て)した状態で扱う(Reserve、Reset、Empty、Shrink、Compact)

C++で配列の領域をあらかじめ確保(事前割り当て)した状態で扱う方法です。

こちらを参考にさせていただきました。

・パフォーマンスを高めるために TArray の使用を最適化する
https://www.unrealengine.com/ja/blog/optimizing-tarray-usage-for-performance?sessionInvalidated=true

公式ドキュメントはこちら。

・TMap
https://docs.unrealengine.com/4.27/ja/ProgrammingAndScripting/ProgrammingWithCPP/UnrealArchitecture/TMap/

上記ドキュメントの「スラック(Slack)」と呼ばれる部分が上記に該当するようです。

領域の確保には「Reserve」関数を使います。

// 領域確保
TArray< FName> aNameList;
aNameList.Reserve(16);

これで16個分の配列の領域が確保されるようです。

この確保された状態で「Empty」関数を実行してしまうと確保したものがすべて削除されてしまいます。
確保した領域を保持したまま要素をすべて削除する場合は「Reset」関数を使います。

// 領域を確保したまま要素をすべて削除
TArray< FName> aNameList;
aNameList.Reset();


「Reserve」関数で設定したサイズ以外で要素を削除したい場合は
「Empty」関数に引数を指定
することでも制御することができます。

Reset を呼び出すか、0 ではないスラック パラメータを指定して Empty を呼び出すことで、使用中のメモリの割り当てを解除することなく要素を削除することができます。

ここらへんですね。

確保した領域を削除したい場合は「Empty」関数を使うか、
「Compact」関数と「Shrink」を組み合わせる
ことで制御することができます。

すべてのスラックを削除するには、Shrink を実行する準備のために、まず Compact 関数を呼び出して、空いたスペースをまとめます。

上記の使い方をどこでするかはあまり想定できないのですが、
詳しくは公式ドキュメントの挙動を見てもらったほうが良いと思います。

なるべく効率よくゲームが作れるようこういったテクニックも覚えておきたいですね。

| UE5 | 10:00 | comments:0 | trackbacks:0 | TOP↑

≫ EDIT

UE5/UE4 C++でアニメーション通知(Animation Notifications)の「AnimNotifyState」を作成する(UAnimNotifyState)

C++でアニメーション通知(Animation Notifications)の「AnimNotifyState」を作成する方法です。

こちらを参考にさせていただきました。

・UE4 AnimNotifyをC++で書く場合のメモ
https://qiita.com/unknown_ds/items/ecadbe7b76cb3b1835d9

公式ドキュメントはこちら。

・UAnimNotifyState
https://docs.unrealengine.com/4.27/en-US/API/Runtime/Engine/Animation/AnimNotifies/UAnimNotifyState/

アニメーション通知(Animation Notifications)の「AnimNotifyState」を作るには
「UAnimNotifyState」を継承したクラス
を作成します。

まずはヘッダの定義になります。

#include "Animation/AnimNotifies/AnimNotifyState.h"

// AnimNotifyStateクラス
class UAnimNotifyState_New : public UAnimNotifyState
{

GENERATED_BODY()
public:
// コンストラクタ
UAnimNotifyState_New ();
public:
// Notify 設定
virtual FString GetNotifyName_Implementation() const override;
virtual void NotifyBegin(USkeletalMeshComponent* MeshComp, UAnimSequenceBase * Animation, float TotalDuration, const FAnimNotifyEventReference& EventReference);
virtual void NotifyEnd(USkeletalMeshComponent* MeshComp, UAnimSequenceBase * Animation, const FAnimNotifyEventReference& EventReference);
virtual void NotifyTick(USkeletalMeshComponent* MeshComp, UAnimSequenceBase * Animation, float FrameDeltaTime, const FAnimNotifyEventReference& EventReference);
public:
// 公開変数
UPROPERTY(EditAnywhere, BlueprintReadWrite)
int32 Value;
};

上記で「UAnimNotifyState」を継承したクラスを作成しました。

「GetNotifyName_Implementation」関数は「Notify」を配置した場合に表示される文字列を記述します。
・「NotifyBegin」関数は「Notify」が開始した時の処理を記述します。
・「NotifyEnd」関数は「Notify」が終了した時の処理を記述します。
・「NotifyTick」関数は「Notify」が実行中の処理を記述します。
・変数を定義することで「Notify」のパラメータとして受け取ることができます。

次に実際の処理を記述します。

・通知が開始された時の処理(NotifyBegin)

// 通知が開始された時の処理
void UAnimNotifyState_New ::NotifyBegin(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, float TotalDuration, const FAnimNotifyEventReference& EventReference)
{

// 取得
TObjectPtr< AActor> aActor = Cast< AActor>(MeshComp->GetOwner());

// 何か処理色々
}


・通知が終了した時の処理(NotifyEnd)

// 通知が終了した時の処理
void UAnimNotifyState_New ::NotifyEnd(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, const FAnimNotifyEventReference& EventReference)
{

// 取得
TObjectPtr< AActor> aActor = Cast< AActor>(MeshComp->GetOwner());

// 何か処理色々
}


・通知が実行中の処理(NotifyTick)

// 通知が実行中の処理
void UAnimNotifyState_New ::NotifyTick(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, float FrameDeltaTime, const FAnimNotifyEventReference& EventReference)
{

// 取得
TObjectPtr< AActor> aActor = Cast< AActor>(MeshComp->GetOwner());

// 何か処理色々
}


こんな感じで通知がきたときの処理を書くことができます。

簡単な通知はBPで作ってしまったほうが良い場合もありますが、
ある程度複雑な処理の場合はC++で書いた方が楽なのかなと思いました。

| UE5 | 10:00 | comments:0 | trackbacks:0 | TOP↑

≫ EDIT

UE5/UE4 C++でアニメーション通知(Animation Notifications)の「AnimNotify」を作成する(UAnimNotify)

C++でアニメーション通知(Animation Notifications)の「AnimNotify」を作成する方法です。

こちらを参考にさせていただきました。

・UE4 AnimNotifyをC++で書く場合のメモ
https://qiita.com/unknown_ds/items/ecadbe7b76cb3b1835d9

公式ドキュメントはこちら。

・UAnimNotify
https://docs.unrealengine.com/5.0/en-US/API/Runtime/Engine/Animation/AnimNotifies/UAnimNotify/

アニメーション通知(Animation Notifications)の「AnimNotify」を作るには
「UAnimNotify」を継承したクラス
を作成します。

まずはヘッダの定義になります。

#include "Animation/AnimNotifies/AnimNotify.h"

// AnimNotify クラス
class UAnimNotify_New : public UAnimNotify
{

GENERATED_BODY()
public:
// コンストラクタ
UAnimNotify_New ();
public:
// Notify 設定
virtual FString GetNotifyName_Implementation() const override;
virtual void Notify(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation) override;
public:
// 公開変数
UPROPERTY(EditAnywhere, BlueprintReadWrite)
int32 Value;
};

上記で「UAnimNotify」を継承したクラスを作成しました。

「GetNotifyName_Implementation」関数は「Notify」を配置した場合に表示される文字列を記述します。
・「Notify」関数は「Notify」が実行された時の処理を記述します。
・変数を定義することで「Notify」のパラメータとして受け取ることができます。

次に実際の処理を記述します。

// 通知が来た時の処理
void UAnimNotify_New::Notify(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation)
{

// 取得
TObjectPtr< AActor> aActor = Cast< AActor>(MeshComp->GetOwner());

// 何か処理色々
}

こんな感じで通知がきたときの処理を書くことができます。

簡単な通知はBPで作ってしまったほうが良い場合もありますが、
ある程度複雑な処理の場合はC++で書いた方が楽なのかなと思いました。

| UE5 | 10:00 | comments:0 | trackbacks:0 | TOP↑

≫ EDIT

UE5 C++で「Gameplay Ability(UGameplayAbility)」を継承した独自の「Gameplay Ability(UGameplayAbility)」を作成する(UGameplayAbility)

C++で「Gameplay Ability(UGameplayAbility)」を継承した独自の「Gameplay Ability(UGameplayAbility)」を作成する方法です。

他のクラスでの継承と同様に「UGameplayAbility」を継承したクラスを作成します。

// include
#include "Abilities/GameplayAbility.h"

// UGameplayAbility を継承した独自のクラスを作成
UCLASS()
class UNewGameplayAbility : public UGameplayAbility
{

//
GENERATED_BODY()
};


「UGameplayAbility」を継承したクラスは、
上記のように特に何かメンバ変数やメンバ関数を持っていなくてはいけない。みたいなことはないので、
後々のことも考えて継承しておくというのもよいのかなと思います。

「GameplayAbility」はかなり処理が切り離せるので便利だと思うので、
動作として必要なことは一通りできるようになるように設計できると量産にも向いているのかなと思いました。

| UE5 | 10:00 | comments:0 | trackbacks:0 | TOP↑

≫ EDIT

UE5/UE4 BPの「For Each」系ノードでピン接続が無いのに型が「Wildcard 型(灰色ピン)」以外になってしまった場合の対処方法(Alt+左クリックでの接続外し操作)

BPの「For Each」系ノードでピン接続が無いのに型が「Wildcard 型(灰色ピン)」以外になってしまった場合の対処方法についてです。

Twitter でこちらのツイートを見かけたのでメモとなります。

上記説明を見る限りですと、
型が固定されてしまった箇所に対して「Alt+左クリック」などでの接続を外す処理を行うことで
元の「Wildcard型(灰色ピン)」に戻るということのようです。

こういうノウハウすごく助かります!

| UE5 | 10:00 | comments:0 | trackbacks:0 | TOP↑

≫ EDIT

UE5 「AI Move To」でアニメーションブループリント(Animation Blueprint)が機能しない場合の対処方法(Use Accelerationfor Paths、Character Movement Component)

「AI Move To」でアニメーションブループリント(Animation Blueprint)が機能しない場合の対処方法についてです。

Twitter でこちらのツイートを見かけたのでメモとなります。

アニメーション関係は詳しくないのでほんと先駆者さんのをそのままメモとなっています。
こういうノウハウ本当に感謝してます!

| UE5 | 10:00 | comments:0 | trackbacks:0 | TOP↑

≫ EDIT

UE5 「IK リグのリターゲティング(IK Rig Retargeting)」を使ってルートモーション(Root Motion)をリターゲットする際の対処方法(Translation Mode、Globally Scaled)

「IK リグのリターゲティング(IK Rig Retargeting)」を使ってルートモーション(Root Motion)をリターゲットする際の対処方法についてです。

Twitter でこちらのツイートを見かけたのでメモとなります。

ここらへんはこのスライドが参考になるのかなと思いました。

ここも気を付けたほうが良いようですね。

アニメーション関係は詳しくないのでほんと先駆者さんのをそのままメモとなっています。
こういうノウハウ本当に感謝してます!

| UE5 | 10:00 | comments:0 | trackbacks:0 | TOP↑

≫ EDIT

UE5 コンポーネント(Component)の「スケルタルメッシュ(SkeletalMesh)」へのアクセスでメンバ変数が「nullptr」になってしまったり「Warning」が出る場合の対処方法(Get Skeletal Mesh Asset、Skeletal Mesh Component、Skinned Mesh Component)

コンポーネント(Component)の「スケルタルメッシュ(SkeletalMesh)」へのアクセスでメンバ変数が「nullptr」になってしまったり「Warning」が出る場合の対処方法についてです。

Twitter でこちらのツイートを見かけたのでメモとなります。

「Mesh Component」系のからのアクセスで
「SkeletalMesh」のメンバ変数でアクセスする
とUE5.1 では Warning がでるようです。
51でのメッシュの取得000

自分の手元でも確認してみましたが、確かに Warning がでるようです。
51でのメッシュの取得001
こんな感じですね。

「Mesh Component」から「SkeletalMesh」を取得する場合は「Get Skeletal Mesh Asset」ノードを使うようです。
51でのメッシュの取得002

新規で処理を作る場合はあまり問題になることはなさそうですが、
今まで作ったものについては結構やっかいな問題になりそうですね…。

| UE5 | 10:00 | comments:0 | trackbacks:0 | TOP↑

| PAGE-SELECT | NEXT