naichi's lab

3日後の自分(他人)への書き置き

【Unity】Isometric 2.5D Toolsetを使ってクォータービュー(Isometric Tilemap)のゲームを作ろう

はじめに

こんにちは、 @naichilab です。

この記事は Unity アセット真夏のアドベントカレンダー 2018 Summer! 22日目の記事です。

昨日は @xiumidaさんの 【アドカレ 2018】Closing Creditsでスタッフロールを作るでした。アセットの更新止まっちゃってるのが残念ですがとても便利そうです!

さて、本記事では Isometric 2.5D Toolset というクォータービューのタイルマップを扱えるアセットを紹介したいと思います。

目次

環境

  • Unity 2018.2.3f1
  • Isometric 2.5D Toolset 3.0.3 (2018/08/15リリース)

クォータービューって?

f:id:naichilab:20180818150205p:plain:w320

Googleで画像検索するとこんな感じ。

クォータービューは和製英語らしいので Isometric Tile とかで調べた方が情報は多いかもしれません

Isometric 2.5D Toolset について

今回紹介する Isometric 2.5D Toolset はアイソメトリックタイルを使ったゲームを作りやすくしてくれるアセットです。

エディター上でのタイル配置、前後関係のソート、物理演算、3Dモデルとの併用など、いろんな機能を提供してくれます。

クォータービューの箱庭ゲームを作ろうと思って色々アセットを購入して比較しましたが、このアセットが一番求めているものに近かったので使っています。

とりあえず使ってみる

このアセットがどんな感じか知ってもらうために利用開始までの手順をまとめておきます。

Isometric 2.5D Toolset をダウンロード&インポート

  1. アセットストアで購入してダウンロード
  2. Unityにインポートします。
    • f:id:naichilab:20180818181825p:plain:w320

IsoWorld を設置

Isometric 2.5D Toolset では、 IsoWorld というスクリプトをつけたオブジェクトが必須です。 まずはそれを作ります。

  1. Hierarchy -> Create -> Create Empty
  2. 名前は IsoWorld とします。
  3. Position も 0,0,0 にしておきましょう。(別にずれててもいいですけど)
    • f:id:naichilab:20180818184954p:plain:w320
  4. さらに AddComponent -> IsoWorld を追加します。
    • f:id:naichilab:20180818185041p:plain:w320
  5. こんな感じ
    • f:id:naichilab:20180818185456p:plain:w320

同一シーンに IsoWorld を複数設置することもできます。

IsoObject を設置

IsoWorld を設置したら、その子供に IsoObject を作っていきます。

  1. IsoWorld を選択して再度 Create Empty します。
  2. 名前は IsoObject にします。( Floor とか、 Table とか分かりやすい名前をつけてもいいです)
  3. Add Componentから IsoObject コンポーネントを付与。
  4. こんな感じになります。
    • f:id:naichilab:20180818185906p:plain:w320
  5. このままでは分かりづらいので下記チェックを入れましょう
    • Editor Only -> Show Iso Bounds
    • Editor Only -> Show Screen Bounds
    • f:id:naichilab:20180818191559p:plain:w320
  6. すると Scene ビューに六角形が表示されます。
    • f:id:naichilab:20180818191725p:plain:w320

タイルサイズを決める

IsoWorldWorld Settings で各タイルのサイズを決めます。

f:id:naichilab:20180818213252p:plain:w320

今回は分かりやすく 1dot = 1m になるように設定してみます。

例えば下記のような 32px x 16px の画像を使う場合、

f:id:naichilab:20180818225452p:plain

Tile SizeTile Height16 にして、下記のようにします。

項目
Tile Size 16
Tile Ratio 0.5
Tile Angle 45
Tile Height 16

試しにサイズが 32 x 16 のCubeと重ねて見るとこんな感じ。

f:id:naichilab:20180818214409p:plain:w320

ちゃんとCubeとひし形が重なりました。

等角以外のタイルについて

Tile RatioTile Angle を変えると等角投影以外のタイルにも対応できます。

Tile Ratio を変更した場合、見下ろす角度が変わります。

f:id:naichilab:20180818215204g:plain:w320

Tile Angle を変更した場合、左右の角度が均一ではなくなります。

f:id:naichilab:20180818215550g:plain:w320

Isometric = 等角ではないタイルはなんて呼ぶんでしょうね?

今回の記事では等角のまま(TileRatio=0.5、 TileAngle=45)で進めます。

タイル画像を用意

