top of page

2Dランゲーム編

Lesson2 ステージを作ろう

2-1

2-1 タイルマップ

2-1 タイルマップ

1

Palletフォルダを
​作成

 UnityにはTileMapという機能があります。グリッド上にタイルを配置することでステージを作ることができる機能です。

 RPGツクールやマリオメーカーあたりがイメージしやすいと思います。

(画像元サイト)

​ タイルマップに配置する素材(画像でいうブロックやコイン)をタイルパレットと言います。配布した素材にもタイルパレット画像が同梱されています。まずはタイルパレットの設定をして、タイルマップが使えるようにしてみましょう。

​ まずはタイルパレットを保存するためのPalletフォルダを作成してください。

2

タイルマップの

設定

 「Sprite」→「TileMap」内にある画像素材を選択してください。

 SpriteModeをMultuple、PixelsPerUnitを16に変更して、Applyをクリックしてください。

3

タイルパレットを

作成

 上部の「Window」→「2D」→「Tile Pallet」を選択して、タイルパレットウィンドウを開きます。

 「Create New Pallet」を選択してパレット名を入力してCreateをクリックします。

​ クリックすると保存先を聞かれるので、先ほど作ったPalletフォルダにしておきましょう。

 パレットを作成できたら、タイルパレット用の画像をドラッグ&ドロップしてください。パレットの作成先を聞かれますが、先ほどと同じようにPalletフォルダにしておきます。

​ タイルが1000枚以上あるため時間がかかりますが、完了するとパレットが表示されます。

4

タイルマップを
​追加

 ヒエラルキーから「2D Object」→「Tilemap」→「Rectangular」を選択してタイルマップを追加してください。

​ 四角形で構成されたタイルマップが作成されます。

5

仮の地面を削除

6

タイルパレットを
​使う

 Hexagonalは六角形のグリッド、Isometricは斜め四角形のグリッドになります。

​ 今回のゲームでは使いませんが、ぜひこれを使ったゲームも作ってみてください。

2_2_15
Unity Tips!

 今まで使っていた地面は必要なくなるので削除しておきましょう。

 タイルパレットを使いやすい場所に移動させてください。

 地面のタイルを選択して、タイルマップ上に地面を描いてみましょう。

 範囲塗りツールを選択すると広範囲を一気に塗ることができます。

​ 他にもスポイトや消しゴムツールも使えます。

