俺、ゲームクリエイターになる!
というわけで、プログラミングの知識はそこそこあるもののゲーム開発に関してはまったくの初心者である私が、Unityを使ってクソゲーを量産していく様子をお届けしたいと思っております。
Game A Week、やっていきます。私はこのブログを書きながらなので、2週間に1本くらいになっちゃうと思います(早くも言い訳)。
で、最初のゲームはとにかくシンプルに紙芝居。紙芝居を作ります。オシャレにいうとノベルゲームです。
プロジェクトの作成
Unity Hubを起動して「新しいプロジェクト」ボタンを押します。
テンプレートは「2D(Built-In Render Pipeline)」を選択します。プロジェクト名を決めて、「プロジェクトを作成」ボタンを押します。

プロジェクトの作成には結構時間がかかります。そして、莫大なディスク容量を消費します。私の環境では1.44GBでした。どんなクソゲーでも最低これだけ消費します。
最初にやること
プロジェクトの作成ができたら、まずシーン(Scene)の名前を変更しましょう。デフォルトで「SampleScene」という名前のシーンがあります。「プロジェクト」タブの「Assets > Scenes > SampleScene」を右クリックして「名前を変更」を選択します。「SampleScene」を長押しでもいけます。

私は「MainScene」という名前にしました。何でもいいんです。なんなら「SampleScene」のままでもOKです。
次に、ゲーム画面のアスペクト比を設定します。
「ゲーム」タブの上部。「Free Aspect」となっているところを「16:9 Aspect」に変更します。

アスペクト比を固定することによって、画面上にオブジェクトを配置しやすくなります。Free Aspectのほうがかっこいいんだけど、私、初心者なので。
画像のインポート
紙芝居の素材となる画像をAssetsフォルダにインポートします。
「プロジェクト」タブの「Assets」フォルダ上で右クリックして「作成 > フォルダ」を選択します。このフォルダに「Images」と名前を付けます。

「Images」フォルダに紙芝居の素材画像をドラッグ&ドロップします。

私は、0.png〜4.pngの5枚の画像を用意しました。これは#0〜#5の番号が書いてあるだけの仮の画像です。ここでは正式な画像を使いません。なぜならば、このプロジェクトは途中で頓挫するかもしれないからです(記事になっているということは頓挫しなかったということなのでご安心ください)。
先に素材をしっかりと作り上げておいて、それからゲームの開発の取り掛かった場合、開発に失敗したときのダメージは計り知れません。というわけで、てきとーに作った仮の素材を使います。あとで正式なものに差し替えます。
ちなみに、画像のサイズは 1280 * 720 ピクセルにしました。アスペクト比 16:9 です。あと画像のピクセル数は4の倍数がいいそうです。圧縮効率がよくなります。
キャンバスの作成
「ヒエラルキー」タブ上で右クリックして「UI > キャンバス」を選択します。

「MainScene」の下に「Canvas」オブジェクトと「EventSystem」オブジェクトが作成されます。

「Canvas」とは、UIを配置するための領域です。「Canvas」を作成せずにUIを作成しようとしても、自動的に「Canvas」が作成されます。
「EventSystem」は、ユーザからの入力を受け取りUIにイベントを送信するためのものです。
画像オブジェクトの作成
「ヒエラルキー」タブの「Canvas」上で右クリックをして「UI > 画像」を選択します。

「Canvas」の配下に「Image」オブジェクトが作成されるので、名前を「DisplayImage」に変更します。
「DisplayImage」を選択して、「インスペクター」タブを見ます。「Image」コンポーネントの「ソース画像」に1枚目の画像を設定します。先ほどAssetsフォルダにインポートした「0.png」ですね。拡張子が表示されないので「0」になってます。

このとき「ゲーム」タブを見ると次のようになっています。

真ん中にある正方形が、今読み込んだ画像です。これをゲーム画面いっぱいに広げたいので、「DisplayImage」オブジェクトのサイズと位置を調整します。
「インスペクター」タブの「Rect Transform」コンポーネントで次のように設定します。

- アンカープリセットを縦横ともに stretch にする。
- 左右上下の値をすべて0にする。
- 位置Zは2Dでは使わない(たぶん)。
これで画像がゲーム画面いっぱいに広がりました。いえい。
パネルオブジェクトの作成
テキストを表示するためのウインドウを作成します。
「ヒエラルキー」タブの「Canvas」上で右クリックをして「UI > パネル」を選択します。

「Canvas」の配下に「Panel」オブジェクトが作成されるので、名前を「DisplayWindow」に変更します。
「DisplayWindow」のインスペクターでオブジェクトのサイズと位置を設定します。

- アンカープリセットの縦を bottom 、横を stretch にする。
- 左右、位置Yの値を0、高さを120にする。
これで、画面下に高さ120のウインドウができました。
次にウインドウの色を設定します。初期値は白の半透明になってます。このままでもいいのですが、黒の半透明にしたいです。インスペクターの「Image」コンポーネントに「色」の項目があるので、次のように設定します。

