絵描きの不定期Unity制作日記❿
「クリエイターズ文化祭に参加した」の巻
2022年10月22日、23日の二日間にかけて再際されていた「クリエイターズ文化祭」に参加してきました!
当日配布したゲーム!
なんともアホなことに、開催10日前に新しくゲームを組み始める(メニュー部分やテキスト処理/BGM処理などは以前から制作していたものの流用)という地獄のような発想をしてしまい、当日までかなりの修羅模様でした
シナリオに1日、キャラデザインに半日、それ以降はずっとシステム組みとセーブ機能の修正・・・アニメーションの制作、当日の昼にBGM制作など
「なんで10日前にこんなこと始めちゃったんですか・・・?」と当日ギリギリまで平均睡眠2時間半の毎日を過ごし泣き言を言っている始末でした
そして、今回のUnity日記なのですが、私がやっている「ノベルゲームのどこでもセーブ方法の考え方」について書いてみたいと思います
本当はもっと早く記事にしたかったのですが、いかんせん他人が遊べる形で「どこでもセーブができるUnityのゲーム」を出したのは今回が初めてだったので、一応出せてから記事にしようかなと考えていたのです
その1:できれば「宴」アセットを買え
「私がやっている方法を説明します」とは書いたものの、ノベルゲームをわざわざUnityで作りたいのであれば「宴」という有料のアセットを買うことを推奨しておきます
つか可能ならティラノで作れ
なぜならば、楽だからです
「どんなゲームにも対応する雛型」なので当たり前ですがゲーム制作がスムーズになります
ただもちろん、有料のアセットなのでお金がかかります
今調べたら約1万円くらいだそう!
たまにセールとかやってると5000円くらいになったりもするそうですが、私は持っていないので正直詳しくありません・・・
「宴」を使用するにはエクセルが必要なのですが、私のパソコンには入っていないため買いませんでした
あとティラノはフェスとかノベルゲーム専用の投稿サイトがあり活気も凄いため、作ったノベルゲームをたくさんの人に遊んで欲しいのなら、ティラノで制作した方が絶っっっっっっっっっっ対に良いです
しかもソフト自体が無料ですよ、奥さん
その2:「どこでもセーブ」の考え方
前置きはそのくらいにしておいて
「エクセルを持っていないから宴を買わなかった」と言ったのですが、この”エクセル”が私のセーブに対する考え方の鍵になっています
セーブ機能について方法を調べまわっているうち、宴の公式サイトに「どこでもセーブはアプデ時にバグになりかねないのでできれば非推奨です」という文面があったのを見たことがありました
それを読んで私は、「エクセルを使用して文章を管理してアプデでバグになるということは、「エクセルの表番号」を読み取ってその番号を保存し、そこから逆輸入してセーブされた文章を再生しているということなのではないか?」と思い至ったのです(※「絵描きの不定期Unity制作日記❼」にて)
要は、「文章に数字を割り振っておいて、その数字をセーブする」というやり方です
・・・これにはメリットとデメリットがあります
◎メリット❶:お金がかからない◎
セーブの読み込みやそもそものゲームシステムに関する部分を0から自分で組むことになるので当たり前ですがお金がかかりません
私はこちらのサイト様からセーブアセットをお借りしてセーブ自体を行っています
ありがたいことに無料で公開されているアセットで、使い勝手も抜群に素晴らしいです
これ以前にはJsonを生成してセーブする方法を組んでいたのですが、jsonセーブはUnityroomで動かないようなのでそれ以降こちらをお借りするようになりました
ノベルゲームの基礎部分に関してはこちらの記事を元にアレンジしています
※文字送りと同時にSEを鳴らしたり、変数自体を文章から変動させたりなどは記事外で自分で考えて組む必要があります
◎メリット❷:自由度は高い◎
当たり前ですが、自分で全て設定するため自分のゲーム専用に作ることができます
私は宴を持っていないので詳細は分かりませんが、「誰でも簡単に作れる」ということは「基礎が固定されている」ということと同義です
なのでアセットを買う以上に自分好みにできますし多少めんどくさいシステムを追加しても融通が利きます
こだわりが強い方にはお勧めです
なにより「自分でやれた!」という愉悦感はプライスレス
ぜひこちら側へ
◆デメリット❶:めんどくさい◆
文章の頭に数字を付けていくわけなのですが、元の宴のセーブと同じように文章が増えたりするとセーブをしている文章がズレてしまいます
ただ文章が1つズレるだけで済めばよいですが、そこが最終文章で、その文章の数字自体を消してしまうアプデだった場合、読み込む数字が見当たらず進行不能バグになるわけです
組んでる時にうっかり書き込む番号がズレてしまう可能性も高いので、軽微なバグの温床にもなってしまいます
◆デメリット❷:めんどくさい◆
文章を打ち込むという面倒臭さだけでなく、ロードをするシステムを組むのも大変に面倒くさいです
基本的に「文章についている数字をセーブしておいて、ロードした時その数字と同じ文章までの道のりをテキストとして表示させずに全部飛ばす」という処理なのですが
「ロード処理をしている間」はプレイヤーの操作や文章が止まる機能、SEが鳴る機能、選択肢機能なんかを全停止しておかなくてはならないのでそこら辺の管理が非常に大変でやっぱりバグの温床になります
if文やswitch文を追加しなくてはならならず、「変数の管理に細心の注意を払う」必要があるのです
総括すると「テストプレイ」に対する根気が必要です
何度も色々な条件でセーブとロードを繰り返し、バグが出ないかを確認する作業が非常に大切になります
逆に言えば根気さえあればなんとかなります
基本的に私がセーブしているのは以下の項目です
・章(int変数) //読み込む章を分岐させるのに使用
・文章の数字(int変数) //読み込む文章を分岐させる
・プレイヤーの名前(string変数) //必要ならセーブしておく
・背景画像(int変数) //画像に数字を割り振ってます
・立ち絵(int変数) //立ち絵にも同様
・流れているBGM(int変数) //BGMも同様
画像や立ち絵には数字を割り振っています
例えば
章を保存しているのは、章で文章を格納する変数を一度リセットしているためです
つまり章の始まりごとに、文章の先頭に付けられている数字が1になります
基本的に文章の先頭に付ける数字は管理が楽なように100以下になるように心がけています
public static int Syou = 0; //章を格納する疑似グローバル変数(別のC#スクリプトで共有可)
public static int t_num = 0; //テキストの頭についている数字を格納する
text1 = "&1「井戸端「私は井戸端です」"+"&2「井戸端「仲良くしてください」";
text2 = "&1「井戸端「私はUnity初心者です」"+"&2「井戸端「もっと頑張りたいです」"+
"&!select_text=\"NEXT1\"=\"頑張れ\"" +
"!select_text=\"NEXT2\"=\"今日のご飯なに?\"" + //選択肢を表示
"#NEXT1" + "&3「井戸端「ありがとう!」"; //選択肢1を選んだ場合
"#NEXT2" + "&4「井戸端「オムライスだよ!」"+ "&5「井戸端「楽しみにしててね!」";//選択肢2を選んだ場合
text3 = "&1「井戸端「書くことが無くなってきました」"+"&2「井戸端「(*´ω`*)」";
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private void Load_Syori()
{
switch(Syou){
case 1: MainText = text1;_pageQueue = _subScenes.First().Value;break; //章が1だった時はtext1を最初から読み込む
case 2:MainText = text2; //章が2だった時はtext2というものが読み込まれる
if(t_num <=2){_pageQueue = _subScenes.First().Value;} //文章の数字が1,2だった場合は最初から
else if(t_num == 3){la = "NEXT1"; JumpTo('"' + la + '"'); }//文章の数字が3だった場合はラベルジャンプを使用
else if(t_num ==4 || t_num ==5){la = "NEXT2"; JumpTo('"' + la + '"'); }//文章の数字が4、5だった場合はラベルジャンプを使用
break;
case 3:MainText = text3;_pageQueue = _subScenes.First().Value;break; //章が3だった時はtext3を最初から読み込む
default: MainText =$"今は{Syou}です";break; //それ以外の時 デバッグとかバグ回避に使えるので一応書いておく
}
}
これだけ書かれても・・・という感じだとは思うのですが、文章自体はロード時にこんな雰囲気で分岐させます
そしてその後は文章読み込み&表示の方の関数で『保存された数字と文章頭の数字が同じになるまではテキスト内にあるものは全て吹っ飛ばす』という処理を付け加えています
選択肢はラベルジャンプを使用して行われている仕様なので読み込みの際にも活用しています
文章頭の数字はsplitを使用して文章の"「"がある場所で区切りを検知させ吸い出す感じ
元の内容では"「"で「キャラの名前」と「喋っている内容」を分けるということをやっていたようなので、どうせなら応用してしまえ!ということでこうなりました
キャラの名前が無いときはネームウィンドウを消すという処理が可能ということは、キャラの名前によってSEを変更したり、あるいは"「"を増やして区切りを増やせば、自由に条件分岐も増やせるってことなんですね!
今更ですが、この日記は「どこでもセーブの考え方」について書く記事なので細かいスクリプトは割愛します
そもそも自分用の日記だしね
基本的にUnityを通してやりたいシステムを実現するための思考忘備録って感じ
数字を付けて検知する部分以外は、先ほど記述したみににさんの「ノベルゲームの雛型」のnote記事で紹介されている内容なのでぜひそちらを見てみてください
そちらの記事内でもセーブの仕組みを解説しているのですが、 PlayerPrefsを使用してのセーブ機能であったため私は実装しませんでした
※PlayerPrefsでのセーブが良くない理由については「絵描きの不定期Unity制作日記 ❺」で触れています