2_2_11

 タイルを選んだ状態で { キー または } キー を押すと回転させることができます。Shift+{ キーを押すと左右反転させることができます。

​ 上り坂のタイルを反転させて下り坂にしてみましょう。

2_2_12

 短くていいので、タイルパレットを使った簡単なステージを作ってみましょう。

【注意すること】

・上り坂と下り坂を配置するようにしてみてください

​・パレット上部に様々な装飾がありますが、後で配置するので今は地形だけ作ってみてください。

7

当たり判定を追加

 地形が完成したら実行して遊んでみてください。

 …残念ながらユニティちゃんは地形を貫通して落下してしまいました。作成したタイルマップに当たり判定がないため、ユニティちゃんが着地できなかったようです。

 タイルマップにAddComponentから「Tilemap Collider 2D」を追加してください。

​ 地面として判定できるようにGroundタグもつけておきましょう。

8

当たり判定を調整

 これでタイルマップに当たり判定が追加されました。

 しかし、パレットの凹凸を律儀に反映しているため坂道がガタガタになってしまっています。このままでは壁と判定されてゲームオーバーになってしまう理不尽な坂道になってしまうので、当たり判定を修正しましょう(ゲームオーバー判定になるかは実行速度にもよります)

 タイルパレットに使用した画像を選択して、Sprite Editorを開いてください。

 Sprite Editorが開いたら、左上のSprite Editorと表示されているボタンをクリックして「Custom Physics Shape」に変更してください。

​ このモードではスプライトの当たり判定を手動で設定することができます。

 使用している坂道のタイルを選択して、範囲内でマウスをドラッグしてください。

 4つの点で構成された四角い当たり判定が作成されます。この点を動かして、坂道の当たり判定を設定していきましょう。

 左上以外の点は隅に移動させます。

​ 左上の点は必要ないので、選択した状態でDeleteキーを押して削除しましょう。

 坂の上部も同じように当たり判定を設定していきます。

 坂のつなぎ目の部分は当たり判定を作ってほしくないので、点を全て端に寄せておきます。

 緩やかな坂も同じように当たり判定を作成していきます。

 坂の当たり判定が作成できたら、右上のApplyをクリックしてください。

 Tilemap Collider 2Dをリセットすると、Sprite Editorで設定した当たり判定が反映されます。

 まだ当たり判定がおかしい場合は再度Sprite Editorを開いて調整してください。

9

当たり判定を合成

 Sprite Editorで当たり判定を調整してもまれにガタついてしまうことがあります。現在の状態ではタイルごとに当たり判定があるため、タイルの境界にひっかかってしまうようです。

 タイルマップに「Composite Collider 2D」を追加してください。これは当たり判定を合成してくれるコライダーです。

 Composite Collider 2Dを扱うためにはRigidBody 2Dが必要です。Composite Collider 2Dを追加した時に自動で追加されているはずです。

 ですが、このままではステージが重力を持って落下してしまいます。Body TypeをStatic(静的)にして動かないようにしてください。

10

​ちらつきを修正

 坂を登っている時などにタイルマップがちらついてしまう問題を修正しましょう。これはUnityが自動でアンチエイリアスをかけて、タイルの輪郭をぼかしてしまっていることが原因です。

 上部の「Edit」→「Project Settings…」を選択してください。

 Quality内にあるAnti Aliasingを「Disabled」に変更するとアンチエイリアスがかからなくなります。このゲームに限らず、ドット絵を扱うゲームであればとりあえず変更しておくとよいと思います。

11

地形を作る

 これで一通りの設定は完了しました。

 

 タイルマップを使って1ステージ分の地形を完成させてみましょう。

 後々ゴールを置くため、終点の地形は広めに取っておいてください。後からギミックや装飾を置けるように、道中も広めにスペースを取っておくと良いでしょう。

 ステージに高さや長さを出したい場合は、Main Cameraが移動できる範囲を調整してください。

2-2

2-2 地形を装飾

2-2 地形を装飾

1

タイルマップを
​追加する

 タイルパレットの上部には装飾に使えそうなパーツがあります。せっかくなので使ってみましょう。

 しかし、現在地形に使っているタイルマップに装飾を置いてしまうとTilemap Collider 2Dによって当たり判定が生成されてしまいます。

​ タイルマップは1つである必要はなく、用途によって分けることができます。装飾用にもう一つタイルマップを作成して、そこに装飾用のタイルを配置していきましょう。

​ Gridを右クリックして「2D Object」→「Tilemap」→「Rectangular」から新しいTileMapを作成してください。装飾用とわかりやすいように名前はDecorationにしておきます。

 作成したタイルマップの描画優先度を-1にしておきましょう。Order in Layerの値が大きい方が前面に描画されます。

2

描画の優先度を
​調整する

 ついでにプレイヤーの描画優先度を1にしておきます。これで装飾→地形→プレイヤーの順番で描画されます。

3

装飾を配置する

 Active Tilemapを地形ではなく装飾用タイルマップに変更してください。ここで接地対象のタイルマップを選ぶことができます。

 装飾用タイルマップに装飾を配置してみてください。Decorationタイルマップには当たり判定を設定していないので、ユニティちゃんが衝突することはありません。

​ Order in Layer(描画優先度)を-1にしているので、装飾はユニティちゃんの後ろに描画されます。ユニティちゃんの前面にも装飾を配置したい場合は、新しく前面装飾用のタイルマップを作り優先度を2以上にしてみてください。

​ ステージに装飾を配置できたらOKです。

 同じ装飾が並ぶと単調に見えるので、Shift+{ で左右反転させながらパーツを置いてみましょう。あまり置きすぎると後ほど設置するギミックが見えなくなるので、ほどほどで構いません。

2-3

2-3 背景を設定

2-3 背景を設定

1

​背景の設定変更

 いつまでも真っ青な背景のままでは寂しいので、背景を設置しましょう。

 「Sprite」→「BackGround」から背景画像を全て選択してください。そして、MeshTypeを「FullRect」にしてApplyをクリックしてください。これはループする画像を配置する時に必要な設定になります。

2

​背景を追加

 設定できたら背景に使いたい画像をシーン上にドラッグ&ドロップしてください。

 配布した背景素材の中でも前景と遠景があるので、まずは前景(手前側に表示するもの)を配置しましょう。

※ 1-1の最後で紹介したsuperpowers-asset-packsにも背景が100種類ほど同梱されています

3

優先度を設定する

 配置した画像に前景として区別できる名前をつけておきましょう。Order in Layer(描画優先度)を-4にしてプレイヤーや地形より後ろに表示されるようにします。

4

背景画像を
​横に敷き詰める

 スプライトのDrawModeを「Tiled」に変更してください。Widthの値を大きくすると左右でループする背景になります。ScaleやPositionも調整して、適当な場所に背景を設置しましょう。

5

遠景を追加する

 前景をコピー&ペーストして遠景も作成しましょう。Spriteを差し替えて、Order in Layerを前景よりもさらに後ろになるように設定します。

6

背景を
​スクロールさせる

 このままでも良いですが、背景とステージでスクロールがずれるようにして奥行きを出しましょう。

​ 新しくBG_Scrollスクリプトを作成して、以下のように入力してください。

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

 

public class BG_Scroll : MonoBehaviour
{
    PlayerMove m_playerMove;

 

    [SerializeField,Header("移動速度補正 大きいほど遅くなる)")]
    float Division = 0.0f;

 

    void Start()
    {
        // PlayerMoveを取得
        m_playerMove = GameObject.FindGameObjectWithTag("Player").GetComponent<PlayerMove>();
    }

 

    void Update()
    {
        // 移動量を計算
        float move = (m_playerMove.MoveSpeed / Division) * Time.deltaTime;
        // 移動する
        transform.Translate(new Vector3(move, 0.0f, 0.0f));
    }
}

 移動量の計算にプレイヤーの移動速度を組み込むことで、プレイヤーの移動速度を変更すると背景の移動速度も変わるようにしています。

​ コードが書けたら保存して、背景にアタッチしてください。前景と遠景でそれぞれ移動速度のパラメータを調整してください。

​ Division…前景 6 遠景 40

 これで移動中に背景が少しずれるようになりました。スクロールで背景の端が見えてしまう場合はWidthの値を大きくしてください。

​ ゲームオーバーになっても背景が移動し続けている問題がありますが、これは後ほど修正するので今は気にしないでください。

2-4

2-4 宝石を作成

2-4 宝石を作成

1

​宝石を配置する

 触れるとスコアが増える宝石を作成しましょう。

​ 「Sprite」→「Gimmick」内に宝石の素材があります。

2

​宝石の画像を
​分割する

 宝石の画像を全て選択して、SpriteTypeをMultipleに変更してください。変更したらApplyを忘れずにしておきましょう。

 使いたい宝石の画像を選んでSpriteEditorを開いてください。

 左上のSliceをクリックして、Typeを「Grid By Cell Count」に変更します。

 その下のColumn&RowをC=4 R=1にしてください。これで横4、縦1に画像がスライスされます。

 Sliceボタンをクリックして、右上のApplyボタンをクリックしてください。

 設定できたらSprite Editorを閉じてください。

 宝石の右側にある三角ボタンをクリックすると、画像が分割されていることがわかります。

3

シーンに宝石を

追加する

 Typeを「Automatic」にすると1枚の画像を自動で分割してくれます。

 全てのパーツをバラバラに取り込むより、1枚の画像を分割して使用した方が処理は軽くなります。素材の管理もしやすくなるので、ぜひSprite Editorを活用してみてください。

Unity Tips!

 1枚でアニメーションになっている画像は、シーン上に配置するだけで自動でアニメーションを作成してくれます。

 使いたい宝石の画像をシーン上にドラッグ&ドロップしてください。アニメーションを作成する場所を聞かれるのでAnimatonフォルダを指定して、名前をGemAnimatonにして保存しましょう。

4

宝石のサイズを
​調整する

 これで宝石が自動でアニメーションするようになりました。

​ デフォルトでは宝石がかなり小さいので、大きく調整してください。後でプレハブ化するため座標は適当で構いません。

5

アニメーションを
​調整する

 大きさを調整したら実行してみてください。宝石が自動でアニメーションしていることが確認できます。

 しかし、宝石の光るアニメーションの頻度が高く目がチカチカしてしまいます。アニメーションを調整しましょう。

 Animatonフォルダを開いてください。

 先ほど作成した宝石のアニメーションがありますが、ユニティちゃんのアニメーションと混ざってわかりにくいので、新規にGemAnimatonフォルダを作成してドラッグ&ドロップして分けておきます。

 GemAnimatonをクリックしてアニメーションウィンドウを開いてください。

​ 宝石が光る部分を囲んで選択し、右へ移動させてください。間隔はお好みで構いません。

6

相対移動で
​宝石を動かす

 これで完成でも良いのですが、宝石が全く動かないと背景に紛れて見えにくい気がします。宝石が上下に揺れるアニメーションを作りましょう。

​ ヒエラルキー内の宝石をクリックして、Add PropertyからPositionの項目を追加してください。

 アニメーションの移動に使う座標には絶対座標相対座標があります。

 絶対座標はオブジェクトの初期位置がどこであっても必ず設定した座標から始まり、設定した座標へ移動します。初期設定では絶対座標を使うようになっています。

​ 宝石は後ほど量産して大量に設置するのですが、この設定だとステージ中の宝石が一点の座標へ移動してしまいます。

相対移動

 相対座標はオブジェクトの初期位置を原点として扱います。オブジェクトがどこにあっても、指定した量だけ移動するようにできます。

​ これで宝石をステージ中に設置してもその場で上下に揺れるアニメーションを再生できるようになります。

2_2_66

 アニメーションが相対座標を使用するようにするには、AnimatorコンポーネントのApply Root Motionにチェックを入れる必要があります。

 初期位置→少し上の位置→初期位置 と移動させたいので、キーを3つ作成します。

 X=0,Y=0を基準に、上下に移動するアニメーションを設定してください。中間のキーのY座標はお好みで調整してください。

2_2_70
2_2_71

 ここまで設定できたら実行して、宝石がその場で上下に揺れていることを確認してみてください(宝石をコピー&ペーストで増やすとわかりやすいです)

7

宝石に当たり判定
​を追加する

 ユニティちゃんが宝石に触れたら取得できるようにしましょう。

 宝石にCircle Collider 2Dを追加します。

 ユニティちゃんが弾かれないようにIs Triggerにチェックを入れ、Radius(半径)を調整してください。取得用の当たり判定は少し大きめにした方が「取れたはずなのに取れなかった!」というストレスをプレイヤーに与えなくて済みます。

 宝石のコライダーが坂道判定に引っかからないように、LayerをIgnore Raycastにしておいてください(1-6で詳しく解説しています)

2_2_72_

8

宝石を取得する
​処理を書く

 Gemスクリプトを作成して、以下のように入力してください。今はユニティちゃんが触れたら宝石が消えるだけで、実際にスコアを加算する処理は後ほど書きます。

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

 

public class Gem : MonoBehaviour
{
    [SerializeField,Tooltip("獲得できるポイント")]
    int Point = 0;

 

    private void OnTriggerEnter2D(Collider2D collision)
    {
        // プレイヤーが衝突したら…
        if (collision.CompareTag("Player"))
        {
            // スコアを加算
            // (後で記述)

 

            // 自身を削除する
            Destroy(gameObject);
        }
    }
}

【プログラムの解説】

​・Tooltip はアトリビュートの一種で、インスペクター内で変数にカーソルを合わせた際に注釈を表示することができます。複雑な用途の変数に使うのがオススメです。

9

獲得ポイントを
​設定する

 コードが書けたら保存して、宝石にGemスクリプトをアタッチしてください。インスペクターで獲得できるポイントが設定できるので、お好みのポイント量にしておきましょう。

10

スコア管理用
​オブジェクト作成

 このままでは宝石は触れたら消えるだけのオブジェクトになってしまうので、ポイントを取得できるようにしましょう。

​ ヒエラルキーから空オブジェクトを作成してください。名前はGameにしておきます。

 GameオブジェクトのタグをGameControllerにします。

(このタグはUnityのデフォルトとして作成されているタグですが、特に用途は定められていません。ですが、スコアや進行状況の管理などをするオブジェクトに設定することを目的に用意されているようです)

11

スコアを格納する
​スクリプトを書く

 新しいスクリプトGameManagerを作成してください。

​ スクリプトの名前をGameManagerにするとアイコンが歯車になりますが、他のスクリプトと挙動は変わりません(アイコンが変わるのは恐らく仕様)

 GameManagerスクリプトに以下のように入力してください。

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

 

public class GameManager : MonoBehaviour
{
    [SerializeField]
    int Score = 0;
    // スコアを加算
    public void AddScore(int score)
    {
        Score += score;
    }
    // スコアを取得
    public int GetScore()
    {
        return Score;
    }

 

    void Start()
    {
        
    }

 

    void Update()
    {
        
    }
}

 コードが書けたら保存して、Gameオブジェクトにアタッチしてください。

 後は宝石に触れた瞬間にスコアを加算するだけです。

​ Gemスクリプトの先ほど // (後で記述) とした部分を埋めて、スコアを加算できるようにしてみてください。

【ヒント】GameオブジェクトにはGameControllerタグが設定されています!

 実行して、宝石を取得すると設定したポイント分のスコアが加算されることを確認してみてください。今はUIがないのでインスペクターでの確認になります。

 宝石は1種類でも構いませんが、今までの手順を踏むことで獲得ポイントが異なる宝石を作ることができます。Gemスクリプトはそのまま再利用できます。ぜひ宝石の種類を増やしてみてください。

2-5

2-5 宝石を並べる

2-5 宝石を並べる

1

宝石をプレハブ化

 作った宝石をステージにたくさん並べましょう。

 3Dアクションゲーム編のようにプレハブ化して1つずつ配置していってもよいのですが、100個も200個も宝石を置くとなると流石に大変です。2-1で地形のパーツをタイルパレットに並べて配置していきましたが、同じようにオブジェクトをタイルパレットにできる「GameObject Brush」という機能があります。これを使って宝石を配置していきましょう。

​ まずはPrefabフォルダを作成して、宝石を全てプレハブ化してください。

2_2_81

2

ギミック用の
​パレットを作成

 Tile Palletを開いて、「Create New Pallet」から新しいパレット「Gimmick」を作成してください。

2_2_82
2_2_83

 パレットの作成先は当然Palletフォルダにしましょう。

2_2_84

3

パレットに
​宝石を追加

 Palletフォルダ内にGimmickパレットが追加されるので、ダブルクリックしてパレット編集画面を開いてください。

2_2_85

 パレット内に先ほどプレハブ化した宝石をドラッグ&ドロップしていきましょう。

2_2_86

 追加した宝石をLayer1の子オブジェクトにしてください。また、宝石の座標もマスの中央になるように調整しましょう。

2_2_87

 パレットが完成したらシーンに戻りましょう。Scenesボタンを押すとパレット編集画面を閉じることができます。

2_2_86_

4

ギミック用
タイルマップ作成

 ヒエラルキー内のGridを右クリックして「2D Object」→「Tilemap」→「Rectangular」から新しいタイルマップを作成してください。名前は「Gimmick」にしておきます。

2_2_88

5

宝石を配置する

 Active Tilemap(設置対象のタイルマップ)をGimmickに変更します。その左下にある、使用するタイルパレットの種類もGimmickに変更してください。

 下部にある「Default Brush」を「GameObject Brush」に変更してください。

​ ここまで設定できたら、シーン上に宝石を設置してみましょう。地形を設置した時と操作は変わりません。

2_2_89

 Gimmickタイルマップの子オブジェクトを確認すると、宝石が作成されていることが確認できます。

 GameObject Brushはタイルを設置するのではなく、グリッドに沿ってオブジェクトを作成するブラシになります。

2_2_90

 作成されているのはプレハブなので、プロジェクト内のプレハブを編集すれば設置した宝石全てに変更を反映させることができます。

​ GameObject Brushを使って宝石を何個か配置してみてください。後でギミックも作成するため、ステージの最後まで宝石を設置する必要はありません。

2_2_91

評価テスト

2-6

2-6 槍を作成

2-6 槍を作成

評価テスト

1

槍を追加する

 触れるとゲームオーバーになる槍を作成しましょう。考え方は3Dアクションゲーム編でトゲを作った時と変わりません。

 槍もGimmickパレットに追加して、GameObject Brushで設置できるようにします。

​ 「Sprite」→「Gimmick」内にある槍の画像をシーン上にドラッグ&ドロップしてください。

2

レイヤーや

​当たり判定を設定

 インスペクターから槍の設定をします。たくさんの項目を一気に設定するので、順番にやっていきましょう。

・Layerを「Ignore Raycast」にする

・Scaleを調整する

・Order in Layerを-1にして、地形より後ろに表示されるようにする

​・Box Collider 2Dを追加

 → is Triggerにチェックを入れる

 → Sizeを調整する

   (宝石とは異なり、プレイヤーにマイナスになる当たり判定は小さめにした方が

   遊びやすいゲームになります)

3

槍のスクリプトを
​書く

 新しいスクリプト「DamageObject」を作成して、以下のように入力してください。青い部分は穴埋めなので埋めてみてください。

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

 

public class DamageObject : MonoBehaviour
{
    private void OnTriggerEnter2D(Collider2D collision)
    {
        // プレイヤーが衝突したら…
        if (collision.CompareTag("Player"))
        {
            // PlayerMove内のGameOver関数を呼び出す!
            (ここに入力)
        }
    }
}

 コードが書けたら保存して、槍にDamageObjectスクリプトをアタッチしてください。

​ 実行して、プレイヤーが槍に衝突するとゲームオーバーになることを確認してみてください。

4

槍のプレハブ化

 槍をプレハブ化して、シーン上にある槍は削除しておきましょう。Gimmickパレットへの追加は他のギミックを完成させてからまとめて行います。

2-7

2-7 矢を作成

2-7 矢を作成

1

矢を追加する

 飛んでくる矢を作成しましょう。発射用判定にプレイヤーが接触すると、矢の移動が開始します。

 「Sprite」→「Gimmick」内にある矢の画像をシーン上にドラッグ&ドロップしてください。

2

レイヤーや
​当たり判定を設定

 インスペクターから矢の設定をします。槍と同じく一気に設定するので、順番に行ってください。

・Layerを「Ignore Raycast」にする

・Scaleを調整する(Xを負の数にすると左右反転します)

​・Box Collider 2Dを追加

 → is Triggerにチェックを入れる

 → Sizeを調整する

   (槍と同じように小さめに調整

​・DamageObjectスクリプトをアタッチ

3

矢の移動開始
​判定を作成

 Arrowの子オブジェクトに空のゲームオブジェクトArrowStartを追加してください。これが矢の移動開始判定になります。

4

レイヤーや
​当たり判定を設定

 ArrowStartオブジェクトの設定をしてください。

・Layerを「Ignore Raycast」にする

・Positionを調整する(矢より大きく左に)

​・Box Collider 2Dを追加

 → is Triggerにチェックを入れる

 → Sizeを調整する

   (Yを大きくして、ステージを縦断するようにする

 ArrowStartオブジェクトの当たり判定にプレイヤーが衝突したら、親オブジェクトである矢が移動を開始するようにしましょう。

5

矢のスクリプトを
​書く

 Arrowスクリプトを作成して、以下のように入力してください。青い部分は穴埋めになります。

 これはプレイヤーが移動開始の指示を受けることで移動開始する、矢のスクリプトになります。

​【ヒント】もしプレイヤーのX座標がDeletePosX以下になったら、自身を削除しましょう!

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

 

public class Arrow : MonoBehaviour
{
    [SerializeField]
    float MoveSpeed = 5.0f;

 

    // 矢が削除される移動量
    const float DeleteMoveX = 50.0f;
    // 矢が削除されるX座標
    float DeletePosX = 0.0f;

 

    // 移動開始フラグ
    bool MoveStartFlag = false;

 

    void Update()
    {
        // 移動開始フラグが立っていたら移動する
        if (MoveStartFlag)
        {
            // 左へ向かって移動
            transform.Translate(new Vector3(-MoveSpeed * Time.deltaTime, 0.0f, 0.0f));
        }

 

        // 削除する座標に到達していたら自身を削除する
        (ここに入力)
    }

 

    // 移動開始関数
    public void MoveStart()
    {
        // 移動開始フラグを立てる
        MoveStartFlag = true;
        // 削除されるX座標を決める
        DeletePosX = transform.position.x - DeleteMoveX;
    }

}

6

発射判定用

スクリプトを書く

 コードが書けたら保存して、矢(Arrow)にArrowスクリプトをアタッチしてください。

​ 後はプレイヤーが衝突したタイミングでMoveStart関数を呼びだすだけになります。

​ ArrowTriggerスクリプトを作成して、以下のように入力してください。

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

 

public class ArrowTrigger : MonoBehaviour
{
    // 衝突した瞬間に呼ばれる
    private void OnTriggerEnter2D(Collider2D collision)
    {
        // プレイヤーが衝突したら…
        if (collision.CompareTag("Player"))
        {
            // 親オブジェクト(矢)の移動を開始する
            transform.parent.GetComponent<Arrow>().MoveStart();

            // 判定が終わったので自身を削除
            Destroy(gameObject);
        }
    }
}

 コードが書けたら保存して、矢の当たり判定(ArrowStart)にArrowTriggerスクリプトをアタッチしてください。

​ 実行して、矢が飛んでくるか確認してみてください。矢が飛んでくる速度が気に入らない人はArrowのMoveSpeedを調整しましょう。

​ ここまで実装できたら矢をプレハブ化して、ステージ上にある矢は削除してください。

​2-8

2-8 磁石アイテムの作成

2-8 磁石アイテムの作成

1

磁石アイテム追加

 触れるとしばらく宝石を引き寄せるようになる磁石アイテムを作成しましょう。編集するスクリプトは多いですが、コードはそこまで長くありません。

​ 「Sprite」→「Gimmick」内にあるアイテムの画像をシーン上にドラッグ&ドロップしてください。

2

レイヤーや

​当たり判定を設定

 インスペクターからアイテムの設定をしましょう。

・Layerを「Ignore Raycast」にする

・Scaleを調整する

​・Circle Collider 2Dを追加

 → is Triggerにチェックを入れる

 → Radiusを調整する

   (プレイヤーにプラスになる効果なので大きめに)

3

エフェクト画像を
​追加

 宝石を引き寄せる効果を発動するために、プレイヤーの子オブジェクトに判定を追加しましょう。

 「Sprite」→「Effect」内にあるMagnetの画像をシーン上にドラッグ&ドロップしてください。

4

​親子関係の設定

5

レイヤーや

​タグを設定

6

当たり判定の
​追加と調整

 ヒエラルキー内で追加した画像をユニティちゃんの子オブジェクトに設定してください。

 インスペクターからMagnetの設定をしてください。

​・新しいタグ「Magnet」を作成して設定する

 (タグの追加方法は1-5を参照)

・Layerを「Ignore Raycast」にする

・PositionとScaleを調整する

​・Colorを選択して、Aの値を調整する 100→50ほどでOK

​ AはAlpha(不透明度)の値で、小さくなるほど透明になります

 Circle Collider 2Dを追加して、Is Triggerにチェックを入れてください。

 Radiusを大きく調整しましょう。この判定に触れた宝石がプレイヤーに向かって移動するようになります。

7

アニメーションの
​作成

 このままでは少し寂しいので、エフェクトが回転するようにしましょう。スクリプトで実装してもよいですが、今回はアニメーションで実装します。

 Animatonフォルダ内にEffectAnimatonフォルダを作成してください。

 Animatonを作成して、名前をMagnetAnimationにしてください。

 MagnetAnimatonをヒエラルキー内のMagnetオブジェクトにドラッグ&ドロップしましょう。

 同フォルダ内にAnimatorControllerが自動で作成されればOKです

 MagnetAnimatonをダブルクリックしてAnimatonウィンドウを開いてください。

​ Magnetオブジェクトをクリックすると「Add Property」ボタンが押せるようになります。「Add Property」をクリックしてRotationの項目を追加してください。

 1つ目のキーはZ=0 、2つ目のキーはZ=360に設定してください。これでオブジェクトが一回転するようになります。

​ 2つ目のキーを左右に移動させることで回転速度を調整できます。お好みの速度に調整してください。

8

アニメーションの
​修正

 この状態で再生してみると、回転の最初と最後に減速がかかっていることが確認できます。デフォルトでは移動が滑らかになるように、Unity側が補正をかける仕様になっています。アニメーションが等速でループするようにしましょう。

 左下の「Curves」ボタンを押してカーブ編集に切り替えてください。グラフを見ると最初と最後が減速するように補正されています。

​ グラフの右端の点を右クリックして、Left Tangentを「Linear」に変更してください。

 左端の点を右クリックして、Right Tangentを「Linear」に変更してください。

 グラフが直線になればOKです。この状態で実行してみると、Magnetオブジェクトが等速で回転するようになっています。

 MagnetAnimatonのLoopTimeにチェックが入っていなかった場合はチェックを入れておいてください。

9

宝石の移動処理

 オブジェクトの設定ができたので、スクリプトを書いていきましょう。

 

 まずは宝石がプレイヤーへ向かって移動する処理を実装します。

​ Gemスクリプトを開いて、赤い部分のコードを追加してください。

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

 

public class Gem : MonoBehaviour
{
    [SerializeField,Tooltip("獲得できるポイント")]
    int Point = 0;

 

    [SerializeField]
    float MoveSpeed = 20.0f;

 

    // 引き寄せフラグ trueならプレイヤーへ向かって接近
    bool m_magnet = false;
    // プレイヤーのゲームオブジェクトを保存できるようにして
    // 何回も取得しなくてもいいようにする

    GameObject m_player;

 

    void Update()
    {
        if (m_magnet)
        {
            // プレイヤーへ向かって移動する
            Vector3 move = m_player.transform.position - transform.position;
            move.Normalize();
            move = move * MoveSpeed * Time.deltaTime;

 

            transform.Translate(move);

        }
    }

 

    private void OnTriggerEnter2D(Collider2D collision)
    {
        // プレイヤーが衝突したら…
        if (collision.CompareTag("Player"))
        {
            // スコアを加算
            GameObject.FindGameObjectWithTag("GameController").GetComponent<GameManager>().AddScore(Point);

 

            // 自身を削除する
            Destroy(gameObject);
        }
        // 磁力ゾーンが衝突したら…
        else if (collision.CompareTag("Magnet"))
        {
            if (m_magnet == false)
            {
                // プレイヤーを検索
                m_player = GameObject.FindGameObjectWithTag("Player");

 

                // プレイヤーへ向かって移動開始
                m_magnet = true;
            }
        }


    }
}

【プログラムの解説】

・目標とする座標へ向かって移動するための計算方法はk2Engineを使っていた時と変わりません。

 ① 目標地点 - 現在地点 を行い、現在地点から目標地点へ向かうベクトルを求める

​ ② 求めたベクトルを正規化(Normalize)して向きベクトルにする

​ ③ 向きベクトルに移動速度を乗算して移動量とする

​・プレイヤーへの移動を開始した瞬間にプレイヤーを検索してメンバ変数に保存しておくことで、何度も取得する手間を省くことができます。

 GameObject.FindGameObjectWithTag("Player") をUpdateで毎フレーム行っても構いません。ですが、小さな負荷が積み重なるとゲームが重くなるリスクがあるため、Update内でGameObjectの検索を毎フレーム行うのは控えた方が良いでしょう。

 ここまで入力できたら保存して、実行してみてください。Magnetの当たり判定に触れた宝石がプレイヤーへ向かって移動することが確認できます。

​ 移動速度が遅い場合は宝石のプレハブを選択してMoveSpeedを調整してください。同じコンポーネントを持つプレハブは、一括選択することでまとめて値を変更できます。

10

アクティブの切替

 Unityにはオブジェクトをアクティブにしたり、非アクティブにしたりする機能があり、オブジェクト名の左側にあるチェックボックスでオブジェクトのアクティブを切り替えることができます

​ Magnetオブジェクトを非アクティブにしましょう。

 チェックが外れて非アクティブになったオブジェクトは透明になり、アタッチされているコンポーネントも全て無効になります。Updateなども全て止まります。

​ 普段はMagnetオブジェクトを非アクティブにしておいて、アイテムを取得したらしばらくの間アクティブになるようにしましょう。アクティブの状態もスクリプトから変更可能です。

 非アクティブになっているオブジェクトはFindで取得できないので注意してください。

​ また、非アクティブにしてもオブジェクトは完全に消えたわけではないので、本当に不要になったオブジェクトは削除するようにしましょう。ゲームが重くなる原因になります。

Unity Tips!

11

アイテムの効果を
​管理する処理

 PlayerMoveでアイテムの取得状況を管理しても良いのですが、わかりにくくなってしまうので新しいスクリプトを作成しましょう。

​ PlayerItemスクリプトを作成して、以下のように入力してください。

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

 

public class PlayerItem : MonoBehaviour
{
    [SerializeField, Header("磁石アイテムの有効時間")]
    float MagnetLimit = 3.0f;

    [SerializeField, Header("磁石引き寄せ判定オブジェクト")]
    GameObject MagnetObject;

 

    // 磁石アイテムタイマー
    float m_magnetTimer = 0.0f;

 

    void Update()
    {
        // タイマーが0より大きい(磁石アイテム有効時間中)
        if (m_magnetTimer > 0.0f)
        {
            m_magnetTimer -= Time.deltaTime;
            // 効果時間が終了
            if (m_magnetTimer <= 0.0f)
            {
                // 引き寄せ判定オブジェクトを非アクティブにする
                MagnetObject.SetActive(false);
            }
        }
    }

 

    // 磁石アイテムを取得した時に呼ぶ関数
    public void GetMagnetItem()
    {
        // 取得したため引き寄せ判定用オブジェクトをアクティブにする
        MagnetObject.SetActive(true);

 

        // タイマーを設定
        m_magnetTimer = MagnetLimit;
    }

 

}

【プログラムの解説】

・GameObjectクラスのSetActive関数は前述したオブジェクトのアクティブ、非アクティブを切り替える関数になります。

 引数にtrueを入れるとアクティブに、falseを入れると非アクティブになります。

 コードが書けたら保存して、ユニティちゃんにアタッチしてください。

​ ユニティちゃんのインスペクター内に SerializeField のアトリビュートを設定した変数が表示されています。MagnetObject にはヒエラルキーから​Magnetオブジェクトをドラッグ&ドロップしてください。

12

アイテムの処理

 最後にプレイヤーがアイテムの当たり判定に衝突したら、先ほどのGetMagnetItem関数を呼び出してMagnetオブジェクトをアクティブにしましょう。

​ MagnetItemスクリプトを作成して、以下のように入力してください。青い部分は穴埋めです。

 このスクリプトを書けるようになっていれば、他のゲームでもアイテムを簡単に実装できます。しっかり書き方を練習しましょう!
​【ヒント】DamageObjectスクリプトを参考にしよう!

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

 

public class MagnetItem : MonoBehaviour
{
    // ① 自分に何かが触れた瞬間に実行
    private void (ここに入力)(Collider2D collision)
    {
        // ② 衝突したオブジェクトのタグがPlayerなら…

        if ((ここに入力))
        {
            // ③ 磁石アイテムの取得処理
            (ここに入力)

            // ④ 自身を削除する
            (ここに入力)
        }
    }
}

 コードが書けたら保存して、磁石アイテムにアタッチしてください。

​ これでプレイヤーがアイテムを取得するとMagnetオブジェクトがアクティブになり、一定時間が経過すると非アクティブになります。

13

アニメーションを
​追加

 アイテムはこれで完成でも良いのですが、アイテムが背景に紛れないようにアニメーションを追加してみましょう。

 Animatonフォルダ内にItemAnimatonフォルダを追加してください。MagnetItemアニメーションを作成して、Itemオブジェクトにドラッグ&ドロップしましょう。

 Itemオブジェクトを選択してAdd Propertyから好きな項目を追加して自由にアニメーションを作ってみてください。

​ Positionを操作する場合は相対移動になるように、AnimatorコンポーネントのApply Root Motionにチェックを入れてください(2-4参照)

 サンプルゲームでは一定間隔でアイテムの画像を拡大・縮小しています。

14

アイテムを
プレハブ化する

 アニメーションが完成したら、ItemオブジェクトをPrefabフォルダ内にドラッグ&ドロップしてプレハブ化しましょう。

​ プレハブ化できたらシーン内にあるオブジェクトは削除してください。

 これでこのLessonで実装するギミックは終了ですが、今までの知識を応用してぜひオリジナルのギミックも作ってみてください。

2-9

2-9 Gimmickパレットの設定

2-9 Gimmickパレットの設定

1

プレハブの追加

 今まで作ったギミックである槍、矢、磁石アイテムをGimmickパレットに設定してGameObject Brushで設置できるようにしましょう。

​ もし他に作成したギミックがあるなら同じ手順で設定してください。

​ Palletフォルダ内にあるGimmickパレットをダブルクリックして開いてください。

​ Gimmickパレット内に今まで作ったギミックのプレハブをドラッグ&ドロップしましょう。

2

ギミックの調整

 追加したギミックをLayer1の子オブジェクトにしてください。

​ ギミックの座標もグリッドの中央になるように調整しましょう。

3

ギミックの配置

 Gimmickパレットの設定ができたらScenesボタンを押してステージの画面に戻ってください。

​ Active TileMap(設置対象のタイルマップ)とその下の使用するタイルパレットを「Gimmick」に変更してください。

​ 下部の使用するブラシが「Default Brush」になっていたら「GameObject Brush」に変更してください。

​ これでギミックを設置できるようになりました。設置したいギミックを選択して、タイルマップ内に設置してみましょう。

2-10

2-10 下から登れる足場

2-10 下から登れる足場

1

タイルマップの
​追加

 最後におまけとして「下からはジャンプで登れるけど、上からは落ちない足場」を実装してみましょう。

​ 一見難しそうに見えるかもしれませんが、Unityでは「Effector 2D」を活用することで簡単に実装できます。

 まずは下から登れる足場専用のTileMapを追加しましょう。

​ ヒエラルキー内のGridを右クリックして「2D Object」→「Tilemap」→「Rectangular」から新しいタイルマップを作成してください。名前はStage_Backにしておきます。

2

足場の追加

 設置対象のTileMapをStage_Backに、使用するPalletをStageに変更しましょう。

 下部の使用ブラシもDeleteBrushに変更してください。

​ パレットの右上に下から登れそうな足場があるので設置してみましょう。

3

タグとレイヤーの

設定

 タイルマップを選択してTagを「Ground」、Layerを「Ignore Raycast」に変更してください。

4

当たり判定の追加

 「Tilemap Collider 2D」​を追加して当たり判定を設定してください。

5

一方通行の
​設定をする

 Tilemap Collider 2D の「Used By Effector」にチェックを入れてください。

 Add Componentから「Platform Effector 2D」を追加してください。これは当たり判定が指定した角度外からの衝突は無視するようになるコンポーネントです。

​ Surface Arcの値を変更すると角度を調整できます。デフォルトでは180になっていますが、100あたりに調整してください。

 これで下から登れる足場の完成です。

 

 足場の当たり判定の形はデフォルトで大丈夫なはずですが、気に入らない場合はCustom Physics Shape機能を使って手動で当たり判定を調整してください。

​ またレイヤーをIgnore Raycastに変更しているため、坂道判定が無効になっています。現在の仕様では下から登れる足場に坂道は使用できないので注意してください。

1-0

2-11

1

ステージを作る

 坂や崖に当たり判定の端が衝突した場合、プレイヤーが左右へ大きく吹っ飛ぶ現象が起こることがあります。

​ 気になる方はPlayarMoveスクリプトのFixedUpdate関数内に、X軸への力を0にする以下の処理を追加してください。FixedUpdate関数内であればどこでもOKです。

Unity Tips!
2-11 ステージの作成

2-11 ステージの作成

 今までのLessonを参考にしながら、タイルマップを使ってステージを一通り作ってみてください。

 

・ステージ1なのであまり難しくしすぎないようにしましょう

・宝石を使ってプレイヤーを誘導するようにすると遊びやすくなります

 ギミックの種類が少なく物足りない人はぜひオリジナルのギミックを追加してみましょう。今までの解説で作れるオススメのギミックを解説します。

 画像素材は検索して集めたり、Lesson1-1で紹介したsuperpowers-asset-packsを使用すると良いでしょう。

【トランポリン】

 プレイヤーが上に乗った瞬間に、プレイヤーに対して上方向に力を加えるだけで作れます。Unityの初心者が最初に作るのにオススメのギミックです。

 ジャンプの処理や宝石の処理を参考にしてみてください。

​【スイッチと扉】

 スイッチを押すと扉が開き、隠しルートの先でスコアを稼げる…といったギミックです。完全に進路を封鎖して、スイッチを押さないと進めないステージにしても面白いでしょう。

​ ランゲームは自動で進む都合上プレイヤーの意思を反映しにくいので、ゲーム体験の自由度を高めるためにもぜひ実装してみましょう。

【無敵アイテム】

 磁石アイテムと同じような要領で作ることができます。

​ 槍などを並べて「無敵状態でないと入れない場所」を作るのも良いかもしれません。

 他にも槍を地面から生えてくるようにしてみたり、プレイヤーに近づくと透明になる矢を作ってみたり、既存のギミックを拡張するのもオススメです。

​ 自分で調べて実装するのが上達の一番の近道です。ぜひオリジナルのギミックを使った自分だけのステージを完成させてみてください。

Unity Tips!

 ステージが完成したらLesson2は終了です。

​ 次のレッスンではゲームクリア、ゲームオーバーといった「ゲームのルール」を一通り実装していきましょう。

まとめ

・画像をグリッド状に分割したタイルパレットをタイルマップに配置することで、簡単に地形を作ることができる

・アニメーションには「絶対座標」と「相対座標」の移動がある

  絶対座標…初期位置に関係なく指定した座標を使用する

  相対座標…初期位置を基点として移動する

​・アニメーションはデフォルトでは絶対座標を使用するが、Animatorコンポーネントの「Apply Root Motion」にチェックを入れることで、相対座標を使用するように設定できる

評価テスト

評価テスト

河原電子ビジネス専門学校
​ゲームクリエイター科

bottom of page