Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Lua文化の伝承!? WFSにおけるイベントスクリプト活用術〜すべてはより良いコンテンツ制作の...

gree_tech
September 18, 2020

Lua文化の伝承!? WFSにおけるイベントスクリプト活用術〜すべてはより良いコンテンツ制作のために〜

GREE Tech Conference 2020 で発表された資料です。
https://techcon.gree.jp/2020/session/Session-7

gree_tech

September 18, 2020
Tweet

More Decks by gree_tech

Other Decks in Technology

Transcript

  1. 西田 綾佑 (Nishida Ryosuke) WFS / Technical Direction @hosi_mo 2014年

    東京大学大学院 情報理工学系研究科修了 株式会社 WFS
  2. Lua

  3. 製作体制 フィールド シナリオ バトル - シナリオ演出 - キャラ劇の演出 - フィールド作成

    (マップエディタ) - フィールドギミック組み込み - フィールドパラメータ調整 - fogや天候調整 - シェーダプログラム調整 - レベルデザイン - バトルギミック設計 レベルデザインから 実装まで行う 演出から 実装まで行う フィールドデザインから 実装まで行う
  4. イベントスクリプト ランタイム(ゲーム) APIリスト ランタイムがLuaに公開してるAPI数 500以上 バトル カメラ制御 フィールドオブジェクト制御 UI アイテム

    サウンド、ムービー ポストエフェクト 移動 フラグ - 約 50 API - 約 30 API - 約 150 API - 約 20 API - 約 10 API - 約 20 API - 約 100 API - 約 30 API - 約 100 API
  5. スクリプトの規模 リリース時(2017年4月) : 63万行 20170531 709077 +72238 20170630 804724 +95647

    20170731 861798 +57074 1年で100万行以上のペース 現在(2020年9月) : 443万行
  6. 25 — イベントシーンアクティベート用フラグ local talk_start = false — エリアに入ると呼ばれる local

    function regist(time) — フィールドの特定オブジェクトにタッチすると Object_setTouchCB( “オブジェクト名”, function () — フラグが上がる talk_start = true end ) end -- trueを返すとイベントシーン起動 local function activate(time, state) if state ~= "update" then return false end return talk_start end キャラクターと会話するためのコード
  7. 26 — イベントシーンアクティベート用フラグ local talk_start = false — エリアに入ると呼ばれる local

    function regist(time) — フィールドの特定オブジェクトにタッチすると Object_setTouchCB( “オブジェクト名”, function () — フラグが上がる talk_start = true end ) end -- trueを返すとイベントシーン起動 local function activate(time, state) if state ~= "update" then return false end return talk_start end キャラクターと会話するためのコード
  8. 27 — イベントシーンアクティベート用フラグ local talk_start = false — エリアに入ると呼ばれる local

    function regist(time) — フィールドの特定オブジェクトにタッチすると Object_setTouchCB( “オブジェクト名”, function () — フラグが上がる talk_start = true end ) end -- trueを返すとイベントシーン起動 local function activate(time, state) if state ~= "update" then return false end return talk_start end キャラクターと会話するためのコード
  9. 28 — イベントシーンアクティベート用フラグ local talk_start = false — エリアに入ると呼ばれる local

    function regist(time) — フィールドの特定オブジェクトにタッチすると Object_setTouchCB( “オブジェクト名”, function () — フラグが上がる talk_start = true end ) end -- trueを返すとイベントシーン起動 local function activate(time, state) if state ~= "update" then return false end return talk_start end キャラクターと会話するためのコード
  10. 29 — イベントシーンアクティベート用フラグ local talk_start = false — エリアに入ると呼ばれる local

    function regist(time) — フィールドの特定オブジェクトにタッチすると Object_setTouchCB( “オブジェクト名”, function () — フラグが上がる talk_start = true end ) end -- trueを返すとイベントシーン起動 local function activate(time, state) if state ~= "update" then return false end return talk_start end キャラクターと会話するためのコード
  11. 30 キャラクターと会話するためのコード — イベントシーン開始されたらseqテーブルを実行 local function update(time) if seq:exec(time) ==

    Enum_SequenceState.FINISH then return true end return false end — seqテーブル定義 local seq = Sequence_create("main", funcTable) — seqテーブル中身 local funcTable = { CustomSeq_faceTo(label_statue_man, CBO_PARTY1), CustomSeq_faceTo(CBO_PARTY1, label_statue_man), Sequence_setDirB(CBO_PARTY1), Sequence_invoke( function() Object_talkWithOptions( label_statue_man, [[なあ見ろよ アルド。この石像の 素晴らしさ! まさに人類の英知と 生命の崇高さに感動するね!]], {talkerDisplayName = "若者"} )
  12. 31 キャラクターと会話するためのコード — イベントシーン開始されたらseqテーブルを実行 local function update(time) if seq:exec(time) ==

    Enum_SequenceState.FINISH then return true end return false end — seqテーブル定義 local seq = Sequence_create("main", funcTable) — seqテーブル中身 local funcTable = { CustomSeq_faceTo(label_statue_man, CBO_PARTY1), CustomSeq_faceTo(CBO_PARTY1, label_statue_man), Sequence_setDirB(CBO_PARTY1), Sequence_invoke( function() Object_talkWithOptions( label_statue_man, [[なあ見ろよ アルド。この石像の 素晴らしさ! まさに人類の英知と 生命の崇高さに感動するね!]], {talkerDisplayName = "若者"} )
  13. 34 血塗られたバルオキー --[[ かくれんボーイ イベント フィーネさらわれている時以外&子供のかくれんぼイベントフラグが1-2の時 、かくれんぼ坊やをアクティベート ]]— if Common_getGlobalFlag(global_flag_baruoki_kakurenboy)

    == 1 or Common_getGlobalFlag(global_flag_baruoki_kakurenboy) == 2 then if Common_isStoryStepComplete(story_step_story_step_ch1_12) == false or Common_isStoryStepComplete(story_step_story_step_ch11_1) then Common_registAreaEvent("kakurenboy", false) end end
  14. 35 血塗られたバルオキー --[[ かくれんボーイ イベント フィーネさらわれている時以外&子供のかくれんぼイベントフラグが1-2の時 、かくれんぼ坊やをアクティベート ]]— if Common_getGlobalFlag(global_flag_baruoki_kakurenboy)

    == 1 or Common_getGlobalFlag(global_flag_baruoki_kakurenboy) == 2 then if Common_isStoryStepComplete(story_step_story_step_ch1_12) == false or Common_isStoryStepComplete(story_step_story_step_ch11_1) then Common_registAreaEvent("kakurenboy", false) end end
  15. 36 血塗られたバルオキー --[[ かくれんボーイ イベント フィーネさらわれている時以外&子供のかくれんぼイベントフラグが1-2の時 、かくれんぼ坊やをアクティベート ]]— if Common_getGlobalFlag(global_flag_baruoki_kakurenboy)

    == 1 or Common_getGlobalFlag(global_flag_baruoki_kakurenboy) == 2 then if Common_isStoryStepComplete(story_step_story_step_ch1_12) == false or Common_isStoryStepComplete(story_step_story_step_ch11_1) then Common_registAreaEvent("kakurenboy", false) end end
  16. 51 朝のシーン local aldo = Adv.character("Aldo", "Default") local fine =

    Adv.character("Fine", "Default") -- ADV開始 Adv.talk(“???”, [[起きて]]) Adv.talk(aldo, [[…ん?]]) Adv.talk(fine, [[起きてってば]]) -- 0.5秒まつ Wait(0.5) local select = Adv.question([[起きる?]], [[はい|いいえ]]) if select == 0 then Adv.talk(aldo, [[おはよう]]) elseif select == 1 then Adv.talk(aldo, [[zzz]]) end Exit()
  17. 52 朝のシーン local aldo = Adv.character("Aldo", "Default") local fine =

    Adv.character("Fine", "Default") -- ADV開始 Adv.talk(“???”, [[起きて]]) Adv.talk(aldo, [[…ん?]]) Adv.talk(fine, [[起きてってば]]) -- 0.5秒まつ Wait(0.5) local select = Adv.question([[起きる?]], [[はい|いいえ]]) if select == 0 then Adv.talk(aldo, [[おはよう]]) elseif select == 1 then Adv.talk(aldo, [[zzz]]) end Exit()
  18. 53 朝のシーン local aldo = Adv.character("Aldo", "Default") local fine =

    Adv.character("Fine", "Default") -- ADV開始 Adv.talk(“???”, [[起きて]]) Adv.talk(aldo, [[…ん?]]) Adv.talk(fine, [[起きてってば]]) -- 0.5秒まつ Wait(0.5) local select = Adv.question([[起きる?]], [[はい|いいえ]]) if select == 0 then Adv.talk(aldo, [[おはよう]]) elseif select == 1 then Adv.talk(aldo, [[zzz]]) end Exit()
  19. 54 朝のシーン local aldo = Adv.character("Aldo", "Default") local fine =

    Adv.character("Fine", "Default") -- ADV開始 Adv.talk(“???”, [[起きて]]) Adv.talk(aldo, [[…ん?]]) Adv.talk(fine, [[起きてってば]]) -- 0.5秒まつ Wait(0.5) local select = Adv.question([[起きる?]], [[はい|いいえ]]) if select == 0 then Adv.talk(aldo, [[おはよう]]) elseif select == 1 then Adv.talk(aldo, [[zzz]]) end Exit()
  20. 55 local aldo = Adv.character("Aldo", "Default") local fine = Adv.character("Fine",

    "Default") -- ADV開始 Adv.talk(“???”, [[起きて]]) Adv.talk(aldo, [[…ん?]]) Adv.talk(fine, [[起きてってば]]) -- 0.5秒まつ Wait(0.5) local select = Adv.question([[起きる?]], [[はい|いいえ]]) if select == 0 then Adv.talk(aldo, [[おはよう]]) elseif select == 1 then Adv.talk(aldo, [[zzz]]) end Exit() 朝のシーン
  21. 56 local aldo = Adv.character("Aldo", "Default") local fine = Adv.character("Fine",

    "Default") -- ADV開始 Adv.talk(“???”, [[起きて]]) Adv.talk(aldo, [[…ん?]]) Adv.talk(fine, [[起きてってば]]) -- 0.5秒まつ Wait(0.5) local select = Adv.question([[起きる?]], [[はい|いいえ]]) if select == 0 then Adv.talk(aldo, [[おはよう]]) elseif select == 1 then Adv.talk(aldo, [[zzz]]) end Exit() 朝のシーン
  22. 57 local aldo = Adv.character("Aldo", "Default") local fine = Adv.character("Fine",

    "Default") -- ADV開始 Adv.talk(“???”, [[起きて]]) Adv.talk(aldo, [[…ん?]]) Adv.talk(fine, [[起きてってば]]) -- 0.5秒まつ Wait(0.5) local select = Adv.question([[起きる?]], [[はい|いいえ]]) if select == 0 then Adv.talk(aldo, [[おはよう]]) elseif select == 1 then Adv.talk(aldo, [[zzz]]) end Exit() 朝のシーン
  23. 58 local aldo = Adv.character("Aldo", "Default") local fine = Adv.character("Fine",

    "Default") -- ADV開始 Adv.talk(“???”, [[起きて]]) Adv.talk(aldo, [[…ん?]]) Adv.talk(fine, [[起きてってば]]) -- 0.5秒まつ Wait(0.5) local select = Adv.question([[起きる?]], [[はい|いいえ]]) if select == 0 then Adv.talk(aldo, [[おはよう]]) elseif select == 1 then Adv.talk(aldo, [[zzz]]) end Exit() 朝のシーン
  24. 63 local aldo = Adv.character("Aldo", "Default") local fine = Adv.character("Fine",

    "Default") -- ADV開始 Adv.talk(“???”, [[起きて]]) Adv.talk(aldo, [[…ん?]]) Adv.talk(fine, [[起きてってば]]) -- 0.5秒まつ Wait(0.5) local select = Adv.question([[起きる?]], [[はい|いいえ]]) if select == 0 then Adv.talk(aldo, [[おはよう]]) elseif select == 1 then Adv.talk(aldo, [[zzz]]) end Exit() 朝のシーン
  25. 64 イベント発火を簡単にする function init() TouchEvent("オブジェクト", Sample2) end function Sample2() --

    タッチ後の処理 Adv.Talk(“にしだ”, [[はーい]]) Wait(0.5) Adv.Talk(“にしだ”, [[0.5秒待ったよ]]) end
  26. 65 イベント発火を簡単にする function init() TouchEvent("オブジェクト", Sample2) end function Sample2() --

    タッチ後の処理 Adv.Talk(“にしだ”, [[はーい]]) Wait(0.5) Adv.Talk(“にしだ”, [[0.5秒待ったよ]]) end
  27. 66 イベント発火を簡単にする function init() TouchEvent("オブジェクト", Sample2) end function Sample2() --

    タッチ後の処理 Adv.Talk(“にしだ”, [[はーい]]) Wait(0.5) Adv.Talk(“にしだ”, [[0.5秒待ったよ]]) end
  28. 71 local aldo = Adv.character("Aldo", "Default") local fine = Adv.character("Fine",

    "Default") -- ADV開始 Adv.talk(“???”, [[起きて]]) Adv.talk(aldo, [[…ん?]]) Adv.talk(fine, [[起きてってば]]) -- 0.5秒まつ Wait(0.5) local select = Adv.question([[起きる?]], [[はい|いいえ]]) if select == 0 then Adv.talk(aldo, [[おはよう]]) elseif select == 1 then Adv.talk(aldo, [[zzz]]) end Exit() 朝のシーン
  29. 72 local aldo = Adv.character("Aldo", "Default") local fine = Adv.character("Fine",

    "Default") -- ADV開始 Adv.talk(“???”, [[起きて]]) Adv.talk(aldo, [[…ん?]]) Adv.talk(fine, [[起きてってば]]) -- 0.5秒まつ Wait(0.5) local select = Adv.question([[起きる?]], [[はい|いいえ]]) if select == 0 then Adv.talk(aldo, [[おはよう]]) elseif select == 1 then Adv.talk(aldo, [[zzz]]) end Exit() 朝のシーン
  30. 73 local aldo = Adv.character("Aldo", "Default") local fine = Adv.character("Fine",

    "Default") -- ADV開始 Adv.talk(“???”, [[起きて]]) Adv.talk(aldo, [[…ん?]]) Adv.talk(fine, [[起きてってば]]) -- 0.5秒まつ Wait(0.5) local select = Adv.question([[起きる?]], [[はい]]) Adv.talk(aldo, [[おはよう]]) Exit() 朝のシーン
  31. 74 local aldo = Adv.character("Aldo", "Default") local fine = Adv.character("Fine",

    "Default") -- ADV開始 Adv.talk(“???”, [[起きて]]) Adv.talk(aldo, [[…ん?]]) Adv.talk(fine, [[起きてってば]]) -- 0.5秒まつ Wait(0.5) DebugPoint() local select = Adv.question([[起きる?]], [[はい]]) Adv.talk(aldo, [[おはよう]]) Exit() 朝のシーン
  32. 75 local aldo = Adv.character("Aldo", "Default") local fine = Adv.character("Fine",

    "Default") -- ADV開始 Adv.talk(“???”, [[起きて]]) Adv.talk(aldo, [[…ん?]]) Adv.talk(fine, [[起きてってば]]) -- 0.5秒まつ Wait(0.5) DebugPoint() local select = Adv.question([[起きる?]], [[はい]]) Adv.talk(aldo, [[おはよう]]) Exit() 朝のシーン
  33. 76 local aldo = Adv.character("Aldo", "Default") local fine = Adv.character("Fine",

    "Default") -- ADV開始 Adv.talk(“???”, [[起きて]]) Adv.talk(aldo, [[…ん?]]) Adv.talk(fine, [[起きてってば]]) -- 0.5秒まつ Wait(0.5) DebugPoint() local select = Adv.question([[起きる?]], [[はい]]) Adv.talk(aldo, [[おはよう]]) Exit() 朝のシーン
  34. ゲームエンジンとコンテンツ ゲームエンジン Advパート ギミック 消滅都市 Cocos2d-x Excel なし アナザーエデン Cocos2d-x

    Lua Lua ほか運営中タイトル Cocos2d-x Excel Luaほか • ほかタイトル群は権利の都合上表示しておりません
  35. x

  36. イベントスクリプト ランタイム(ゲームシステム) • アドベンチャーパート • 立ち絵 • UI • サウンド

    • フィールド • カメラ制御 • オブジェクト制御 • ポストエフェクト • バトル • タイムライン連携 • 会話演出 • メインストーリー • Scene制御 • ほか <- 大量のAPI -> <- 大量のAPI -> <- 大量のAPI -> <- 大量のAPI -> <- 大量のAPI -> <- 大量のAPI -> <- 大量のAPI -> <- 大量のAPI -> <- 大量のAPI -> <- 大量のAPI -> <- 大量のAPI -> <- 大量のAPI -> <- 大量のAPI -> <- 大量のAPI -> <- 大量のAPI -> <- 大量のAPI -> <- 大量のAPI -> <- 大量のAPI ->
  37. Lua