ゲーム開発備忘録

ゲーム開発備忘録

ゲームプログラマー UE4・5向けの記事を書いておりますので見ていただけるとありがたいです。

【UE4・UE5】〈Tips〉ブループリントグラフを生成するエディタユーティリティを作る

目次

 

はじめに

ブループリントにはグラフを複数作成することができますが、皆さんは使ったことがあるでしょうか?

EventGraphにすべてを記述するとどんどん肥大化して、ノードを探すのにも一苦労といったことになりがちです。

そこで、機能やネットワークポリシーなどでグラフを分割して管理すると、可読性の向上やチーム開発においてはマージのしやすさなどの恩恵があります。

そんなグラフですがテンプレートのような形で毎回手動で作るのはめんどくさいですよね!
そんな悩みを解決するエディタユーティリティを作るため、グラフを自動生成するノードを作ってみました。

 

▽できること

 

個人の備忘録としてまとめています。誤った情報がある場合があります。

コメントにてご指摘のほどお願いいたします。

 

C++でのプロジェクトビルド環境必須です。

UE5.4.3で解説します。

 

解説

①エディタモジュールの配置

エディタ専用のノードなのでエディタモジュールに実装します。

モジュールについては以下の記事が分かりやすいので、こちらを参考にエディタ用のモジュールを作りましょう。

historia.co.jp

strv.dev

 

②モジュールの追加

エディタモジュールのDependencyModuleNamesに以下の要素を追加しておきます。

PublicDependencyModuleNames.AddRange(new string[]
{
"Core",
"CoreUObject",
"UnrealEd", // 追加
"BlueprintGraph" // 追加
});

 

③コードの追加

エディタモジュールのPublicフォルダに以下を作ります。

 

▽CustomEditorUtilityNode.h

#pragma once

#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "CustomEditorUtilityNode.generated.h"

UCLASS()
class YOUR_API UCustomEditorUtilityNode : public UBlueprintFunctionLibrary
{
GENERATED_BODY()

public:

#if WITH_EDITOR
/** Adds an event graph to the specified Blueprint.
*
* @param Blueprint Target Blueprint
* @param GraphName Create a new graph with this name
* @return bool True if the graph was added successfully
*/
UFUNCTION(BlueprintCallable, Category = "CustomEditorUtility", meta=(OnlyIncludeInEditor))
static bool AddGraphToBlueprint(UBlueprint* Blueprint, const FString& GraphName);
#endif
};
 

 

▽CustomEditorUtilityNode.cpp


#include "CustomEditorUtilityNode.h"
#include "Kismet2/BlueprintEditorUtils.h"
#include "Kismet2/KismetEditorUtilities.h"

bool UCustomEditorUtilityNode::AddEGraphToBlueprint(UBlueprint* Blueprint, const FString& GraphName)
{
if (!Blueprint)
{
UE_LOG(LogTemp, Error, TEXT("Blueprint is null!"));
return false;
}

// すでに同じ名前のイベントグラフが存在しないか確認
for (const UEdGraph* Graph : Blueprint->UbergraphPages)
{
if (Graph->GetName() == GraphName)
{
UE_LOG(LogTemp, Warning, TEXT("Graph '%s' already exists!"), *GraphName);
return false;
}
}

// 新しいイベントグラフを作成
UEdGraph* NewGraph = FBlueprintEditorUtils::CreateNewGraph(
Blueprint,
FName(*GraphName),
UEdGraph::StaticClass(),
UEdGraphSchema_K2::StaticClass()
);

if (!NewGraph)
{
UE_LOG(LogTemp, Error, TEXT("Failed to create new graph!"));
return false;
}

// Blueprintに追加
FBlueprintEditorUtils::AddUbergraphPage(Blueprint, NewGraph);

// Blueprintを更新
FBlueprintEditorUtils::MarkBlueprintAsStructurallyModified(Blueprint);
FKismetEditorUtilities::CompileBlueprint(Blueprint);

UE_LOG(LogTemp, Log, TEXT("New event graph '%s' added successfully!"), *GraphName);
return true;
}

 

これでビルドに成功するとノードが利用できるようになります!

※エディタ用のBPなのでランタイム想定のBPでは配置できないはずです。

 

④ツールの追加

エディタに戻り、コンテンツを右クリック->エディタユーティリティ->エディタユーティリティブループリントを選択します。

 

アセットアクションユーティリティを選択します。

 

名前はEUB_AddCustomGraphとしました。

 

アセットを開き、クラスのデフォルトからブループリント用のアクションであるにチェックを付けます。

 

⑤ツールの編集

"ほげ"と"ふが"を追加する関数GenerateGraph"HOGE"_"FUGA"を作りました。

 

エディタで呼び出す が有効になっていることを確認しましょう。

 

