読者です 読者をやめる 読者になる 読者になる

自分用めも

初心者ちっくなプログラムネタを中心に、自分用の覚え書きをメモっていくための場所です。

Unityでスプライトドラッグ時に移動制限をつける

Unity 5.3.1f1 (64-bit)。



1. 前提:移動制限方法

公式のチュートリアルが参考になります。
第09回 プレイヤーの移動制限と様々な修正 · unity3d-jp-tutorials/2d-shooting-game Wiki · GitHub

Mathf.Clampを使います。

//移動先座標
Vector2 position = ドラッグ中の座標;

//画面左下、右上のワールド座標をビューポートから取得
Vector2 min = Camera.main.ViewportToWorldPoint(new Vector2(0, 0));
Vector2 max = Camera.main.ViewportToWorldPoint(new Vector2(1, 1));

//移動先を補正する
position.x = Mathf.Clamp(position.x, min.x, max.x);
position.y = Mathf.Clamp(position.y, min.y, max.y);

//補正済みの座標を反映
this.transform.position = position;

2. スプライトが画面より小さい場合

前提の移動制限方法ですと、補正の基準はスプライトの中心座標になります。
そのままですと画面恥までドラッグした場合に、
スプライトが半分画面外に出てしまうため、制限範囲を補正します。

スプライトが画面より小さい場合は、単にはみ出る分(スプライトの半分のサイズ)を
足し引きしてやればokです。

//スプライトのサイズを取得
Vector2 size = this.GetComponent<SpriteRenderer>().bounds.size

//画面左下、右上のワールド座標をビューポートから取得
Vector2 min = Camera.main.ViewportToWorldPoint(new Vector2(0, 0));
Vector2 max = Camera.main.ViewportToWorldPoint(new Vector2(1, 1));

//範囲をスプライトサイズを考慮して補正する
min.x += size.x / 2;
max.x -= size.x / 2;
min.y += size.y / 2;
max.y -= size.x / 2;

3. スプライトが画面より大きい場合

こっちが問題で、かなりハマりました。メモしとこうと思うレベルで。

例えば画面よりでかいワールドマップをドラッグして動かす際に、
ワールドマップの端まで来たらそれ以上スクロールさせないようにするイメージです。

考え方としては単純で、画面からはみ出た分 = (マップサイズ - 画面サイズ)ですので、
それで補正してやればいいだけです。
だけなのですが…罠がありハマりました。

//スプライトのサイズを取得
Vector2 size = this.GetComponent<SpriteRenderer>().bounds.size

//画面左下、右上のワールド座標をビューポートから取得
Vector2 min = Camera.main.ViewportToWorldPoint(new Vector2(0, 0));
Vector2 max = Camera.main.ViewportToWorldPoint(new Vector2(1, 1));

//max座標からスクリーンサイズを算出
//ビューポートの場合基点は左下で座標0となるが
//ワールド座標の場合は中心が座標0となる為、maxを2倍しないと画面サイズにならない
//Screen.widthを変換しても同じく座標なので、同様に2倍する必要がある
var screenWorldWidth = max.x * 2;
var screenWorldHeight = max.y * 2;

//範囲をスプライトサイズを考慮して補正する
min.x += (screenWorldWidth / 2) - (size.x - screenWorldWidth) / 2;
max.x -= (screenWorldWidth / 2) - (size.x - screenWorldWidth) / 2;
min.y += (screenWorldHeight / 2) - (size.y - screenWorldHeight) / 2;
max.y -= (screenWorldHeight / 2) - (size.y - screenWorldHeight) / 2;

以上、わかってる方には常識かもと思いますが、
ビューポートとワールド座標の"0"の違いに思い当たらず、
だいぶハマってしまったと言うメモでした…