unityでuniluaを使ってADV機能を実装する - Qiita
版の記事書きました動機ADVみたいな2Dの寸劇を制御するスクリプトが欲しかったのです。最初は…
unilua版はこちら、もう5年前ですか…言ってることがわかりませんね
僕の実装の基本はコルーチン
IEnumerator CoDrama001()
{
yield return ShowMsg("hello, world!");
yield return ShowMsg("bye");
}
こんな風にガリガリ書いてけば、ADVとして動きそうですよね? 実際こうやって作ったゲームもありました。
しかし、ミニゲームならともかく、そこそこの規模のゲームでハードコードは悪いです。
処理変えるだけでコンパイル発生するし、プログラマ以外触れないし、AssetBundle化できないからモバイルのDLC的なこともできません。
歴史振り返ってみても、ノベルゲーの文章ハードコードするなんて聞いたことないですよね
そうだluaのコルーチン使おう
そこで僕は同じコルーチンでもluaのコルーチンに目をつけました。調べたらuntiyでも動くluaパーサー存在しました。ということはluaで上記のようなコード書けば、コンパイル無し、非プログラマも使える、AssetBundle化容易、と全ての問題解決します。
こういう思想で作ったのが初代uniluaベースのADV機能です。もちろん単純にコルーチン実行するわけでなく、もう少し複雑なことしてます。
XLuaでluaコルーチンをC#から実行してやる
xLua/Assets/XLua/Examples/06_Coroutine at master · Tencent/xLua
xLua is a lua programming solution for C# ( Unity, .Net, Mono) , it supports android, ios, windows, linux, osx, etc. - Tencent/xLua
xluaのコルーチンサンプルは残念な事に、luaからC#コルーチンを扱うものでした。逆は根性で調べました。
luaコルーチンをC#コルーチンに変換
how can i invoke lua coroutine in c# coroutine · Issue #499 · Tencent/xLua
i have some c# function IEnumerator coroutine , if i want invoke lua function which the lua function is coroutine. how can i implement this
libc = CS.DramaInterfaceFromLua;
function a()
libc.ShowMsg(hello, world);
libc.ShowMsg(bye);
end
local util = require 'xlua.util'
function get_co()
return util.cs_generator(a);
end
IEnumlator CoMain(){
LuaEnv luaenv = new LuaEnv();
luaenv.DoString(luascript);
var getCoroutine = luaenv.Global.Get<System.Func<IEnumerator>>("get_co");
var c = getCoroutine();
yield return StartCoroutine(c);
}
こんな感じでしょうか、わかりやすいですね
get_coをコルーチンごとに用意するのはだるいですね。文字列引数でget_co(“a”)みたくできないでしょうか
resumeをassertで囲む
xLua/Assets/XLua/Doc/Faq_EN.md at master · Tencent/xLua
xLua is a lua programming solution for C# ( Unity, .Net, Mono) , it supports android, ios, windows, linux, osx, etc. - Tencent/xLua
luaコルーチンがエラーを出さない時があるらしいので
assert(coroutine.resume(co));
luaコルーチンをresumeする関数をC#で呼ぶ
libc = CS.DramaInterfaceFromLua;
function a()
libc.ShowMsg(hello, world);
libc.ShowMsg(bye);
end
co = coroutine.create(a);
function resume()
coroutine.resume(co);
end
var resume = luaenv.Global.Get<System.Action>("resume");
resume();
このままだと終了判定が取れないので、coroutine.status()をreturnするようにするか、status()を取得する関数を作るのがよいですね
まとめ
xluaでもコルーチンベースのADV機能実装できそうです