ぬるーむ

Unity初心者が誰もが知っているゲームの模倣をしています。個人的な備忘録ですが、入門書を読み終えたばかりの初心者の方は「こんなへなちょこでもいいのか!」「俺の方がうまく作れる」と作成意欲がわいたりするかもしれません。

Unityによるパックマンの作り方 ~ゴーストの状態~

IStateを継承したクラスで、ゴーストの状態の遷移と、そのときの行動を処理します。Dictionary<State, IState>とenum Stateで各stateを登録・参照し、Mover、Animatorで移動、アニメーションを行います。

f:id:Nullsuke:20210509131659p:plain
状態とそのときの行動

移動に関しては下記を参照してください。

nullsuke.com

アニメーションに関しては下記を参照してください。

nullsuke.com

Unityによるパックマンの作り方 ~ゴーストの作成~

ゴーストオブジェクトの作成

16px × 16pxの画像を用意し、Pixels Per Unitを8にします。画像からSpriteを作成し、Rigidbody2D、BoxCollider2Dをアタッチします。適当にColliderの大きさを設定します。

f:id:Nullsuke:20210504105158p:plain
Sprite画像

f:id:Nullsuke:20210515003559p:plain
ゴーストオブジェクト

状態の管理

ゴーストは最初、巣に待機しており(アカベイは除く)、一定時間経過すると特定のエリアを巡回するようになります。一定時間巡回するとパックマンを追跡するようになります。一定時間追跡するとまた特定のエリアを巡回するようになります。パックマンがパワーエサを食べると恐慌状態になり、このときパックマンに食べられると、死亡状態となります。死亡状態では一旦巣に戻り、巣に入ると待機状態になります。

f:id:Nullsuke:20210509143653p:plain
ゴーストの状態遷移

これら状態遷移と行動を実装します。今回はStateパターンを使いますが、if文やSwitch文の方が簡単かもしれません。

状態クラスについては下記を参照してください。

nullsuke.com

Stateパターンについては下記のサイトを参照してください。

qiita.com

抽象クラスAGhostの作成

状態クラスを使って移動や処理する抽象クラスです。ワープの為のインターフェイスIWarpableとパックマンに食べられる為のインターフェイスIEatableを継承します。

各ゴーストのクラスを作成

AGhostを継承して各ゴーストのクラスを作成します。各ゴーストのAIついては下記を参照してください。

アカベイ

ピンキー

アオスケ

グズタ

完成

ゴーストオブジェクトにゴーストクラス、ゴーストAI、Mover、Animatorをアタッチし、待機時間などパラメータを設定します。

f:id:Nullsuke:20210512221645p:plainf:id:Nullsuke:20210512221829p:plain
アカベイ、ピンキー

f:id:Nullsuke:20210512222002p:plainf:id:Nullsuke:20210512222004p:plain
アオスケ、グズタ

迷路上にゴーストをセットすれば完成です。

f:id:Nullsuke:20210515224840g:plain
ゴーストの完成

Unityによるパックマンの作り方 ~パックマンの作成~

仕様はいたってシンプルです。

  • キーを押したら障害物にぶつかるまで進み続ける。
  • 移動中にキーを押すと、その方向に移動できるようになったとき自動的にその方向に進む。
  • ワープ地点に来たら反対側にワープする。
  • エサ、パワーエサ、フルーツ、怯えた状態のゴーストを食べる。
  • 通常状態のゴーストに食べられる。

Pacmanオブジェクトの作成

16px × 16pxの画像を用意し、Pixels Per Unitを8にします。画像はUnityのSprite Packerを使って1つの画像にまとめるとゲーム起動時の負荷が減ります。

f:id:Nullsuke:20210504105158p:plain
Sprite画像

画像からSpriteを作成し、Rigidbody2D、CirlceCollider2Dをアタッチします。適当にColliderの大きさを設定します。

f:id:Nullsuke:20210504105225p:plain
Pacmanオブジェクト

Pacmanクラスの作成

移動

当たり判定

Physics2D.Linecastを使います。この関数の引数はグローバル座標なので注意してください。

