【C#】Unity 2Dでできるだけ簡単にアドベンチャーゲーム(ノベルゲーム)を作る その1

だいぶ前に書いた書きかけの記事があったので、追記して更新します。 この記事は、「Unityでアドベンチャーゲーム作りたいけど、どうやったらいいのか分からない」という方のために書かれた、 Unity 2Dで可能な限り最小限のコードのみでアドベンチャーゲームを作る、超入門チュートリアルです。

はじめに

 Unityはゲーム開発のための優れた開発プラットフォームです。それを証明するかのように、ネット上には数多のチュートリアル記事が存在します。 しかし、公式チュートリアル"Roll-A-Ball"がそうであるように、それら記事の多くは、 主にUnity 3Dで作る物理エンジンを用いたアクションゲームに関するものになっています。

 もちろん、そういったゲームを、最小限のプログラミング知識で作れることはUnityの大きなメリットの一つです。 しかし、例えば「脱出ゲーム」のような、テキスト+スクリプトベースで進行するゲームをいざ作ろうと思うと、 チュートリアル記事も少なく、初心者の方は困ってしまうと思われます(むしろ自分がそうでした)。

今回はそういった方のために、Unityでできるだけコードが短くなるようにアドベンチャーゲームを制作する過程を記していきます。 3Dは必要ないので、開発はUnity 2Dで行います。

なお、単純にアドベンチャーゲームを作りたいだけなら、ジョーカースクリプトというUnity向けのプラグインが存在するみたいなので、 そちらを使ったほうが簡単かと思われます。 今回は、あくまでUnityを使いつつC#も勉強したいという方のために書くつもりなので、 最低限クラスとメソッドが分かれば理解できる内容にしていきたいと思っています。

jokerscript.jp

ゲームの設計

開発を始める前に、まず、アドベンチャーゲームを作るために必要な要素を考えます。

  1. 特定の動作を行うことでメッセージウィンドウにテキストが表示され、画面クリックで次のテキストへ進む。
  2. 選択肢が表示され、選んだ選択肢に応じて次のテキストが表示される。
  3. 2.の結果に応じて、ゲーム内で何かしらの処理を行う(フラグを立てるなど)。

最低限これらの要素を満たせれば、ゲームとして成立すると考えられるため、今回はそれを目指します。

プロジェクトの基本設定

プロジェクトの作成

それでは早速作っていきましょう。まずはプロジェクトを作成します。Unity、またはUnity Hubから新規プロジェクトを作成し、 Templateを2Dに設定します。 f:id:Kanchi0914:20190307144348p:plain

メッセージウィンドウの追加

はじめに、メッセージウィンドウを作ります。 hierarchyビューを右クリック、UI→Canvasを追加します。 追加したCanvasをクリックし、inspectorウィンドウのCanvas>Render Modeを Screen Space - Cameraに設定し、下のRender Cameraに HierarchyビューからMain Cameraをドラッグして追加します。 さらに、Plane Distanceを適当に小さな値にし、 加えてCanvas ScalerのUI Scale ModeをScale With Screen Sizeに変更しておきます。

f:id:Kanchi0914:20190307162535p:plain

hierarchyウィンドウに戻り、UI>PanelをCanvasに追加し、 画面の下のほうに適当に配置します。 さらにUI>TextをPanelの子オブジェクトに追加し、これも大きさを適当に揃えます。 ここまでで、Unityの画面は次のようになっていると思います。

f:id:Kanchi0914:20190307151225p:plain

図1

下のProjectウィンドウのAssetsフォルダに、新しくScriptsフォルダを作り、 右クリック>Create>C# scriptからスクリプトを追加、GameControllerに名前を変更します。 Hierarchyウィンドウで右クリック>Create Emptyから新しいGameObjectを追加し、これもGameControllerに名前変更後、 そこに先ほどのスクリプトをアタッチします。 これで、GameControllerオブジェクトにアタッチしたスクリプトを、Unity側が自動で読み込んでくれるようになりました。

