PaperSloth’s diary

主にゲーム開発関連についての記事を書きます。

Lumberyard Lua入門

この記事はLumberyard Advent Calendar 2017の5日目の記事です。
Lumberyard Advent Calendar 2017 - Qiita

環境

・Lumberyard 1.11.1.0


概要

LumberyardでのLuaの記述についての記事を書きますが
極力Unity, UE4の例も出して多くの方にイメージが伝わるように書ければと思います。
また、初めてのLuaですので誤りがあれば指摘いただけると幸いです。


新規Entityの作成

Level上で右クリックをして、Create enitityで作成します。
f:id:PaperSloth:20171203184657p:plain

ここで作成されたコンポーネントエンティティシステムは
現在はPreviewで絶賛開発中のようです。
コンポーネントエンティティシステム - Lumberyard

古いシステムのEntity Systemと置き換わるようです。
エンティティシステム - Lumberyard

このEntitySystemは
UnityでいうところのGame Object
UE4でいうところのActorといった感じでしょうか。


Luaの追加

作成したEntityにAdd Componentから
f:id:PaperSloth:20171203185153p:plain

LuaScriptを選択します
f:id:PaperSloth:20171203185306p:plain

Unityのスクリプトの追加に近いイメージなので、Unityユーザーにはイメージしやすいかもしれませんね。

続いて、LuaScriptの”{ }”ボタンを押すとLua Editorが開きます。
f:id:PaperSloth:20171203185512p:plain

f:id:PaperSloth:20171203185543p:plain

とりあえずここで一度Scriptを保存しておきます。
今回はStarterGameのプロジェクトを使用しているので
dev/StarterGame/Scriptsの下にComponentsフォルダを作成し、Sample.luaという名前で保存します。
f:id:PaperSloth:20171203190251p:plain


ここでちょっと特殊なのが、この段階ではこのスクリプト
Entityに関連付いていません。
なので、このLuaScriptを参照するように設定します。
LuaScriptの”...”ボタンを押します。
f:id:PaperSloth:20171203190642p:plain

すると、下図のようなWindowが開くので、先程保存したLuaを指定します。
f:id:PaperSloth:20171203190729p:plain

指定するとそのScript名が表示されます。
f:id:PaperSloth:20171203190823p:plain


初めてのLua「HelloWorld」

とりあえずはHelloWorldから始めましょう。
Luaについては先ずはこのドキュメントから読み始めると良さそうです。
コンポーネントエンティティシステムで使用する Lua スクリプトの作成 - Lumberyard

sample=
{
}

function sample:OnActivate()
    Debug.Log("Hello World")
end

return sample

OnActivateはUnityでいうStart()、UE4でいうBeginPlay()といったところでしょうか。
早速実行してみましょう。

無事にConsoleにHello Worldが出てきました。
f:id:PaperSloth:20171203203930p:plain


変数(プロパティ)の追加

続いてPropertiesテーブルを追加してみます。

sample=
{
    Properties=
    {
        HitPoint =
        {
            default = 100.0,
            min = 0.0,
            max = 500.0,
            description = "Player HitPoint"
        }
    }
}

function sample:OnActivate()
    Debug.Log("Hello World")
end

return sample

Unity C#で書くと

 [SerializeField, Range(0.0f, 500.0f)]
float HitPoint;

UE4の場合は
Blueprintだと
変数でfloatを作成し、Min, MaxのRangeを指定した状態ですね。
Unreal C++だと

UPROPERTY(EditAnywhere,  BlueprintReadWrite, meta=(ClampMin = "0.0", ClampMax = "500.0"))
float HitPoint;

追加したら無事に反映されました。
f:id:PaperSloth:20171203211056p:plain


更新処理と終了処理の追加

ここまででプロパティの追加、初期化が分かりました。
あとは更新と終了処理があれば何か動くものが作れそうです。
UnityだとUpdate()とOnDisable()
UE4だとTick(float DeltaTime)とEndPlay()ですね。

というわけで、更新処理と終了処理を追加しました。

sample=
{
    Properties=
    {
        ActivateLogMessage = "",
        HitPoint =
        {
            default = 100.0,
            min = 0.0,
            max = 500.0,
            description = "Player HitPoint"
        }
    }
}

function sample:OnActivate()
    Debug.Log(self.Properties.ActivateLogMessage)
    self.tickBusHandler = TickBus.CreateHandler(self)
    self.tickBusHandler:Connect()
end

function sample:OnTick(DeltaTime)
    Debug.Log("Call Every frame message")
end

function sample:OnDeactivate()
    Debug.Log("OnDeactivate!")
    self.tickBusHandler:Disconnect()
end

return sample

しれっとOnActivate()でActivateLogMessageという新しいプロパティが使用されていますが
これはPropertiesへのアクセス方法を示したかっただけですので、特別な意味はありません。

先ずは終了処理から見ていきましょう。
構文は下記のような形でOnActivate()が分かれば理解は簡単ですね。

function scriptname:OnDeactivate()
end

問題は更新処理の呼び出し方です。
Lumberyardで更新処理を呼び出すにはシステムのTickBusから通知を受け取る必要があるようです。
そのため、初期化時にはTickBusハンドラーの作成と接続を行い、終了時には切断を行う必要があります。

function sample:OnActivate()
    -- TickBusのハンドラーを作成
    self.tickBusHandler = TickBus.CreateHandler(self)
    -- TickBusとの接続
    self.tickBusHandler:Connect()
end

function sample:OnDeactivate()
    -- TickBusの切断
    self.tickBusHandler:Disconnect()
end

実行してみるとログが正しく出力されていることが確認できました。
f:id:PaperSloth:20171203214925p:plain


今回の入門編は以上になります。
初めてのスクリプト言語でかっても分からないことも多く、苦戦しました。
あとはスクリプト間の通信方法と衝突判定の通知の受け取り方が分かればゲームが作れそうな気はします。

今後も色々とLumberyardの入門記事が出てくるとうれしいです!