タイルサイズを決めたら画像を用意します。

  • この記事では今作ってるゲームの画像を使います。
    • f:id:naichilab:20180819002100p:plain:w320

インポートした Isometric 2.5D Toolset にもサンプル画像が含まれてるので特に用意しなくても試せます。

ドット絵タイル画像の自作について

自分は絵がかけないのでデザイナさん頑張ってとしか言えないのですが、
32px x 16px を基準にする場合、32px x 15px を積み重ねるように描くと綺麗に敷き詰められるようです。

32x15 でひし形を用意

f:id:naichilab:20180818184103p:plain:w320

厚み1pxで緑を重ねるとこんな感じ

f:id:naichilab:20180818184236p:plain:w320

ぴったり並びました。

Isometric 2.5D Toolset では、IsoObject の高さを0にすると同じ高さ同士でのソート順がおかしくなることがあります。 なので上記のような薄っぺらいオブジェクトも、1px分の厚みがあるものとして設定していきます。

テクスチャのインポート設定

  1. 用意した画像をUnityに放り込みます。
    • f:id:naichilab:20180818225929p:plain:w320
  2. テクスチャ設定を変更します。
    • TextureType = Sprite(2D and UI)
    • Pixels Per Unit = 1 (画像サイズとタイルサイズの兼ね合いで調整してください)
    • Pivot = Bottom
    • Generate Physics Shape = false (不要)
    • Filter Mode = Point (no filter) (ドット絵なのでOFF)
    • f:id:naichilab:20180818223800p:plain
  3. 変更したら Apply

IsoObject にSpriteをつける

やっとタイル設定と画像の取り込みが終わったのでシーンに配置していきます。

  1. IsoObject の子として 2D Object -> Sprite を追加します。
    • f:id:naichilab:20180818223506p:plain:w320
  2. Sprite のインスペクタから画像を選択します。
    • f:id:naichilab:20180818230134p:plain:w320
    • ひし形に合うように表示されました。
    • 位置があってない場合はSpriteを移動させてしまえば大丈夫です。
  3. IsoObject を選択し、Sizeを変更する
    • この画像は高さ1pxなので、1/16 を入力します。( IsoWorld の設定で Tile Height を16にしたので1dot = 1/16)
    • f:id:naichilab:20180818230341p:plain:w320
    • 赤線がぴったり合いました。
  4. IsoObject の名前を分かりやすく変更し、Prefabにでもしておきましょう。
    • f:id:naichilab:20180818230633p:plain:w320

タイルを並べる

  1. 作ったPrefabをHierarychyビューにドラッグするか、直接 IsoObjectCtrl+Dcmd+D で複製します。
    • f:id:naichilab:20180818230847p:plain:w320
  2. それぞれの IsoObject を自由に移動します。
    • f:id:naichilab:20180818231040p:plain:w320
    • 綺麗に並びました。
IsoObject のドラッグ移動が楽々

IsoObject を選択した場合のGizmoはこんな感じです。

f:id:naichilab:20180818231414p:plain:w320

XYの線(赤と緑)が斜め上方向に伸びています。
IsoObject のXYZ座標はWorldのXYZ座標と一致していないので、専用のハンドルが用意されています。

そしてこのハンドルはスナップが効くようになっているので整列させるのが非常に楽です。

f:id:naichilab:20180818232021g:plain:w320

他の形も並べてみる

同様に幅や高さの違う IsoObject を作ってみました。

