Slide 1

Slide 1 text

━━━━━━━━━━━━━━━━━ 宴はいいぞ いも(@adarapata) ━━━━━━━━━━━━━━━━━ 2020/07/31 yokohama.unity #4 1

Slide 2

Slide 2 text

⾃⼰紹介 いも (@adarapata) adarapata.com 仕事でUnity触ってるエンジニア テスト、DIとかよく話すおじさん 最近Godot Engineがアツい 2020/07/31 yokohama.unity #4 2

Slide 3

Slide 3 text

宴とは 「ビジュアルノベルをかんたん作成」できる有償アセット 会話テキストの表⽰ キャラ⽴ち絵の設定、表情変更 ⼀枚絵、パーティクルによる演出強化 選択肢による分岐、パラメータ機能 ログ機能 Excelによるシナリオ管理、およびデータ設定 etc... 2020/07/31 yokohama.unity #4 3

Slide 4

Slide 4 text

公式が最強 https://madnesslabo.net/utage/ 2020/07/31 yokohama.unity #4 4

Slide 5

Slide 5 text

今⽇話すこと 宴を⾃分のゲームに組み込むときのお話 スクリプトでの実⾏⽅法 アプリケーション -> 宴の連携 宴 -> アプリケーションへの連携 アセット管理の連携 サウンド周りのカスタマイズ 時間⾜りなかった 対象者 ⾃作ゲームの会話パート周り作るのが⾯倒だなと思っている⼈ 2020/07/31 yokohama.unity #4 5

Slide 6

Slide 6 text

組み込みの話 宴は単体でノベルゲームを作成できるが、⾃分のアプリケーションと 組み合わせて使うこともできる。 https://madnesslabo.net/utage/?page_id=402 ゲーム内の会話シーンとして宴を使う チュートリアル部分だけ使う これを⾏うためにはいくつかスクリプトを書いて、連携処理を⾏う必 要がある。 2020/07/31 yokohama.unity #4 6

Slide 7

Slide 7 text

宴で主に登場するScriptableObject 宴に使うシナリオやリソースの定義は全てExcelファイルで⾏う。 Excelファイルが更新されるとImporterが⾛り、ScriptableObjectが⽣ 成or更新される Project: 宴のプロジェクトファイル全体の設定情報を持つ 最上位のファイルなのでExcelから⽣成はされない Scenarios: Chapterファイルの情報を1:Nで持つ Chapter: 「章」に相当する。Bookを1:Nで持つ Book: Excelファイルをパースしたもの。xlsと1:1の関係 Excelファイルは任意の粒度で分割できる 2020/07/31 yokohama.unity #4 7

Slide 8

Slide 8 text

AdvEngineの起動 スクリプトからの最低限の⼿順は以下の感じ _advEngine = FindObjectOfType(); // 初期化 _advEngine.BootFromExportData(scenarioData, "directory/path"); // シナリオ呼び出し _advEngine.JumpScenario("scenario_name"); // シナリオを読み終えるまで待つ yield return new WaitUntil(_ => _advEngine.IsEndOrPauseScenario); Scenarios.assetをどこかから取ってくればOK 2020/07/31 yokohama.unity #4 8

Slide 9

Slide 9 text

アプリケーション -> 宴 宴はシナリオ内部でパラメータを定義できる パラメータはシナリオ内で計算したり、タグを使って表⽰することも できる 2020/07/31 yokohama.unity #4 9

Slide 10

Slide 10 text

このパラメータはスクリプト側からget,setできる advEngine.Param.TrySetParameter("名前", "imo"); advEngine.JumpScenario("test"); プレイヤーの名前とか、レベルとかゲーム側の状況を渡して遊べる 2020/07/31 yokohama.unity #4 10

Slide 11

Slide 11 text

宴 -> アプリケーション シナリオで打ち込めるコマンドは基本的には宴にしか影響を与えない が、アプリケーション側に影響を与えるようなコマンドを⾃分で作る こともできる GameOver というコマンドはデフォルトでは存在しないが、スクリプト 側でこのコマンドをパースして独⾃の処理を⾏える。 これをカスタムコマンドと呼ぶ。 2020/07/31 yokohama.unity #4 11

Slide 12

Slide 12 text

