ゲーム化!tomo_manaのブログ

ゲーム化!tomo-manaのブログ

Unityでゲームを作る方法について紹介しています

Unity学習#8 (Unity 2019.4.1f1) キャラクターのワープ

第8回は、キャラクターのワープに挑戦しました。
ここまで実装を続けてくることで、Unityの基本的な構想が分かってきて、キャラクターのワープの実装についても勘が働くようになってきました。
キャラクターのワープは、第5回の当たり判定と、前回(第7回)の中で触れたパラメータを画面上から入力できるようにする処理の組み合わせで実現します。また、データ容量を軽くするため、Create Emptyを使用します。

移動を考慮したマップの構成

第7回で、フィールドと町、ダンジョンとの間の移動は、とりあえず実装ハードルの低い同一平面上の移動で実現することにしました。マップを同一平面に作る場合は、マップ間の移り込みを避ける必要があります。

マップの間に必要な隙間

iPhoneandroid、その他の媒体での公開を検討する時に、媒体ごとに画面のピクセル数や縦横比が変わりますので、媒体ごとの差を埋めるための作り方は今後調べていくとして、どんなピクセル数、縦横比でも、マップとマップを何マス開けるかは事前に調べておく必要があります。
Unityのデフォルトで設定できる縦横比については、マップの端から以下のマス数(左右, 上下)を空ける必要があります。(Main CameraのSizeを7にした場合)

f:id:tomo_mana:20200724135408p:plain
縦横比と必要なマップ間隔の確認
縦横比 拡大率(Scale) 左右マス数(X) 上下マス数(Y)
16:9 1 13 7
16:10 1 11.5 7
3:2 1 11 7
4:3 1 10 7
5:4 1 9.2 7
Standalone(1024x768) 0.421 10 7
960x600 0.538 11.7 7

ワープポイントの作成

Emptyオブジェクトの作成

ワープポイントは、Emptyオブジェクトを使用します。作成後、座標はリセットしておきます。

(1) Hierarchyウィンドウの空きスペースで右クリック
(2) Create Empty を選択
(3) Inspectorウィンドウで名前を変更(WarpPoint)
(4) Inspector > Transform欄の縦3個の点が並んでいるアイコンを右クリック
(5) Reset を選択

Emptyオブジェクトの作成(各ワープポイント)

Emptyオブジェクトは位置情報など最低限の情報だけを持っているオブジェクトで、複数のオブジェクトを束ねるのに適しています。ワープポイントは複数作成するので、上記で作成したオブジェクトの下に、すべてのワープポイントを束ねると良いかと思います。

(1) Hierarchyウィンドウで先ほど作成したEmptyオブジェクトを選択
(2) オブジェクトの名前の上で右クリック > Create Empty を選択
(3) Inspectorウィンドウで名前を変更

ワープポイントの名前

名前は、どこからどこへ、が分かるように付けるようにするため、以下のようにします。
フィールド(Field:F)、町(Village:V)、ダンジョン(Dangeon:D)
フィールド→町:F2V

ワープポイントに当たり判定を付加する

ワープポイントにBox Colliderを付加します。
パラメータはisTriggerにチェックを付ける以外は第5回の障害物と同じです。

ワープポイントに質感を付加する

ワープポイントにRigidBody 2Dを付加します。
パラメータは第5回と同じく、BodyTypeをstaticにします。

f:id:tomo_mana:20200724120521p:plain
当たり判定

ワープC#スクリプトの作成

ワープ先を画面で管理できるように、また複数のワープポイントに同じスクリプトを適用できるように、ワープ先(warpPoint)をpublic変数として定義します。

(1) Projectウィンドウで右クリック
(2) Create > C# Script を選択
(3) 確定する前に、オブジェクト名を入力します
(ここでは、Warpとします)
(4) Projectウィンドウの空きスペースをクリックして、名前を確定します

(5) Projectウィンドウ上で右クリック > Openでコードを開きます。
(6) コードは以下のようにしました。

コード

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Warp : MonoBehaviour
{
	public Vector2 warpPoint;
	private Vector3 target;
	
    // Start is called before the first frame update
    void Start()
    {
    }

    // Update is called once per frame
    void Update()
    {
    }
    
    void OnTriggerEnter2D (Collider2D other) {
    	target = other.gameObject.transform.position;
    	target.x = warpPoint.x;
    	target.y = warpPoint.y;
    	other.gameObject.transform.position = target;
    }
}

ワープC#スクリプトのアタッチ

先ほどのコードをワープポイントオブジェクトにアタッチします。
(1) Hierarchyウィンドウでコードを付与するオブジェクトを選択
(2) Projectウィンドウでワープポイントのコードを選択
(3) Inspectorウィンドウの空いているスペースにドラッグ&ドロップ

ワープポイントに移動元、移動先を入力する

(1) Hierarchyウィンドウでコードを付与するオブジェクトを選択
(2) InspectorウィンドウのTransform > Positionに移動元の座標を入力
(3) InspectorウィンドウのC# Script欄に「Warp Point」が追加されます。
移動先の座標を入力します。

f:id:tomo_mana:20200724120946p:plain
移動元、移動先

ここまでで、意図したとおりにワープしてくれるかテストします。

ワープポイントの設計

往路と復路

ワープポイントは、一方通行でない限り、行きと帰りがあります。往路と復路は別々に用意します。

往路と復路で座標をずらす

移動元と移動先の座標は、重ならないようにします。(重なってしまうと、移動した瞬間に当たり判定が走ってしまい、無限に行ったり来たりを繰り返してしまうため)

ラベル Object名 移動元(X,Y) 移動先(X,Y)
フィールド→町 WarpPoint>F2V (0,-2) (25, 0)
町→フィールド WarpPoint>V2F (0, 24) (0, -3)
f:id:tomo_mana:20200724120136p:plain
町とフィールドの移動

座標の設定

先述の画面移りを防止するため、フィールド、町、ダンジョンの端と端を20マス空けるとして、座標を以下のようにします。

f:id:tomo_mana:20200724115536p:plain
ワープポイント
ラベル Object名 移動元(X,Y) 移動先(X,Y)
フィールド→町 WarpPoint>F2V (0,-2) (25, 0)
町→フィールド WarpPoint>V2F (0, 24) (0, -3)
フィールド→ダンジョン WarpPoint>F2D (0, 2) (-25, 0)
ダンジョン→フィールド WarpPoint>D2F (0, -24) ((0, -1)

Tilemapとのずれを補正する

第5回に書いた通り、座標系とTilemap座標には半マスずれています。第5回ではキャラクターをずらしましたが、ワープポイントを使いやすくするためにTilemap側を半マスずらすように修正します。

f:id:tomo_mana:20200724115813p:plain
Tilemapの座標(Grid)

キャラクターの座標は元の(0, 0)に戻します。

f:id:tomo_mana:20200724115851p:plain
Playerの座標 (0, 0に戻す)

ワープポイント(2点目以降)の作成

作り方は1点目と同じです。
(1) ワープポイントを束ねるオブジェクトの下に、Emptyオブジェクトを作成
 名前の付け方は移動元→移動先
 パラメータはリセット
 Transform > Position に移動元座標を入力
(2) 作成したEmptyオブジェクトに当たり判定(Box Collider)を付加
 isTrigger にチェック
(3) 作成したEmptyオブジェクトに質感(RigidBody 2D)を付加
 BodyType = static
(4) 先ほど作成したC#スクリプト(Warp)を付加
(5) C#スクリプト > Warp Point にワープ先座標を入力

次回やること
画面のフェードアウト・フェードイン