壁に激突するロケットのイラスト

Unityでアクションゲームを作っていると、オブジェクトの移動範囲を制限したい時がよくあります。

 

たとえば、「プレイヤーが画面外に出ない」ようにしたり、「ある範囲内でのみ、カメラが追従する」というようなときに使えます。

今回は、オブジェクトの移動できる範囲を制限する簡単なスクリプトを紹介します。

はじめに

 

プレイヤーの移動範囲を制限しないとプレイヤーが画面の外にはみ出てしまう危険性があります。

そういった時に、コライダーなどを使えば壁を作ったりすることができるのですが、コライダーはすり抜けたりするので、場合によっては使いたくありません。

 

コライダーを使わずに移動制限を実装してみよう

 

そこで使えるコードが「Mathf.Clamp」です。

まずは、このコードの使い方について説明していきます。

 

Mathf.Clampとは

 

Mathf.Clampの基本的な形は、Mathf.Clamp(value, min, max);というような使い方をします。

valueに移動制限をしたいオブジェクトの座標などを記入します。

 

min と max にはそのまま最小値と最大値を入れればOKです。

 

Mathf.Clamp(Player.transform.x, Min.transform.position.x, Max.transform.position.y);

 

このようにすることでプレイヤーのx座標はMinのx座標より大きく、Maxのx座標より小さい値の中でしか動けないという意味になります。

 

このコードを transform.positionに入れれば良いです。

これだけ見ると簡単ですが、実際にプレイヤーなどのオブジェクトを指定していくとなかなか長いコードになります。

 

以下から説明していきます。

 

具体的な使い方

 

では実際にコードを組み込んだ場合を見ていこう

 

以下のようなコードを使うと、Playerのx座標は「wall_Leftからwall_Rightまで」で移動制限し、y座標は「wall_Bottomからwall_Topまで」で移動を制限します。

 

using UnityEngine;
using System.Collections;

public class PlayerController : MonoBehaviour {

    GameObject Player;
    GameObject wall_Left;
    GameObject wall_Right;
    GameObject wall_Bottom;
    GameObject wall_Top;

    bool MoveRight;
    bool MoveLeft;

    // Use this for initialization
    void Start () {

        Player = GameObject.Find ("Player");
        wall_Left = GameObject.Find ("Wall Left");
        wall_Right = GameObject.Find ("Walll Right");
        wall_Bottom = GameObject.Find ("Wall Bottom");
        wall_Top = GameObject.Find ("Wall Top");

    }

    // Update is called once per frame
    void Update () {

        if (Input.GetKey (KeyCode.RightArrow)) {
            MoveRight = true;
            MoveLeft = false;
        } else if (Input.GetKey (KeyCode.LeftArrow)) {
            MoveLeft = true;
            MoveRight = false;
        }else {
            MoveRight = false;
            MoveLeft = false;
        }
    Player.transform.position = (new Vector3(Mathf.Clamp(Player.transform.position.x, wall_Left.transform.position.x, wall_Right.transform.position.x),
            Mathf.Clamp(Player.transform.position.y, wall_Bottom.transform.position.y, wall_Top.transform.position.y),
            Player.transform.position.z));

    }
    void FixedUpdate(){

        if (MoveRight) {
            Player.GetComponent ().velocity = (transform.up * 2);
            Player.transform.Rotate (new Vector3 (0, 0, -5));
        } else if (MoveLeft) {
            Player.GetComponent ().velocity = (transform.up * 2);
            Player.transform.Rotate (new Vector3 (0, 0, 5));
        } else {
            Player.GetComponent ().velocity = (transform.up * 0);
        }
    }
}

 

※わかりやすいようにプレイヤーをどのように動かしているか、というコードも一緒に書いてあります。

移動制限をしているコードは以下の部分のみです。

 

Player.transform.position = (new Vector3(Mathf.Clamp(Player.transform.position.x, wall_Left.transform.position.x, wall_Right.transform.position.x),
Mathf.Clamp(Player.transform.position.y, wall_Bottom.transform.position.y, wall_Top.transform.position.y),Player.transform.position.z));

 

このコードでMathf.Clampを使っているのがわかると思います。

見てわかる通り、x座標とy座標をそれぞれ制限してしまうと、とても長いコードになってしまいます。

 

そういった時は、先にwall_Leftなどのpositionを定義してから記入すると綺麗に書くことができます。

以下を参考にして書き換えましょう。

 

using UnityEngine;
using System.Collections;

public class PlayerController : MonoBehaviour {

    GameObject Player;
    GameObject wall_Left;
    GameObject wall_Right;
    GameObject wall_Bottom;
    GameObject wall_Top;

    Vector3 LeftPos;
    Vector3 RightPos;
    Vector3 BottomPos;
    Vector3 TopPos;

    // Use this for initialization
    void Start () {

        Player = GameObject.Find ("Player");
        wall_Left = GameObject.Find ("Wall Left");
        wall_Right = GameObject.Find ("Walll Right");
        wall_Bottom = GameObject.Find ("Wall Bottom");
        wall_Top = GameObject.Find ("Wall Top");

    LeftPos = wall_Left.transform.position;
        RightPos = wall_Right.transform.position;
        BottomPos = wall_Bottom.transform.position;
        TopPos = wall_Top.transform.position;

    }

    // Update is called once per frame
    void Update () {

               Player.transform.position = (new Vector3 (Mathf.Clamp (Player.transform.position.x, LeftPos.x, RightPos.x),
               Mathf.Clamp (Player.transform.position.y, BottomPos.y, TopPos.y), transform.position.z));

    }
}

 

このようにStart()で先に座標を指定しているのでMathf.Clampが若干短くまとまっているかと思います。

 

実際に確認

 

コードが書けたら実際に確認してみましょう。

プレイヤーが制限した範囲の外に出ないようになっていれば成功です。

 

Point
コライダーを設定していないのに壁があるような挙動になる

 

ですが、あくまでオブジェクトの中心が座標として指定されているので、中心より内側で制限したい時は

 

Mathf.Clamp(Player.transform.x, LeftPos.x + 10, RightPos.x + 10));

 

などのようにしてみると範囲制限できるので、調整してみてください。

(Spriteを使っている場合、SpriteEditorで中心点を変えるというのも良いかもしれません)

 

Point
数式を使って移動制限の範囲を指定することも可能

 

私の場合、以下のようになりました。

(コライダーは入れていません。)

 

20170513171633

 

画像だと伝わりにくいけど、ロケットが壁にぶつかっているように見えるね

 

まとめ

 

今回は、プレイヤーの移動制限で説明しましたが、本来はカメラの移動などでよく使われます。

カメラも今回の方法と同じようにすれば、AからBの範囲で制限することができるようになります。

 

Point
Mathf.Clampはカメラにも使える!!

 

便利な使い方はプレイヤーを追従するようにしながら、「プレイヤーが端まで動いたらカメラが追いかけないようにする」というようなものです。

また、「最大の値がどこまででも良い」というような時には以下のように書きましょう。

 

Player.transform.position = (new Vector3 (Mathf.Clamp (Player.transform.position.x, LeftPos.x, Mathf.Infinity))

 

Mathf.Infinityと書くことで、最大値の座標は際限なく、最小値の範囲だけを制限することができます。

今回の方法はとても便利なので是非とも活用していきましょう。

 

 

ではまた。

過去にレビューしたアイテム