Unity(C#)初心者・入門者向けチュートリアル ひよこのたまご

AndroidやiOS向けアプリを簡単に作れるゲーム開発環境Unity(ユニティ)の使い方を、チュートリアル方式で一緒に学びましょう!

【Unity】2Dタイルマップ⑩ Isometricなマップで建物の上を通る・下をくぐる【後編】

Unity 2020.2.1f1 Personal(2021年3月)
前回の続きです!
前編ではTilemapの配置とPlayerの作成を行ました。
後編ではCollider用Tilemapの作成とプレイヤーの位置によって有効なColliderを切り替える方法を解説します。

この記事はUnity 公式のIsometric 2DTilemapプロジェクトを一部参考にしています。

blogs.unity3d.com


f:id:hiyotama:20210318213156p:plain

TilePaletteの作成(ColliderPalette)

まずはColliderTilemap用のパレットを作成します。
ColliderPaletteという名前でTilePaletteを作成して下さい。

f:id:hiyotama:20210320012126p:plain
ColliderPalette作成

続いてColliderとなるSpriteをパレットに登録していきます。
以下の画像をUnityにアップして下さい。

f:id:hiyotama:20210320012259p:plain
collider1.png
f:id:hiyotama:20210320012304p:plain
collider2.png
f:id:hiyotama:20210320012307p:plain
collider3.png
f:id:hiyotama:20210320012310p:plain
collider4.png
f:id:hiyotama:20210320012314p:plain
collider5.png
f:id:hiyotama:20210320012320p:plain
collider6.png

各Spriteの設定は以下の通りです。

f:id:hiyotama:20210320012547p:plain

またSprite EditorのCustom Physics Shapeにて各Spriteの形通りに囲って下さい。

f:id:hiyotama:20210320012806p:plain
collider1.pngの例

各Spriteの設定が完了したらColliderPaletteにドラッグ&ドロップしTileを登録していきます。

f:id:hiyotama:20210320013124p:plain
Collider用Tileを登録

Tilemapを作成する(Collider用Tile)

パレットの設定が完了したので続いてTileを配置していきます。
今回は1階用・階段用・2階用のTilemapを作成します。
まずは1階用Tilemapです。
HierarchyからCreate > 2D Object > Tilemap > IsometricでTilemapを作成して下さい。
名前は「Collider1f」とします。

f:id:hiyotama:20210320013610p:plain
Tilemap作成

作成したTilemapのTilemapRendererのModeをIndividualに、
またColliderを確認しやすいようにSorting Layerに「ColliderDebug」を作成して設定します。

f:id:hiyotama:20210320014006p:plain

またColliderを確認しやすいように色を透けたピンクにします。
ProjectビューにてCreate > MaterialでMaterialを新規作成し、名前を「ColliderTilemap」にします。
作成したMaterialのInspectorから、ShaderをSprite/Defaultに、Tintをピンクにして透明度を60%程度にします。

f:id:hiyotama:20210320014349p:plain

作成したMaterialをCollider1fのTilemapRendererのMaterialに設定します。

f:id:hiyotama:20210320014456p:plain
Materialを設定

あとはCollider1fオブジェクトにTilemapCollider2DとCompositeCollider2Dを取り付けます。
TilemapCollider2DのUsed byCompositeをtrueに、
自動的に取り付けられるRigidbody2DのBody TypeをKinematicに変更します。

f:id:hiyotama:20210320014907p:plain
TilemapCollider2D, Rigidbody2D, CompositeCollider2Dの設定

Tileを配置する(Collider用Tile)

ようやくTilemapの準備が完了しました。
それではTileを配置していきます。

f:id:hiyotama:20210320015436p:plain
1階のColliderを配置

フィールドの外に出ないように囲ったのと、階段の後ろ側をブロックしました。

同じ要領で階段用のTilemapを作成します。
基本的にはCollider1fと同じです。

f:id:hiyotama:20210320015932p:plain

・ColliderStairという名前でTIlemap作成
・ModeをIndividualに変更
・MaterialにColliderTilemapを設定
・Sorting LayerをColliderDebugに設定
・TilemapCollider2Dを取り付けUsed by Compositeをtrue
・Composite Collider2Dを取り付ける
・Rigidbody2DのBody TypeをKinematicに設定

f:id:hiyotama:20210320020245p:plain
階段のColliderを配置

同じようにCollider2fという名前の2階用Tilemapを作成し、Tileを配置していきます。

f:id:hiyotama:20210320020606p:plain
2階のColliderを配置

以上でCollider用のTilemapの作成は完了です。

f:id:hiyotama:20210320020645p:plain
Collider用Tilemapを3つ作成

プレイヤーの位置によって有効なColliderを切り替える

Collider用TIlemapの作成まで完了しました。
最後にプレイヤーの位置によって有効なColliderを切り替える機能を実装します。(1階にいる時は1階のColliderを、2階にいる時は2階のColliderを有効にする)

まずはMapController.csを作成します。

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

public class MapController : MonoBehaviour
{
    public static MapController instance;
    [SerializeField] List<GameObject> floorList;

    private void Awake()
    {
        if (instance == null)
        {
            instance = this;
        }
        else
        {
            Destroy(this.gameObject);
        }
    }


    private void Start()
    {
        SetCurrentFloor(0);
    }


    public void SetCurrentFloor(int floor)
    {
        for (int i = 0; i < floorList.Count; i++)
        {
            floorList[i].SetActive(i == floor);
        }
    }
}

MapController.cs

こちらのScriptをControllerオブジェクトに取り付けて下さい。
またInspectorからFloorListを3つ用意し、各Collider用のTilemapを登録します。

f:id:hiyotama:20210320021801p:plain
Collider1f, ColliderStair, Collider2fの順番で登録する。

SetCurrentFloorメソッドを実行すると
引数で設定したCollider用Tilemapが有効になりそれ以外のCollider用Tilemapが無効になります。

続いて階を切り替えるポイントとなるFloorChangePointオブジェクトを作成していきます。
空オブジェクトを作成し名前を「FloorChangePoint」に変更します。
作成したFloorChangePointオブジェクトはCollider1fオブジェクトの子オブジェクトにします。

f:id:hiyotama:20210320022943p:plain


InspectorからPolygonCollider2Dコンポーネントを取り付け、
PolygonCollider2DのEdit Colliderから下の画像のように階段の入り口にColliderを形作ります。

f:id:hiyotama:20210320022753p:plain

PolygonCollider2DのIsTriggerはtrueにしておきます。

f:id:hiyotama:20210320024640p:plain

最後にFloorChangePoint.csを作成しFloorChangePointオブジェクトに取り付けます。

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

public class FloorChangePoint : MonoBehaviour
{
    [SerializeField] int floorNum;

    private void OnTriggerExit2D(Collider2D collision)
    {
        if (collision.transform.tag == "Player")
        {
            MapController.instance.SetCurrentFloor(floorNum);

            switch (floorNum)
            {
                case 0:
                    collision.transform.GetComponent<Player>().SetZPos(2f);
                    break;
                case 1:
                case 2:
                    collision.transform.GetComponent<Player>().SetZPos(8f);
                    break;
            }
        }
    }
}

FloorChangePoint.cs

OnTriggerExit2Dが実行されるタイミングは先ほど作成したColliderをPlayerオブジェクトが外に出たタイミングです。
先ほどのMapControllerのSetCurrentFloorメソッドが実行されます。
引数のfloorNumはFloorChangePointオブジェクトのInspectorから設定できます。
Collider1fを非表示にしてColliderStairを表示したい場合は、floorNumを1に設定する、といった感じです。

f:id:hiyotama:20210320023526p:plain

switch文ではPlayerのposition.zを変更しています。
というわけでPlayer.csにSetZPosメソッドと追加していきます。

Player.csにSetZPosメソッドを追加

それではPlayer.csにSetZPosメソッドを追加修正していきます。

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

public class Player : MonoBehaviour
{
    private readonly float speed = 0.03f;

    public void MoveUp()
    {
        transform.position = new Vector3(transform.position.x + speed, transform.position.y + (speed / 2f), transform.position.z);
    }


    public void MoveDown()
    {
        transform.position = new Vector3(transform.position.x - speed, transform.position.y - (speed / 2f), transform.position.z);
    }


    public void MoveLeft()
    {
        transform.position = new Vector3(transform.position.x - speed, transform.position.y + (speed / 2f), transform.position.z);
    }


    public void MoveRight()
    {
        transform.position = new Vector3(transform.position.x + speed, transform.position.y - (speed / 2f), transform.position.z);
    }

// ***** 追加 *****
    public void SetZPos(float zPos)
    {
        transform.position = new Vector3(transform.position.x, transform.position.y, zPos);
    }
// ***** 追加終了 *****
}

Player.cs

SetZPosメソッドは単純にPlayerのzPosを更新するだけのメソッドです。

FloorChangePointを複数作成する

ここまででPlayerが階段を通過しようとするとCollider1fが無効になり、ColliderStairが有効になるようになりました。
同じように階段から2階へ上がるポイントにFloorChangePointオブジェクトを置きます。
FloorChangePointをPrefab化し、ColliderStairオブジェクトの子オブジェクトにします。

f:id:hiyotama:20210320024958p:plain

ColliderStairを非表示にしCollider2fを表示させたいので、
FloorChangePoint.csのfloorNumを2にします。

f:id:hiyotama:20210320025136p:plain

位置としては階段と2階の間です。

f:id:hiyotama:20210320025259p:plain
階段と2階の間にCollider配置

続いて2階から階段へ移動するFloorChangePointオブジェクトを作成します。
Collider2fオブジェクトの子オブジェクトとしてFloorChangePointオブジェクトを作成し、FloorChangePoint.csのfloorNumを1にします。
位置としては階段と2階の間ですが、先ほど作成した2階に切り替えるFloorChangePointオブジェクトより階段寄りに配置します。

f:id:hiyotama:20210320025804p:plain
階段と2階の間にCollider配置

最後に階段から1階へ移動するFloorChangePointオブジェクトを作成します。
ColliderStairオブジェクトの子オブジェクトに作成し、floorNumを0にします。
最初に作成したFloorChangePointオブジェクトより1階寄りに配置します。

f:id:hiyotama:20210320030818p:plain
1階と階段の間にCollider配置

以上で左側の階段のFloorChangePointの作成が完了しました。
右側の階段も同様の手順でFloorChangePointを配置したら作業完了です。

結果

それでは結果を確認していきます。
まずは建物の下をくぐってみます。

f:id:hiyotama:20210320031134g:plain

有効になっているColliderは1階のみなので、
当然建物の下をくぐることができます。

続いて建物の上を通ります。

f:id:hiyotama:20210320031624g:plain

1階、階段、2階とプレイヤーの位置によって有効なColliderを切替え、
無事建物の上を通過することができました。

オマケ:HideTilemapRendererスクリプト

ゲーム開始時にTilemapColliderの色を消すHideTilemapRenderer.csを最後に掲載します。

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

public class HideTilemapRenderer : MonoBehaviour
{
    void Start()
    {
        GetComponent<TilemapRenderer>().enabled = false;
    }
}

HideTilemapRenderer.cs

TilemapRendererのenabledをfalseにして色だけ消しています。(Colliderは残っています。)
using UnityEngine.Tilemaps;
の記述をしないとTilemapRendererを使えないのでご注意下さい。
こちらのScriptをCollider1f, ColliderStair, Collider2fオブジェクトにつけることでゲーム開始時にColliderの色を隠すことができます。

というわけで今回は以上です。
ありがとうございました〜。