選択されているブループリントアセットに対してHOGEとFUGAを追加するようにします。※エラー表示などはbool値でよしなにしてください。

⑥ツールの使い方

グラフを追加したいBPをコンテンツブラウザ上で右クリック

->スクリプト化された~から作成した関数を押します。

 

やった!!!

 

 

最後に

需要があれば、イベントノードの生成とかも書くかもしれません。

UE4やUE5向けの記事を書いています。

皆様の応援が投稿のモチベーションになりますので

コメントやX(Twitter)のフォローなどしていただけるとありがたいです。

それではよきゲーム開発を。

投げ銭を投げる

 

【UE4・UE5】〈Tips〉Console Variable 通称CVarの使い方と変更検知を取得する方法

目次

 

はじめに

本記事では Console Variable(CVar)の基本 と、BPで変更を検知する方法 について解説します。

・CVar の作成・更新・取得
C++ で変更を監視する ConsoleVariableListener
・BP での利用方法

 

個人の備忘録としてまとめています。誤った情報がある場合があります。

コメントにてご指摘のほどお願いいたします。

UE5.4.3で解説します。

 

解説

Console Variableの概要

Console Variable(CVar) は、Unreal Engine の開発コンソールから値を変更できる変数のことです。ゲームの デバッグ や パフォーマンス調整、設定の切り替え などに活用されます。

Console Variableの作成

プロジェクト設定からCvarsを作成することができます。

 

3つのタイプから選ぶことができます。

 

今回は以下のような機能を定義してみました。

 

Console Variableの更新

CVar のプロパティ名 + 値

で更新を行うことができます。

▽コンソールから実行


▽BPから実行

 

Console Variableの取得

特定のConsoleVariableを取得する場合はこちらを行います。

 

Console Variableの変化検知

BPにはこの変更を検知する仕組みが公開されていないので、

そこで、C++で定義されている関数をBPで利用できるような機能を作りました。


取得された値が0などの場合、どの型であるかの判定をするのが難しいと判断したため

、個別にインスタンスを作成し取得する型は運用でカバーできる形にしました。

 

これを利用することで、異なる場所で実行されたコンソールの変更を検知することができます。

 

▽ConsoleVariableListener.h

#pragma once

#include "CoreMinimal.h"
#include "ConsoleVariableListener.generated.h"

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnConsoleVariableChanged, FString, ChangeConsoleVariableName);


UCLASS(Blueprintable)
class UConsoleVariableListener : public UObject
{
GENERATED_BODY()

public:
/**監視するコンソール変数の追加
*
* @param ConsoleVariableNames 追加するConsoleVariable
*/
UFUNCTION(BlueprintCallable, Category = "ConsoleVariable")
void WatchConsoleVariables(const TArray<FString>& ConsoleVariableNames);


/**除外するコンソール変数の追加
*
* @param ConsoleVariableName 除外するConsoleVariable
*/
UFUNCTION(BlueprintCallable, Category = "ConsoleVariable")
void UnwatchConsoleVariable(FString ConsoleVariableName);

// 全てのコンソール変数の監視を解除
UFUNCTION(BlueprintCallable, Category = "ConsoleVariable")
void UnwatchAllConsoleVariables();

// コンソール変数の変更通知デリゲート
UPROPERTY(BlueprintAssignable, Category = "ConsoleVariable")
FOnConsoleVariableChanged OnVariableChanged;

private:
void OnCVarChanged(IConsoleVariable* CVar, FString VariableName) const;
void ClearConsoleVariableCallback(const FString& VariableName);

TMap<FString, FConsoleVariableDelegate> ConsoleVariableCallbacks;
};

 

▽ConsoleVariableListener.cpp

#include "ConsoleVariableListener.h"
#include "Engine/Engine.h"
#include "HAL/IConsoleManager.h"

void UConsoleVariableListener::WatchConsoleVariables(const TArray<FString>& ConsoleVariableNames)
{
for (const FString& VariableName : ConsoleVariableNames)
{
// すでに登録されている場合はスキップ
if (ConsoleVariableCallbacks.Contains(VariableName))
{
continue;
}
if (IConsoleVariable* CVar = IConsoleManager::Get().FindConsoleVariable(*VariableName))
{
// 変更検知用のデリゲート作成
FConsoleVariableDelegate Callback = FConsoleVariableDelegate::CreateLambda(
[this, VariableName](IConsoleVariable* Var)
{
OnCVarChanged(Var, VariableName);
});

// 変更コールバックを設定
CVar->SetOnChangedCallback(Callback);
ConsoleVariableCallbacks.Add(VariableName, Callback);
}
else
{
UE_LOG(LogTemp, Warning, TEXT("Console Variable '%s' が見つかりません"), *VariableName);
}
}
}