画像がないと寂しいので、適当な背景を借りてきて、Asset内にインポート後、Hierarchy内に追加します。 今回はこちらのサイト様からお借りしました。

teddy-plaza.sakura.ne.jp

画面はこんな感じになりました。(若干アス比が変わってるのは気にしないでください)

f:id:Kanchi0914:20190307155422p:plain

では、まずはノベルゲームで最も重要な要素である、文字送りで次のテキストを表示するスクリプトを組んできいましょう。

C#スクリプト(文字送り編)

まず先にコードを書いておきます。 GameController.csの内容を次のように書き換えると、GameControllerオブジェクトのInspectorビューに Scenario Messageという欄が出ると思うので、そこにTextオブジェクトをアタッチします。 シーンを再生して画面をクリックすると、メッセージウィンドウのテキストを順番に切り替えることができます。

f:id:Kanchi0914:20190307165156g:plain

Sample script for adventure games

コード解説

まず、クリックされると次に進む一連の文章をシナリオと呼ぶことにし、 Scenarioクラスにまとめることにします。

    class Scenario
    {
        public string ScenarioID;
        public List<string> Texts;
        public string NextScenarioID;
    }

ScenarioクラスはシナリオのIDと文章を入れるためのListであるTextsを持ちます。 シーンが再生されると、まずUnity側は各GameObjectにアタッチされたスクリプトのStart()を呼び出します。 サンプルコードのStart()内では、Scenarioクラスのインスタンスの生成と初期化をまとめて行ったあと、 メッセージウィンドウのTextオブジェクトに最初の文章をセットします。

    void Start ()
    {
        var scenario01 = new Scenario()
        {
            ScenarioID = "scenario01",
            Texts = new List<string>()
            {
                "テスト文章1",
                "テスト文章2",
                "テスト文章3",
                "テスト文章4",
                "テスト文章5"
            }
        };

        SetScenario(scenario01);
    }

    void SetScenario(Scenario scenario)
    {
        currentScenario = scenario;
        scenarioMessage.text = currentScenario.Texts[0];
    }

Update()関数は、シーンが再生されると毎フレーム呼び出されます。 そこに、マウスのクリックが感知されたとき、 現在のScenarioの次の文章をセットする処理を書きます。

    void Update()
    {
        if (currentScenario != null)
        {
            if (Input.GetMouseButtonDown(0))
            {
                SetNextMessage();
            }
        }
    }

    void SetNextMessage()
    {
        if (currentScenario.Texts.Count > index + 1)
        {
            index++;
            scenarioMessage.text = currentScenario.Texts[index];
        }
        else
        {
            ExitScenario();
        }
    }

現在のScenarioの最後の文章まで到達したとき、続けてどのシナリオの文章を再生するかをチェックします。 今回のコードでは次のシナリオが設定されていませんが、ScenarioクラスのNextScenarioIDに次のScenarioのScenarioIDを セットしておくことで、別のシナリオをそのまま再生することができます。

    void ExitScenario()
    {
        scenarioMessage.text = "";
        index = 0;
        if (string.IsNullOrEmpty(currentScenario.NextScenarioID))
        {
            currentScenario = null;
        }
        else
        {
            var nextScenario = scenarios.Find
                (s => s.ScenarioID == currentScenario.NextScenarioID);
            currentScenario = nextScenario;
        }
    }
}

これで、ゲームの設計で述べた「1. メッセージウィンドウにテキストが表示され、画面クリックで次のテキストへ進む。」 機能を実装できました。 続けて、「2. 選択肢が表示され、選んだ選択肢に応じて次のテキストが表示される」 「3. 2.の結果に応じて、ゲーム内で何かしらの処理を行う」を実装していきましょう。 (追記:続きです) kanchi0914.hatenablog.com

kanchi0914.hatenablog.com