フレームごとの移動

Vector2.MoveTowardsを使い現在座標、目標座標、移動速度からフレーム毎の移動座標を求め、Rigid2D.MovePositionで移動させます。

目標座標に限りなく近づいたら壁との当たり判定を行い、判定が偽の場合移動します。

また、キー入力もここで行います。

ワープ

パックマンの現在地をWarpPointの出口にし、進行方向を1つ先に設定するだけです。継承したIWarpable.Warpに実装し、WarpPointに接触したら実行するようにします。

食べる

パックマンが食べることができるもの(エサ、パワーエサ、恐慌状態のゴースト、フルーツ)にIEatableインターフェイスを継承します。食べたときの動作は食べられる側で実装します。パックマン側はOnTriggerEnter2DでIEatable.Eatenを実行するだけです。

アニメーション

上下左右の移動と死亡時のアニメーションを作成します。 すべてのアニメーションはAny Stateから遷移するようにします。 Animation ControllerのParametersに以下の変数を作成します。

  • float DirX
  • float DirY
  • bool isDead

f:id:Nullsuke:20210503101958p:plain
Animation Controller

遷移の条件は以下の通りです。また、Can Transition To Selfは必ずオフにしておきましょう。

  • Up:DirY > 0.1 & isDead == false
  • Right:DirX > 0.1 & isDead == false
  • Down:DirY < -0.1 & isDead == false
  • Left:DirX < -0.1 & isDead == false
  • Dead: isDead == true

f:id:Nullsuke:20210503103402p:plain
UpへのTransition

死亡のアニメション終了と同時に自身を削除するようにしておきます。

f:id:Nullsuke:20210503103855p:plain
死亡のアニメーション終了後の設定

移動時に、DirXとDirYにパックマンの進行方向を代入します。

死亡時に、IsDeadを真にします。

完成

PacmanオブジェクトにAnimator、Pacmanクラスをアタッチします。適当にSpeedを設定します。

f:id:Nullsuke:20210504105403p:plain
Pacmanオブジェクト

毎フレーム、MoveとAnimateを実行させます。

nullsuke.com

上記で作成した迷路上にパックマンをセットすれば完成です。パックマンの初期位置は必ず整数にしてください。そうしないと、移動中に引っかかってしまいます。

f:id:Nullsuke:20210503133733g:plain
パックマン(キャラのみ)の完成

Unityによるパックマンの作り方 ~半自動でBoxCollider2Dをセット~

BoxCollider2Dに必要な中心座標、サイズをを取得したいが、直接迷路の画像から取得するのは難しい。なので、まずデータ取得用の画像(ColliderMap)を作成し、そこから必要なデータを取得するようにします。この取得したデータをもとに迷路の画像にBoxCollider2Dをアタッチします。

ColliderMapの作成

ここではClipStudioを使用していますが、下記の機能が使えるものなら何でもよいです。

  • ベクターレイヤー。
  • グリッドの表示、グリッドにスナップ。

迷路の画像のレイヤーの上からBoxCollider2Dの半分の大きさの短形を描いていきます。ベクターレイヤーで矩形をブラシサイズ1pxで描画し、ラスターレイヤーで適当な色で塗りつぶしていきます。このとき、適当なサイズでグリッドを表示し、グリッドにスナップするようにしておくと楽です。

f:id:Nullsuke:20210501152714g:plain
ColliderMapの描画
f:id:Nullsuke:20210502231835p:plain
ColliderMap

BoxCollider2Dそのものの短形にしないは、BoxCollider2Dが隣接しているとうまく座標を取得できないからです。

作成した画像はRead/Write Enableを有効にしておくこと。そうしないとスクリプトから画像を読み込めません。

f:id:Nullsuke:20210502092252p:plain
ColliderMapの設定

ColliderMapから矩形を取得

以下の手順で矩形を取得していきます。

  1. ColliderMapをTexture2Dとして読み込ます。
  2. 原点(左下)から水平方向に、連続してある不透明な(α値が0でない)点を取得します。
  3. 垂直方向に、2で取得した直線と同じ長さの不透明な直線があるか精査し、あれば取得します。
  4. 2, 3を精査済みの点を飛ばしながら繰り返します。