カスタムコマンドクラスは AdvCommand を継承させる public class GameOverCommand : AdvCommand { public GameOverCommand(StringGridRow row) : base(row) { } public override void DoCommand(AdvEngine engine) { // ゲームオーバーにさせる何某 } } コンストラクタはシナリオ読み込みタイミングで呼び出され、実際の コマンド実⾏時に DoCommand が呼ばれる 2020/07/31 yokohama.unity #4 12

Slide 13

Slide 13 text

パース処理を担う AdvCommandParser にコールバックがある public class CustomCommandManager : MonoBehaviour { private void Awake() { Utage.AdvCommandParser.OnCreateCustomCommandFromID += OnCreateCustomCommand; } private void OnCreateCustomCommand( string id, StringGridRow row, AdvSettingDataManager datamanager, ref AdvCommand command) { switch (id) { case "GameOver": command = new GameOverCommand(row); break; } } } コマンド名(ID)が取得できるので、⽣成処理を書いていく。 2020/07/31 yokohama.unity #4 13

Slide 14

Slide 14 text

リソース管理 基本的には3種類 ビルドに含めて Resources.Load (ローカル) 宴側が⽤意しているAssetBundleManagerでロードする Manifestファイル or ⾃前でリスト登録 ⾃作のファイルマネージャーを組み合わせる 宴だけで完結するなら宴側のAssetBundleManager使うと楽。 いい感じのリソースコンバーターも⽤意している。 今回は⾃作のファイルマネージャーを組み合わせる話 2020/07/31 yokohama.unity #4 14

Slide 15

Slide 15 text

Asset管理周りの登場⼈物 覚えておくべきはこの⼆つ AssetFileBase AssetFileManager 2020/07/31 yokohama.unity #4 15

Slide 16

Slide 16 text

AssetFileBase ファイル名、種類などアセットの情報を持つ基底クラス アセットをどのようにロードするかを知っている。 具体的には LoadAsync を実装させる 1アセットごとに作られるクラス シートに10個の画像を定義したのなら10個のAssetFileBase デフォルトではこれを継承した AssetFileUtage のインスタンスが 作られる 2020/07/31 yokohama.unity #4 16

Slide 17

Slide 17 text

AssetFileManager AssetFileBase を管理するクラス 宴の初期化時にシナリオデータから⾃動でアセットのインスタンス を追加してくれる 基本的にはクラスそのものを叩く必要はない AssetFileBase インスタンスを作る処理をフックできる AssetFileManager.GetCustomLoadManager().OnFindAsset += MyFindAsset CustomLoadManagerに噛ませることができる 2020/07/31 yokohama.unity #4 17

Slide 18

Slide 18 text

噛ませる public class MyFileManager : MonoBehaviour { void Awake() { // 宴のアセット検索時に⾃前のコールバックを噛ませる AssetFileManager.GetCustomLoadManager().OnFindAsset += FindAsset; } void FindAsset(AssetFileManager mangager, AssetFileInfo fileInfo, IAssetFileSettingData settingData, ref AssetFileBase asset) { switch (fileInfo.FileType) { case AssetFileType.Texture: asset = new MyTexture2DFile(mangager, fileInfo, settingData); } } } 2020/07/31 yokohama.unity #4 18

Slide 19

Slide 19 text

⾃前の AssetFileBase を継承したクラスを作る public class MyTexture2DFile : AssetFileBase { public override IEnumerator LoadAsync(System.Action onComplete, System.Action onFailed) { // ⾃前のManagerからアセットを取ってくる何某 yield return InitFromAbManager(); IsLoadEnd = true; onComplete(); } public override bool CheckCacheOrLocal() { return false; } public override void Unload() => IsLoadEnd = false; IEnumerator InitFromAbManager() { // ⾃前のManagerから取ってきて渡す Texture = MyAssetBundleManager.LoadAssetBundle(FileInfo.FileName); } } 2020/07/31 yokohama.unity #4 19

Slide 20

Slide 20 text

AssetFileBaseのプロパティ Text : テキストアセット Texture : 画像リソース系(キャラクター・背景etc) Sound : ⾳声リソース(Unity Audio限定) UnityObject : その他シナリオファイルとかパーティクル、3Dモデ ル etc.. 最終的に FileType と⼀致するプロパティにデータが⼊っていれば問題 なく動く・・と思う (FileType == AssetFileType.Texture) なら Texture プロパティがnull でないことを期待している 2020/07/31 yokohama.unity #4 20

Slide 21

Slide 21 text

そのほか組み込みのいいところ 宴のコードが基本的に拡張前提に作られている コールバックでのフックを⽤意している箇所が多い 継承できるような設計になっている コード⾒れるし最悪システムの差し替えやれないことはない 情報が多い 公式のフォーラムが活発、困ったら⼤体誰かが踏んでる ⾮エンジニアに対しての敷居が低い Excelという馴染みのある武器、構⽂エラーが丁寧に出る コンテンツを作り始めてからが本番だから・・ 2020/07/31 yokohama.unity #4 21

Slide 22

Slide 22 text

まとめ 宴は組み込みができるぞ スクリプトからの実⾏は簡単だよ 宴 <-> アプリケーションの相互連携もできるよ リソース管理を⾃前のManagerと連携もできるよ 宴はいいぞ 2020/07/31 yokohama.unity #4 22