Blog

[UE4] プラグインとアクタの連携について(1)

執筆者 / K.T

はじめに

UE4で、レベルに依存しない汎用的な処理を、プラグインとして切り離しておくと便利です。

プラグインに、アクタとの連携機能やティック機能を持たせれば、より使い勝手が良くなります。

そのようなプラグインのサンプルを作成してみます。

この記事の内容

長いので、2回に分けてお送りします。

今回(1/2)は、サンプルのプロジェクトを作成した上で、以下のような機能を持つプラグインを追加します。

 1.デリゲートを持ち、アクタのイベント関数を結合できる

 2.ティック機能を持ち、ティック関数が呼び出される

 3.ティック関数でデリゲートを実行し、パラメータ(角度)をアクタのイベント関数へ送る

 4.パラメータ(角度)は等速で増え続ける

次回(2/2)は、アクタがイベント関数でパラメータ(角度)を受け取り、自身のZ軸回転に反映させるようにします。

つまりアクタがコマのようにくるくる回るようにします。

また、カメラをアクタの背後に置いて、アクタと一緒に回転するようにします。

これによって生じる問題点についても解説し、修正を行います。

用意するもの

・Unreal Engine 4.23.1

・Visual Studio 2017

プロジェクトの作成

プロジェクトブラウザを起動し、新規プロジェクトを作成します。

C++タブの基本コードを選択し、スターターコンテンツは有りにしましょう。

プロジェクトを作成したら、いったん閉じます。

そして、できあがったプロジェクトのContentフォルダ内に、Flyingというフォルダを作成してください。

作成したFlyingフォルダの中に、以下のフォルダから4つのアセットファイルをコピーします。

UE_4.23\Templates\TemplateResources\Standard\Flying\Content\Meshes

ここまでできたら、プロジェクトを起動してください。

メッシュの設定

コンテンツ/Flyingフォルダ内のUFOMaterialを開きます。

詳細の[一般]-[Parent]にBaseMaterialを設定すると、パラメータグループが現れるので、保存後に閉じてください。

続いて、同じくFlyingフォルダ内のUFOを開きます。

詳細の[Material Slots]-[エレメント0]にUFOMaterialを設定すると、メッシュが水色に変わるので、保存後に閉じてください。

アクタの設定

コンテンツフォルダ内にブループリントクラスを新規追加します。

親クラスはActorにしてください。

作成したActorFlyingを開きます。

DefaultSceneRootの下に、StaticMeshComponentを追加してください。

詳細の[Static Mesh]-[Static Mesh]にUFOを設定します。

また、[Materials]-[エレメント0]にUFOMaterialを設定します。

コンパイルして保存後に閉じてください。

ActorFlyingをビューポートにドラッグ&ドロップして、マップへ配置します。

詳細の[トランスフォーム]で、アクタの位置や回転を図のように設定してください。

プラグインの作成

メニューの[編集]-[プラグイン]を選択します。

[New Plugin]ボタンを押してください。

Blueprint Libraryを選択し、[Name]にControlActorと入力してください。

[Create Plugin]ボタンを押すと、プラグインのひな形が作成されます。

プラグインの編集

Visual Studioでソリューションが開かれるので、プラグインのソースコードを編集していきましょう。

図でフォーカスされている4つのファイルが対象です。

編集が終わったら、ソリューションをビルドして、保存後に閉じてください。

ControlActorBPLibrary.h
#pragma once
#include “Kismet/BlueprintFunctionLibrary.h”#include “ControlActorBPLibrary.generated.h”
// 動的デリゲートの宣言(引数としてfloatを1つ渡します)DECLARE_DYNAMIC_DELEGATE_OneParam(FControlActorEvent, float, RotYaw);
UCLASS()class UControlActorBPLibrary : public UBlueprintFunctionLibrary{ GENERATED_UCLASS_BODY()
// イベント関数を結合(ブループリントから呼び出せる関数です) UFUNCTION(BlueprintCallable, Category=”ControlActor”) static void BindEvent(UObject* object, FName func_name);};
ControlActorBPLibrary.cpp
#include “ControlActor.h”
// コンストラクタUControlActorBPLibrary::UControlActorBPLibrary(const FObjectInitializer& ObjectInitializer): Super(ObjectInitializer){}
// イベント関数を結合void UControlActorBPLibrary::BindEvent(UObject* object, FName func_name){ FControlActorModule::BindEvent(object, func_name);}
ControlActor.h
#pragma once
#include “Modules/ModuleManager.h”#include “Tickable.h”#include “ControlActorBPLibrary.h”
class FControlActorModule : public IModuleInterface, public FTickableGameObject{private: FControlActorEvent m_Event; // イベント用のデリゲート
public: // モジュール関連の関数 virtual void StartupModule() override {} virtual void ShutdownModule() override {}
static inline FControlActorModule& Get(void){ return FModuleManager::LoadModuleChecked< FControlActorModule >( “ControlActor” ); } static inline bool IsAvailable(void){ return FModuleManager::Get().IsModuleLoaded( “ControlActor” ); } static FControlActorModule* GetInstance(void){ return ( FControlActorModule::IsAvailable() ? &Get() : nullptr ); }
// ティック関連の関数 virtual TStatId GetStatId(void) const { RETURN_QUICK_DECLARE_CYCLE_STAT(FControlActorModule, STATGROUP_Tickables); } virtual bool IsTickable(void) const { return true; } virtual void Tick(float delta_time);
// イベント関数を結合 static void BindEvent(UObject* object, const FName& func_name);};
ControlActor.cpp
#include “ControlActor.h”
#define LOCTEXT_NAMESPACE “FControlActorModule”
// ティックvoid FControlActorModule::Tick(float delta_time){ static float rot_yaw = 0.0f;
rot_yaw += 5.0f; // 角度を更新 if(rot_yaw > 360){ rot_yaw -= 360; }
m_Event.ExecuteIfBound(rot_yaw); // デリゲートを実行}
// イベント関数を結合void FControlActorModule::BindEvent(UObject* object, const FName& func_name){ FControlActorModule* module = GetInstance();
if(module == nullptr){ return; } // インスタンスの取得失敗
if((object == nullptr) || func_name.IsNone()){ module->m_Event.Clear(); // 引数が不正 }else{ // デリゲートにイベント関数を結合 module->m_Event.BindUFunction(object, func_name); }}
#undef LOCTEXT_NAMESPACE IMPLEMENT_MODULE(FControlActorModule, ControlActor)

プラグインの解説

コメントでだいたい理解できると思いますが、ポイントとなる部分について簡単に解説します。

・ControlActorBPLibrary.h(7行目)

FControlActorEventという動的デリゲートを宣言しています。

プラグインからアクタへ、イベントという形で情報を送るためのものです。

・ControlActorBPLibrary.h(16行目)

BindEventという関数を宣言しています。

この関数は、ブループリントから呼び出すことが可能です。

第1引数のobjectには、イベント関数を保有するアクタオブジェクトを渡します。

第2引数のfunc_nameには、イベント関数名を渡します。

・ControlActor.h(7行目)

FTickableGameObjectというクラスを継承しています。

モジュールクラスにティック機能を付加するためのものです。

まとめ

今回(1/2)は、プロジェクトを作成し、アクタやプラグインなど必要なものを追加しました。

また、プラグインのソースコードを編集し、ティック機能やデリゲートを実装しました。

次回(2/2)はこのプラグインとアクタを連携させて、アクタが動くようにします。

参考リンク

デリゲート

FTickableGameObject

カテゴリー・タグ一覧