- R, G, B の値を 0 にする(黒)。
- A の値を 180 にする(透明度)。
「ゲーム」タブまたは「シーン」タブを見るとウインドウの色が変わっているのがわかりますね。いえい。

テキストオブジェクトの作成
「ヒエラルキー」タブの「DisplayWindow」上で右クリックをして「UI > テキスト – TextMeshPro」を選択します。

以下のウインドウが表示されたら、「Import TMP Essentials」「Import TMP Examples & Extras」ボタンを順にクリックしましょう。

TMP Essentials
初めてTextMesh Proにアクセスするようなので、TextMesh Proを使うために必要なリソースをプロジェクトに追加する必要があります。これらの新しいリソースは、プロジェクトのルートにある「TextMesh Pro」フォルダに配置されます。
TMP Samples & Extras
サンプル&エクストラパッケージには、TextMesh Proのパワフルな機能をより簡単に発見し、学ぶための追加リソースとサンプルが含まれています。これらの追加リソースは、TMP必須リソースと同じフォルダに配置されます。
さて、「DisplayWindow」の上で右クリックしたので、「DisplayWindow」の配下に「Text (TMP)」オブジェクトが作成されました。名前を「DisplayText」に変更します。
「DisplayText」のサイズと位置を設定します。

- アンカープリセットを縦横ともに stretch にする。
- 左右の値を120にする。
- 上下の値を10にする。
テキストオブジェクトには初期値として「New Text」という文字列が表示されています。これを日本語にしてみましょう。インスペクターの「Text Input」に何か入力してみます。

無事、豆腐文字が表示されました。日本語フォントをインポートしないとダメっぽいです。というわけで、日本語フォントを用意しましょう。定番は Google Fonts ですね。
フォントを用意したら、「プロジェクト」タブで「Assets」フォルダの下に「Fonts」フォルダを作成します。そして、「Fonts」フォルダにフォントファイルをドラッグ&ドロップします。

もうひと仕事あります。メニューの「ウィンドウ > TextMeshPro > フォントアセットクリエーター」を選択します。

「Font Asset Creator」ウインドウが開くので、次のように設定します。

「Custom Character List」には使用するすべての文字を羅列する必要があります。以下のページで、文字のリストがまとめられています。ありがたく使わせていただきましょう。
設定したら、「Generate Font Atlas」ボタンをクリックします。少し待つと右側の空き地に何やら表示されます。これが Font Atlas というヤツなのでしょう。「Save」ボタンを押してこれを保存します。
「DisplayText」オブジェクトのインスペクターで「Font Asset」を日本語フォントに設定します。

これで日本語が表示されるようになりました。ついでにフォントサイズも変更しました。1画面で3行表示するには、24くらいが良さそうです。

ボタンオブジェクトの作成
「ヒエラルキー」タブの「Canvas」上で右クリックして「UI > ボタン – TextMesh Pro」を選択します。同じものを2つ作ります。それぞれ「BackButton」と「NextButton」に名前を変更します。

ボタンオブジェクトの横の
クリックして展開すると「Text (TMP)」オブジェクトが入っています。ここにボタンに表示するテキストを入れます。インスペクターで「もどる」「つぎへ」というテキストを設定します。これだけだと文字化けしてしまうので「Font Asset」に日本語フォントを設定します。「Auto Size」にチェックを入れると、ボタンの大きさに合うフォントサイズに自動調整してくれるっぽいです。

「もどるボタン」のサイズと位置を設定します。
「ヒエラルキー」タブで「BackButton」を選択してインスペクターで次のように設定します。

- 基準点の設定: ピボットの X と Y を 0 にする。
- サイズの設定: 幅を 80、高さを 30 にする。
- 位置の設定: アンカープリセットの縦を bottom 、横を left にする。位置 X と Y を 20 にする。
ピボットとは、オブジェクトの基準点のことです。
ここでは、ボタンを画面の左端から20、下端から20のところに配置しようとしています。このとき、ボタン側の基準点がボタンの左下だと配置しやすいですね。

同じように「つぎへボタン」のサイズと位置を設定します。

- 基準点の設定: ピボットの X を 1 に Y を 0 にする。
- サイズの設定: 幅を 80、高さを 30 にする。
- 位置の設定: アンカープリセットの縦を bottom 、横を right にする。位置 X を -20 に Y を 20 にする。
以上で UI の配置が完了しました。こんな感じです。

スクリプトの作成
いよいよスクリプトを書いていきます。
まず、「Assets」フォルダの下に「Scripts」フォルダを作成。「Scripts」フォルダの下に「C# スクリプト」を作成します。そして、スクリプトの名前を「GameController」に変更します。