void UConsoleVariableListener::UnwatchConsoleVariable(FString ConsoleVariableName)
{
if (ConsoleVariableCallbacks.Contains(ConsoleVariableName))
{
UE_LOG(LogTemp, Warning, TEXT("Console Variable '%s' が監視されていません"), *ConsoleVariableName);
return;
}
ClearConsoleVariableCallback(ConsoleVariableName);
// マップから削除
ConsoleVariableCallbacks.Remove(ConsoleVariableName);
}

void UConsoleVariableListener::UnwatchAllConsoleVariables()
{
for (const auto& Pair : ConsoleVariableCallbacks)
{
ClearConsoleVariableCallback(Pair.Key);
}

// マップをクリア
ConsoleVariableCallbacks.Empty();
}

void UConsoleVariableListener::ClearConsoleVariableCallback(const FString& VariableName)
{
if (IConsoleVariable* CVar = IConsoleManager::Get().FindConsoleVariable(*VariableName))
{
CVar->SetOnChangedCallback(FConsoleVariableDelegate());
}
}

void UConsoleVariableListener::OnCVarChanged(IConsoleVariable* CVar, FString VariableName) const
{
if (!CVar)
{
return;
}
OnVariableChanged.Broadcast(VariableName);
}

 

最後に

UE4やUE5向けの記事を書いています。

皆様の応援が投稿のモチベーションになりますので

コメントやX(Twitter)のフォローなどしていただけるとありがたいです。

それではよきゲーム開発を。

投げ銭を投げる

 

【Rider】〈Tips〉フォルダ以下でコード内文字列検索のショートカット

目次

 

はじめに

Riderディレクトリ階層以下での文字列検索をするときのショートカットについてのメモです。

個人の備忘録としてまとめています。誤った情報がある場合があります。

コメントにてご指摘のほどお願いいたします。

 

参考にしたサイト

pleiades.io

バージョンはJetBrains Rider 2024.3.4です。

メモ

検索したいフォルダに移動して、

Ctrl+Shift+F

で検索できます。

 

検索したいディレクトリのルートを変えたい場合は

パスの横にある … を押すことで変更可能です。

 

最後に

UE4やUE5向けの記事を書いています。

皆様の応援が投稿のモチベーションになりますので

コメントやX(Twitter)のフォローなどしていただけるとありがたいです。

それではよきゲーム開発を。

投げ銭を投げる

 

【UE4・UE5】〈Tips〉知っていると得するキャラクターが持つ便利なDelegateの紹介(着地・移動検知・モード切替・ジャンプ最高到達点)

目次

 

はじめに

Characterクラスがブループリントに公開しているディスパッチャは4種類あります。
意外と知られていないのでこの記事で紹介します。

 

個人の備忘録としてまとめています。誤った情報がある場合があります。

コメントにてご指摘のほどお願いいたします。

UE5.4で解説します。

解説

LandedDelegate

ジャンプや落下など着地したときに発火します。

 

 

なおCharacterBP自体にはLandedが存在するためDelegateでなくていいのであればこちらを利用しましょう。

 

ちなみにEvent On Walking Off Ledgeノードであればジャンプではなく落下のみのイベントを取得できます。


CharacterMovementUpdated

キャラクターの加速度や位置を取得できます。

以下のサンプルでは移動しているかの検知をするサンプルです。


Tickを利用して同様のチェックをすることもできますが、このノードの実装のコメントを見るとマルチプレイにおいては、このDelegateを利用することを推奨しています。

サーバー/クライアント間の移動処理の同期タイミングと、Tickのタイミング独立してしまうため、サーバーの補正が行われる前の位置情報を元に処置を行ってしまう懸念があります。

そのため、このイベントの発火元であるCharacterMovementComponentはネットワークを考慮し補正後の値を返すので正確な位置情報を元に取得できるようです。

 

MovementModeChangedDelegate

MovementModeの変化を検知して発火するDelegateです。

取得で更新したい場合はSetMovementModeから更新できます。

注意点として、イベントノードのピンにPrevとついているのでここで返ってくる値は変更前の値なので上のように変数から現在の値を取らないといけません。

 

なおCharacterBP自体にはModeChangedが存在するためDelegateでなくていいのであればこちらを利用しましょう。

 

OnReachedJumpApex

落下中の最高到達点になったら通知します。

このイベントを使うには落下中にChreacterMovementのNotifyApexの変数を更新する必要があるので忘れずに。

 

2Dゲームなど、落下時に画像を書き換えたりするときに利用するのもいいかもしれません。

 

最後に

UE4やUE5向けの記事を書いています。

皆様の応援が投稿のモチベーションになりますので

コメントやX(Twitter)のフォローなどしていただけるとありがたいです。

それではよきゲーム開発を。

投げ銭を投げる

 

