地底電波塔

気が向いたときに勢いにまかせて何かを書き連ねるブログ

自由研究2022(夏)

夏の中盤ごろから急にやる気を出して始まった自由研究がついに終わった。というわけで、私の夏は今日をもって終了です。今日から秋です。よかった、年を越せそうだ。

さて、さっそくだがなにを書けばいいのかわからない。公開さえできてしまえば「完成品はこちらです →URL(ドヤ!)」でなにもかもを終えることができたのだが、残念ながら公開しないことになったから、ここでつらつらとなにか書かないと本当に日の目を見ないブツになってしまった。おお、かわいそうに……

自由研究を始めたときは最後に解説記事をつくるぞというつもりでいたが、冷静に考えて自由研究の解説記事とはなんだ。さすがに Unity のインストールから解説したくないし、書いたコードをすべて解説する気もない。とりあえずそれっぽい見出しを並べてそれっぽくしてみる。

自由研究の概要と感想

動機
  • ノベルゲームをつくってみたい!

  • 自分の脳内から出てきたキャラクターたちがキャッキャとおしゃべりしているのを眺めたい!

期間
  • 8月初旬?~10/17

Unity プロジェクトの作成日が8/28だったから、たぶん8月初旬ごろにはなんかやるぞという気になっていたと思う。

できたもの
  • キャラ立ち絵なし

  • 謎のマップ切り替え機能と探索要素

WHY...

ちなみに一番最初は登場人物4人で舞台は遊園地だったのだが、これは完成する前に絶対に手が止まると確信したので、規模を縮めて登場人物2人で舞台も1部屋だけで済むようにした。おかげで完成(仮)まで漕ぎつけることができた。

使ったもの
  • Unity2021.3.8.f1

始めたときに一番新しい安定版がこれだった。今だと2022があるっぽい。なぜ Unity か? これしか知らなかったから。

なぜ VisualStudio にしなかった? VScode のほうがなじみがあったから。最初にちょっと設定すれば普通に使える。完璧に予測とか補完とかしてほしいなら VisualStudio になるのかもしれないが、別にそこまで求めていなかったので特に不満はなかった。Coroutine を使うときに yield がないぞと叱ってくれるだけで十分だ。

失ったもの
  • 睡眠時間(今日からはたくさん寝るぞ)

  • 黒歴史をつくる機会

  • ゲーム制作への恐怖心

得たもの
  • ノベルゲームどころか2D脱出ゲームくらいならつくれるな、という自信

  • まあそこそこ Unity 触れるな、という自信

  • 意外と2か月近くは続けることができるんだな、という自分への信頼

なぜ公開しないことにした?
  • 「あ、これはもうこれで終わりだ」と急にすとんと来た

  • 一応、遊べなくはない代物にはなっていると思うが、それはそうと公開する気になれなかった。正直昨日くらいまではせっかくここまでつくったのだから出来はどうであれ公開してもいいのでは? と迷っていた。

やってみた感想

実装については、ぶっちゃけ、ひたすら Coroutine とジリジリ仲良くなる日々だった。いかに Coroutine のことを理解し、うまく使いこなすかが終盤のほとんどを占めていた。物の表示非表示とかは SetActive() とか .enabled とかでなんとかなるしな。

当たり前だがやはり公式ドキュメントは最高。公式ドキュメントにすべてが書いてある。それでもうまいこと思いつかないときはブログ記事とか質問サイトとかを探す。この流れで大体なんでも解決する。

さいごに

実はちょっとこれならさくっとつくれるし(本当に?)つくった後に公開してもいいかな(本当に?)という案がひとつ浮かんでいる。マジでしょうもないやつ。つくりてえ。これを冬の自由研究にしてやろうか。いけるかな。年を越せなかったらどうしよう。

家に帰ればPCを開いてなにかしら作業をし、頻繁にやめ時を見失っては睡眠時間を削っていた。なかなか感動的なことだ。正直ちゃんと寝てほしかった。今日はこれさえ終わらせたらとっとと寝てくれという意味を込めて、全体のタスクリストとは別に「今日やることリスト」をつくっていたのだが、なんの役にも立たなかった。タスクが終わっても次のタスクに手を出して延々と作業をしそうになっていた。

しかも、私は毎日元気に出社している社会人だが、通勤で電車に揺られている間はひたすらゲームをどういじるかとか、昨日詰まった箇所はどうやったら実装できそうかとかそんなことをスマホでメモしていた。ざっくり言うと企画・ストーリー作成は通勤中に進め、家ではUnity実装にあてていた。

え? めちゃくちゃやる気に満ち溢れているじゃないか。びっくりした。誰だ、おまえ。