MazeUtilityクラスでColliderMapの読み込み、精査、矩形の取得をします。取得した矩形をRectangleクラスで保存します。

BoxCollider2Dをアタッチ

MazeオブジェクトにMazeUtilityをアタッチし、ColliderMapをセットします。Mazeオブジェクトが読み込まれたときBoxCollider2Dをアタッチするようにします。

f:id:Nullsuke:20210505105258p:plain
Mazeオブジェクト(余計なものがいろいろついてますが気にしないでください)

MazeUtilityで得た矩形は必要な矩形の半分の大きさなので2倍した値を使います。また、迷路の画像はPixels Per Unitを8pxにしているので8で割ります。

Unityによるパックマンの作り方 ~迷路の作成~

Mazeオブジェクトの作成

迷路の画像を用意しスプライトを作成します。

f:id:Nullsuke:20210501223846p:plain
迷路の画像

Pixel Per Unitを8、Pivotを左下にします(左下を原点にしておくと今後わかりやすいので)。

f:id:Nullsuke:20210502081128p:plain
迷路の画像の設定

Mazeクラスを作成し、アタッチします。この時点で、クラスは空でかまいません。

f:id:Nullsuke:20210505102811p:plain
Mazeゲームオブジェクト

BoxCollider2Dをアタッチ

迷路の壁部分にそれぞれBoxCollider2Dを0.25単位でアタッチします(0.25刻みでないとパックマンが移動中に引っかかってしまう)。

f:id:Nullsuke:20210502085754g:plain
手作業でBoxCollider2Dをアタッチ
f:id:Nullsuke:20210502091949p:plain
BoxCollider2Dの位置、サイズ
f:id:Nullsuke:20210502092114p:plain
BoxCollider2D

手動でも十分可能ですが、半自動でアタッチすることもできます(といっても下準備に手間がかかるのですけどね)。

nullsuke.com

ワープ地点の作成

IWarpableインターフェイスを作成し、ワープさせたいキャラ(パックマン、ゴースト)に継承させます。

ワープ用のクラスWarpPointを作成します。これにワープの出口の座標を保持させ、IWarpable.Warpメソッドを使いワープの出口に瞬間移動させます。

空のGameObjectを2つ作成し、それぞれにBoxCollider2D、WarpPointをアタッチします。ワープの出口の座標は出た直後に、出口のワープポイントとキャラが接触しないよう少し離れた位置にしましょう。これらを迷路のワープの入り口にセットします。

f:id:Nullsuke:20210502120539p:plain
WarpPoint位置
f:id:Nullsuke:20210502130935p:plainf:id:Nullsuke:20210502133033p:plain
ワープポイントの設定

Unityによるパックマンの作り方

主に下記サイトを参考にしました。これらのサイトを読めば十分かもしれません(笑)。ただ、どのサイトも古く(まぁ、パックマン自体が古いが)、英語のサイトなので日本語で今風の作り方の解説もあってもよいかなとも思っています。

Unityによるパックマン作成のチュートリアルです。ここを見れば、8割方作れます。ただ、ゴーストの移動が一定だったり、パワーエサがなかったりと中途半端です。

Unityによるパックマンのソースです。上記のサイトにはないゴーストの移動などのソースがあります。

パックマンの仕様が書いてあります。ゴーストの移動の仕様などは参考になります。

迷路の作成

下記を参照してください。 nullsuke.com

パックマンの作成

下記を参照してください。 nullsuke.com

ゴーストの作成

下記を参照してください。 nullsuke.com

アイテムの作成

下記を参照してください。 nullsuke.com

BGM・SEを再生する

下記を参照してください。 nullsuke.com

完成

nullsuke.com

unityroomに自作ゲーム 「Let's Eat」 を公開しました

パックマンもどきのゲーム「Let's Eat」をunityroomに公開しました。近いうちに作成の解説も公開する予定です。

f:id:Nullsuke:20210501233709g:plain
Let's Eat
unityroom.com