シェアする

Unity オブジェクトの移動範囲を制限するMathf.Clampの使い方

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

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

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

はじめに

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

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

そこで使えるコードが「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が若干短くまとまっているかと思います。

実際に確認

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

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

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

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

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

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

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

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

まとめ

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

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

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

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

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

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

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

ではまた。