f:id:naichilab:20180818232628p:plain:w320

  • 茂み(IsoSize = 1x1x1
  • 木(IsoSize = 1x1x5
  • テーブル(IsoSize = 1x2x1

適当に移動してもいい感じに整列してくれます。

f:id:naichilab:20180818232808p:plain:w320

Sceneビューを3D表示にすると常にソートされていることがよく分かります。

f:id:naichilab:20180818234737g:plain:w320

その他の小ネタ

物理演算したい

IsoRigidbody コンポーネントを使えば可能です。

  • 茂みに IsoRigidbodyIsoBoxCollider をつけました。
    • f:id:naichilab:20180818235821p:plain:w320
  • 床に IsoBoxCollider をつけました。
    • f:id:naichilab:20180818235848p:plain:w320

これだけでちゃんと重力を扱ってくれます。便利。

f:id:naichilab:20180819000256g:plain:w320

クリックされた場所のIsoWorld座標を取得したい

IsoWorldMouseIsoPosition が使えます。

using UnityEngine;
using IsoTools;

public class Sample : MonoBehaviour
{
    void Update()
    {
        var iso_world = IsoWorld.GetWorld(0);
        if (iso_world && Input.GetMouseButtonDown(0))
        {
            var iso_mouse_pos = iso_world.MouseIsoPosition(0);
            Debug.Log("クリックしたIso座標は[" + iso_mouse_pos + "]です。");
        }
    }
}

たったこれだけ。

クリックされたIsoObjectを取得したい

IsoPhysicsRaycast を使います。(IsoObjectにIsoColliderをつけておく必要があります)

using UnityEngine;
using IsoTools;
using IsoTools.Physics;

public class Sample : MonoBehaviour
{
    static IsoRaycastHit[] _raycastBuffer = new IsoRaycastHit[16];

    void Update()
    {
        //クリック座標の下にあるIsoObjectsを取得
        var iso_world = IsoWorld.GetWorld(0);
        if (iso_world && Input.GetMouseButtonDown(0))
        {
            var iso_mouse_pos = iso_world.MouseIsoPosition(0);
            var ray_from_iso_camera = iso_world.RayFromIsoCameraToIsoPoint(iso_mouse_pos);
            var hit_count = IsoPhysics.RaycastNonAlloc(ray_from_iso_camera, _raycastBuffer);
            for (var i = 0; i < hit_count; ++i)
            {
                IsoRaycastHit hit = _raycastBuffer[i];
                Debug.Log(hit.collider.gameObject.name + "をクリックしました。");
            }
        }
    }
}

困ったら?

とりあえず公式フォーラムを読み漁りましょう!

https://forum.unity.com/threads/v3-0-1-isometric-2-5d-toolset.291418/

作者のblackmatさん、結構マメに返信してて好感が持てます。

最近もアセットの更新は続いてるようなので、フォーラムの返信も期待できます。

他のアセットとの比較

さて、Isometric 2.5D Toolset の基本的な機能は伝わったでしょうか?

アセットストアにはいくつかアイソメトリックタイル用のアセットがあるので簡単に比較してみます。

Ultimate Isometric Toolkit

すぐに見つかるのはこちらの Ultimate Isometric Toolkit かと思います。無料のLite版もあります。

こちらも専用のGizmoが用意されていますが、スナップ機能はないようです。

f:id:naichilab:20180819004239p:plain:w320

また、こちらのチュートリアル にあるように、タイルサイズより大きなSpriteは分割して扱う前提のようです。

物理演算やキャラクターコントローラ、パスファインディング等の機能もあるようですね。

Isometric Builder

こちらのアセット存在は知りませんでした。(この記事書いてて見つけました)

Youtubeのチュートリアル見る感じ、使いこなせればかなり強力そうです。

2Dタイルマップのオートタイル機能のようにドラッグでどんどんマップを作れるようなので、RPGとかどんどんマップ作っていく系のゲームには向いてそうですね。

ただちょっとフレームワークとして大掛かりすぎる気もします・・・。

Unity標準機能

Unity標準でもタイルマップ機能は提供されています。

Unity 2017.2から2Dタイルマップ、さらにUnity 2018.2から六角形の2Dタイルマップがサポートされました。

ただ、残念ながらアイソメトリックタイルは非対応です。

2D Experimental Preview には入ってるらしい?(ちょっと確認できなかった)
のでいずれ標準機能でサポートされるかもしれません。

自作する

Introduction to Isometric Movement in Games - YouTube

Isometric座標の計算自体はそれほど難しいものではなさそうなので、実装してみるのもいいかもしれません。

自分も最初は実装しようかと思ったのですが、タイルサイズを考慮してのソートが必要になると一気にややこしくなって諦めましたw

所感

いくつか見てきましたが、テーブルのようなXY長さがタイルサイズより大きいものをソートできるのは Isometric 2.5D Toolset だけでした。

固定サイズのブロックを並べていくような用途の場合、 Ultimate Isometric ToolkitIsometric Builder の方が優れている点も多そうです。

宣伝

今日紹介した Isometric 2.5D Toolset を使って新作作ってます。

森を開拓して建物を並べて〜といった森開拓シミュレーションになる予定です。

こちらのアカウントで情報出していくのでぜひフォローお願いします。

twitter.com

来年春ぐらいに出したい・・・な

まとめ

クォータービューのゲームはワクワクするのでみんな作りましょう!遊びたい!

と言うわけでUnity アセット真夏のアドベントカレンダー 2018 Summer!、22日目の記事でした。

明日は ラズさんです。お楽しみに〜。