【UE4・UE5】〈Tips〉自作プラグインからプロジェクトにGameplayTagを追加する方法

目次

 

はじめに

プラグインを追加したときにGameplayTagを自動的に付与したい場合に見る記事です

参考にしたフォーラム

forums.unrealengine.com

 

個人の備忘録としてまとめています。誤った情報がある場合があります。

コメントにてご指摘のほどお願いいたします。

UE5.5で解説します。

解決法

プラグインフォルダー/Config/Tagsの下に追加します。

 

GameplayTag.iniのタグの追加のサンプル

[/Script/GameplayTags.GameplayTagsList]
GameplayTagList = (Tag="CustomPluginTag.Hoge",DevComment="")
GameplayTagList = (Tag="CustomPluginTag.Fuga",DevComment="")

 

プラグイン.Build.csに以下を追加

PublicDependencyModuleNames.AddRange(
new string[]
{
"Core",
"GameplayTags"
// ... add other public dependencies that you statically link with here ...
}
);

 

プラグイン名.cpp

class Fプラグイン名Module : public IModuleInterface
{
public:

/** IModuleInterface implementation */
virtual void StartupModule() override;
virtual void ShutdownModule() override;
};

 

StartupModuleに追加

この時のパスはpluginsフォルダーからこのプラグインのTagsまでのパスなので注意して下さい。※プラグイン自体をユーザーがplugins/Hoge/CustomPluginみたいに配置されると読み込めない。

#include "プラグイン.h"
#include "GameplayTagsManager.h" //追加

#define LOCTEXT_NAMESPACE "FプラグインModule"

void Fプラグイン名Module::StartupModule()
{
//追加
UGameplayTagsManager::Get().AddTagIniSearchPath(FPaths::ProjectPluginsDir() / TEXT("プラグイン/Config/Tags"));
}

 

 

ビルドして完成です。

 

最後に

UE4やUE5向けの記事を書いています。

皆様の応援が投稿のモチベーションになりますので

コメントやX(Twitter)のフォローなどしていただけるとありがたいです。

それではよきゲーム開発を。

投げ銭を投げる

 

【UE4・UE5】〈Tips〉プレイヤーが任意の範囲にいるかどうかをチェックする簡単な方法

目次

 

はじめに

ゲーム開発で求められる機能の中で、○○にいたら~するといった仕様は多く存在します。

例えば、

・裏世界でベッドを配置したときのみ爆発する。

・ホラーゲームで特定の範囲のプレイヤーだけに対して音や映像を流したい。

キャラクターがボリュームに入ったときついてはOverlapイベント等の通知として取得できますが、これでは既にボリュームに入っている場合は変数をどこかで持っている必要があったりとやや管理が面倒です。


そのなときに便利なノードを紹介します。

個人の備忘録としてまとめています。誤った情報がある場合があります。

コメントにてご指摘のほどお願いいたします。

UE5.4で解説します。

解説

前提

紹介するノードが機能するにはコンポーネントやアクタの当たり判定が互いに検出できる必要があります。コリジョンの設定からOverlapもしくはBlockされているかどうかを確認しましょう。

Is Overlapping Actor / Is Overlapping Component 

自身が特定のアクタやコンポーネントの範囲にいるかどうかを検知するときに便利なノードです。

 

例: Fボタンを押したときに水中にいるかどうかを判定する。

 

Component Overlap Actors / Get Overlapping Components

任意のコンポーネントに対して複数のActorやコンポーネントを返します。

 

例: このコリジョンの中にいるアクターに対して1秒ごとにダメージを1与える毒エリア

最後に

UE4やUE5向けの記事を書いています。

皆様の応援が投稿のモチベーションになりますので

コメントやX(Twitter)のフォローなどしていただけるとありがたいです。

それではよきゲーム開発を。

投げ銭を投げる

 

【UE4・UE5】〈Tips〉キャラクターの移動に対して地面にブロック状の影やノイズが表示される場合の解決方法

目次

 

はじめに

 

キャラクターが移動した際に影が画像のように切れたようなものが発生する問題に直面した時の修正方法です。


これはカリングやシャドーマップの生成に利用されるオブジェクトのBounds(オブジェクト境界)が小さいことが問題で起こるようです。

参考にしたフォーラム

forums.unrealengine.com


UE5.4で解説します。

メモ

①操作しているキャラクターのスケルタルメッシュを開きます

 

②メッシュ->バウンドを開いてプレビューします

③アセット詳細->Boundsからカリングに利用されるBoundsを広げます

 

最後に

UE4やUE5向けの記事を書いています。

皆様の応援が投稿のモチベーションになりますので

コメントやX(Twitter)のフォローなどしていただけるとありがたいです。

それではよきゲーム開発を。

投げ銭を投げる