「GameController」をダブルクリックするとエディタが起動するのでコードを書きます。
スクリプトは以下のようになりました。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI; // UI用の名前空間
using TMPro; // TextMesh Pro用の名前空間
public class GameController : MonoBehaviour
{
public Image displayImage; // 画像表示
public TextMeshProUGUI displayText; // テキスト表示
public Button nextButton; // つぎへボタン
public Button backButton; // もどるボタン
public Sprite[] images; // 画像の配列
public string[] texts; // テキストの配列
private int currentIndex = 0; // 現在表示している画像とテキストのインデックス
// Start is called before the first frame update
void Start()
{
UpdateDisplay(); // 表示を更新
nextButton.onClick.AddListener(NextImage); // つぎへボタンのクリックイベントを登録
backButton.onClick.AddListener(PreviousImage); // もどるボタンのクリックイベントを登録
}
void NextImage()
{
if (currentIndex < images.Length - 1) // 最後の画像でない場合
{
currentIndex++; // インデックスを進める
UpdateDisplay(); // 表示を更新
}
}
void PreviousImage()
{
if (currentIndex > 0) // 最初の画像でない場合
{
currentIndex--; // インデックスを戻す
UpdateDisplay(); // 表示を更新
}
}
void UpdateDisplay()
{
displayImage.sprite = images[currentIndex]; // 現在の画像を表示
displayText.text = texts[currentIndex]; // 現在のテキストを表示
}
}
Unityに戻って、「プロジェクト」タブの「GameController」を「ヒエラルキー」タブの「Canvas」にドラッグ&ドロップしてアタッチします。アタッチとは紐付けるということです。

「Canvas」のインスペクターを見ると「Game Controller」コンポーネントが追加されています。

「Game Controller」コンポーネントには、スクリプト内でアクセス修飾子public
を指定した変数が表示されます。これらの変数に対応するUnityで作成したオブジェクトを設定していきます。
Images配列には0.png〜4.pngの画像を設定します。Texts配列には仮のテキストを設定します。
プロジェクトの実行
紙芝居が完成しました。いえーい。
Unityウインドウの上部にある「
、「ゲーム」タブのゲームを操作してみましょう。ちゃんと動きました。いえーい。画像の差し替え
ちゃんと動作するアプリが完成したので、画像とテキストを本番用に差し替えたいと思います。
で、画像を差し替える方法なのですが、Unity上で画像ファイルを上書きすればいいじゃんと思いますよね。でも、それではうまくいきません。こうなります。

同じ名前の画像をドラッグ&ドロップするとリネームされていまいます。というわけで、MacならばFinder、Windowsならばエクスプローラー上で上書きするのが正解です。「プロジェクト」タブの「Images」上で右クリック「Finder で表示」を選択すればFinder上の「Images」フォルダの場所がわかります。
テキストは、「Canvas」オブジェクトの「Game Controller」コンポーネントで書き換えます。
ゲームのビルド
ゲームをビルドします。メニューバーの「ファイル > ビルド設定…」を選択します。

「Build Settings」ウインドウが開きます。今回はMac用のアプリを作りたいので次のように設定しました。

- プラットフォームは「Windows, Mac, Linux」
- ターゲットプラットフォームは「macOS」
- アーキテクチャは「Intel 64-bit + Apple シリコン」
次に左下の「プレイヤー設定…」ボタンをクリックします。プレイヤー設定ウインドウが開きます。設定項目が非常に多いです。特に大事なものだけ設定しましょう。

- 企業名: 制作者の名前です。
- プロダクト名: これがそのままアプリの名前になります。
- バージョン: アプリのバージョン番号です。App Store などで公開する場合は、ちゃんとバージョン番号が増えてないと更新できないそうです。
- デフォルトのアイコン: アプリのアイコン画像を設定します。
- 解像度と表示: アプリを全画面モード、ウインドウモードのどちらで表示するか等の設定をします。
- スプラッシュ画像: 無料版のUnityでは必ず「MADE WITH Unity」のスプラッシュスクリーンが表示されますが、それに加えて独自のスプラッシュスクリーンを追加することができます。
設定を終えたらウインドウを閉じます。
「Build Settings」ウインドウに戻って、右下の「ビルド」または「ビルドして実行」をクリックします。「ビルドして実行」は文字通りビルドしたあとに自動的にアプリが起動します。
以上でゲームアプリが完成しました。わーい。

振り返り
はじめてUnityで成果物を作ったので、すべてが学びでした。引っ掛かったところはなかったかな。
ただ、C#スクリプトは全面的にChatGPT氏に書いてもらいました。読んでみてだいたい意味はわかるけど、自分で書けるようになるのはまだまだ先かも。いや、書けなくてもいいのか。便利な時代になったものだ。
次回、この紙芝居をもうちょっとブラッシュアップしたいです。BGMとかSEをつけたいなぁ。
でわでわ
コメント