もちろん、さすがに四六時中自由研究にかかりっぱなしになっていたわけではない。ふつうに遊びに出かけるし、やりたくねえなあと思ったときは素直に動画を眺めたりしていた。最近は自由研究というつぶやく対象ができたからか twitter にもよく出入りするようになっていた。おかげで久しぶりにtwitterを眺める日々を得ている。懐かしい。TLのみんな、これからも健やかに元気でな。

おまけ(本題)

ここから先はスクショとなんとなく気に入っているコードの紹介をする。気になるひとはどうぞ。

スクショ祭り

貼り付けていって思ったんですけど私けっこうちゃんと背景描けてるな!? 素直に自画自賛できる。色も落ち着いていて目にやさしくていい。本当にどうして公開しないのでしょうか。公開する気になれなかったからですね。仕方ない。

スタート画面

オープニングその1

オープニングその2

マップその1

マップその2

レシピをクリックしたとき

選択肢

エンディング一覧(未解禁)

エンディング一覧(解禁済)

コード置き場
  • セリフや説明文をパパパパと1文字ずつ出すやつ
// _Consts: キャラ名とかセリフ送りのスピードとか、いろいろなところで共通で使いそうな固定値を置いているクラス
public IEnumerator TypeWriterEffect(string targetText)
{
    _clickedPlayText.isClicked = false;
    mainText.text = "";
    nextIcon.enabled = false;

    // セリフを考えるときにキャラ名をいちいち入れるのがめんどくさくてA、Bで書いていたのをキャラ名に変換する
    string editedText = targetText;
    editedText = editedText.Replace("A", _Consts.nameA);
    editedText = editedText.Replace("B", _Consts.nameB);

    foreach (char c in editedText) 
    {
        if (_clickedPlayText.isClicked) { // 途中でクリックされたらサッと全文表示する
            mainText.text = editedText;
            _clickedPlayText.isClicked = false;
            break;
        }
        mainText.text += c;
        yield return charSpeed;
    }
    nextIcon.enabled = true;
    yield break;
}
  • 上のパパパパと表示するやつはマジで文字を流すだけなので、それをクリック待ちにする
public IEnumerator TypeWriterEffectWaitClick(string targetText)
{
    yield return StartCoroutine(TypeWriterEffect(targetText));
    while(!_clickedPlayText.isClicked) yield return null;
    yield break;
}

参考: unitycoder.com

  • はい・いいえ選択を出す GameObject を使いまわすやつ
// _ConstsTextPanel: 吹き出し関連のやつをまとめたクラス
// _YesBtnText: 「はい」ボタンのテキスト部分
// _NoBtnText: 「いいえ」ボタンのテキスト部分
public IEnumerator AskYesNo(string targetText, string yesTxt, string NoTxt)
{
    yield return StartCoroutine(_ConstsTextPanel.TypeWriterEffect(targetText));
    _ConstsTextPanel.nextIcon.enabled = false;
    _ConstsTextPanel.ToggleClickedCollider(false);
    _ConstsTextPanel._clickedPlayText.isClicked = false;

    _selectYesNoButtons.SetActive(true);
    _YesBtnText.text = yesTxt;
    _NoBtnText.text = NoTxt;
    while(!_EventClickButton.isClicked) yield return null;

    _selectYesNoButtons.SetActive(false);
    _ConstsTextPanel.ToggleClickedCollider(true);
    _EventClickButton.isClicked = false;

    yield break;
}

上の「選択肢」スクショと同じ選択肢オブジェクト

以下、思い出したメモ。

  • 共通で使えそうなものは一通り共通関数用クラスに突っ込んだ。これは大正解だった。おかげで簡単かつ気軽に使いまわせた。

  • GameObject は共通っぽそうなのはとりあえず pfefab にしておいた。正解だった。共通のやつの形とか変えたくなったときに一発で変えられて便利。

  • あと、数はなるべく増やさない。ちょっとスクリプト書いていじれるようなもの(上の AskYesNo() みたいな)ならそれで済ませる。なぜなら増えすぎると私が混乱するから。

  • スクショ右上にあるように、ゲームを途中でやめてスタート画面に戻る機能を入れていたから、Coroutine 再生途中でもスタート画面に戻る可能性があった。ということで、中断するときはCoroutine を使っているクラス全部で StopAllCoroutines(); をやる初期化用関数を用意する脳筋ソリューションをやった。これをやらないと Coroutine 関連の挙動がすべておかしくなるので仕方ない。

  • 公式ドキュメントは最高 でもこれでよくわからないときは解説記事をひたすら漁る ありがとうございます

docs.unity3d.com

では、これにて自由研究2022(夏)を終わりにします。Twitterで見守ってくださったみなさま、ここまで読んでくださったみなさま、ありがとうございました。