9
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

C++メインでUE4ぷちコンに参加してみた

Last updated at Posted at 2019-04-03

概要

ぷちコン参加は今回で5回目。これまで最優秀1回、受賞2回。
BPメイン(C++ 1~3割)で作ってました。

今回はほぼC++で作ってます。

C++で開発して良かったこと

  • BPスパゲッティをみなくてすむ
  • 開発後半は、デバッグしやすくコードの差分が見やすいので助かった
  • AnswerHubなどで見つけた解決策がC++でも大丈夫
  • ソースを読めば解決できることも多い

今回やったこと

Visual Studioのプラグインを使ってみた

特にVisual Assist X はオススメです。
ファイル検索だけでよければ、無料のVSFileNavもけっこう使いやすかったです。

  • Visual Assist X
  • Entrian Source Search
  • VsVim

モジュールを分けてみた

ヒストリアさんの記事などを参考にモジュール分割をしてみました。
http://historia.co.jp/archives/3097/

少し手こずりましたがモジュールの仕組みを知ることは、UE4 C++を触るうえで必須だと感じました。
リンクエラーの原因とかもわかるようになります。

ただ、整理のためにモジュールの移動とかしてるとトラブルも起きやすいので、ぷちコンの期間外で試してみたほうがいいです。
そもそもぷちコンの規模の作品では、モジュール分割してもデメリットが多く、あまり必要ないと思います。

Luaを使ってみた

Luaはスクリプト言語なのでC++のビルドを待たずにすぐ結果が反映されます。
ジャンプ力や回転速度、チェインの挙動など細かく調整したいパラメータをLuaで設定できるようにしました。
最初の設定が手間ですが一度仕組みを作ってしまえば、UPROPERTYを追加する+アルファくらいの感覚でパラメータを追加できます。
BPと比べて、

  • テキストなので一覧性が高い
  • 変更履歴が管理できる
  • 計算させた値を返したりできる

など導入するメリットは大きいです。

下のサイトを見て、実装しました。
モジュール分けとか試したあとだと理解しやすいような気がします。
https://wiki.unrealengine.com/Integrating_Lua

後は、下のような関数を用意して呼び出しました。

/** Luaの関数名を指定してfloatを受け取る */
float ULuaImporter::GetFloat(FString Path, FString FuncName)
{
    lua_State* lua = luaL_newstate();
    luaL_openlibs(lua);
    FString root = FPaths::ConvertRelativePathToFull(FPaths::ProjectContentDir());
    root += FString::Printf(TEXT("Script/%s.lua"), *Path);
    luaL_loadfile(lua, TCHAR_TO_UTF8(*root));
    lua_pcall(lua, 0, 0, 0);
    lua_getglobal(lua, TCHAR_TO_UTF8(*FuncName)); // 呼び出す関数
    lua_pcall(lua, 0, 1, 0);
    float ret=0;
    if (lua_isnumber(lua, -1))
    {
        ret = lua_tonumber(lua, -1);
    }
    lua_pop(lua, 1);
    return ret;
}

luaで簡単な値を返す例

function spin_time() return 1.0 end
function spin_time_in_air() return 5.0 end
function jump_force() return 1800 end

function combo_factors(arr)
   for i = 1, #arr do
       arr[i] = (i - 1) * 500 > 2000 and 2000 or (i - 1) * 500
   end
   return arr
end

サブレベルのストリーミング

ひとつひとつのステージはサブレベルで配置しています。
ステージ呼び出し後に読み込んだアクターに対して処理をしたかったので、下のようにして通知を受け取るようにしました。
UUIDを変えないと、複数のレベルを同時に読み込むことができませんでした。

 FName LevelToLoad = FName(*name);
 FLatentActionInfo LatentInfo;
 LatentInfo.CallbackTarget = this;
 LatentInfo.ExecutionFunction = FName("NotifyLevelLoaded");
 LatentInfo.Linkage = 1;
 LatentInfo.UUID = ++UUID;
 UGameplayStatics::LoadStreamLevel(this, LevelToLoad, true, true, LatentInfo);

LoadLevelInstanceで呼んだほうが、読み込んだレベルのアクターを直接取得できて便利だったのですが、読み込みが重かったのでやめました。

 bool b;
 auto streaming = ULevelStreamingDynamic::LoadLevelInstance(GetWorld(), LevelToLoad.ToString(), FVector(0, 0, 0), FRotator(0, 0, 0), b);
 CurrentStreaming = streaming;
 GetWorld()->AddStreamingLevel(CurrentStreaming);
 CurrentStreaming->OnLevelLoaded.AddDynamic(this, &AStageLoader::NotifyLevelLoaded);

デバッグラインのカスタム

円弧のデバッグラインが欲しかったので、ULineBatchComponentを真似して円弧のラインを描けるようにしました。
こういうことが簡単にできるのはC++の利点だと思います。

ぷちコンでC++を使うべきか

C++を使うと開発スピードが落ちるので、短期間の開発でC++メインにするのはリスクが高いです。
簡単なゲームでも完成させたことがない人や、デザイナー・プランナー志望ならBPメインで作ったほうがいいと思います。

C++を使う場合でも、使ったことのないライブラリの検証とかは、ぷちコンの期間内ではやらないほうがいいです。
肝心のゲーム開発が進まなくなります。

BPとC++を使う上で、参考になる資料も上がってますので、最後に紹介しておきます。

BPからC++に移行した話
https://www.slideshare.net/EpicGamesJapan/ue4-bp18

BPメインの事例
https://www.slideshare.net/EpicGamesJapan/ue4-137253034

9
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?