マウスのドラッグ操作でオブジェクトを動かす方法

開発のTips

1.概要
 マウスはスクリーン座標、オブジェクトはワールド座標のため、マウスの動きに合わせてオブジェクトを動かすためにはマウスクリックしたときのスクリーン座標とオブジェクトのワールド座標のオフセットを保持し、マウスの動きに合わせて、オブジェクトの位置を「オフセット+マウスの移動量」で動かす必要があります。また、オブジェクトはワールド座標のため、ここで求めたオブジェクトの位置をスクリーン座標からワールド座標に変換する必要があります。

 ここで、カメラが写すワールド座標とマウスが動くスクリーン座標の関係について、カメラの中心に対応するスクリーン座標を取得することで確認してみます。
 下記のスクリプトをMainCameraのオブジェクトにアタッチすることで、スクリーン座標の原点はDisplayの左下の点であることが確認できます。
 画面サイズのX軸:1080ピクセル(横)、Y軸:1920ピクセル(縦)の上でカメラの中心位置はログに示す通り、X軸:540ピクセル、Y軸:960ピクセルとなります。

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

public class Kamera1 : MonoBehaviour
{
    private Camera mainCamera; // メインカメラの参照


    // Start is called before the first frame update
    void Start()
    {
        mainCamera = Camera.main; // メインカメラを取得
    }

    // Update is called once per frame
    void Update()
    {
        Vector3 cameraScreenCenter = mainCamera.WorldToScreenPoint(mainCamera.transform.position);
        Debug.Log("Camera Screen Center: " + cameraScreenCenter);
    }
}

2.スクリプト
2.1 変数の定義
・private Vector3 offset
 マウスがクリックされたときのマウス位置とオブジェクト位置の相対的な位置(オフセット)を記憶するための変数で、ドラッグ中のマウスとオブジェクトが一緒に動くようにします。
・private Camera mainCamera
 シーン内に存在するMainCameraタグが付けられたカメラのオブジェクトを保存するための変数です。
・private Rigidbody2D rb2D
 オブジェクトのRigidbody2Dコンポーネントを参照するための変数です。

2.2 メソッドの定義
・Startメソッド
 初期化処理では、メインカメラとオブジェクトにアタッチされたRigidbody2Dを取得します。

//mainプロパティはMainCameraタグが付けられたカメラのオブジェクトを返します
mainCamera = Camera.main;
//オブジェクトにアタッチされたRigidbody2Dを取得します
rb2D = GetComponent<Rigidbody2D>();

・OnMouseDown()
 マウスの左クリックがオブジェクト上で押された際に呼び出され、ワールド座標でマウス位置とオブジェクトの位置の相対位置(オフセット)を求めます。

// マウス位置とオブジェクト位置の相対位置を計算
 Vector3 mousePosition = GetMouseWorldPosition();
 offset = transform.position - mousePosition;

・OnMouseDrag()
 マウスの移動に合わせてオブジェクトを移動します。

// マウスのワールド座標を取得します
Vector3 mousePosition = GetMouseWorldPosition();
// マウスの位置にオフセットを加えてオブジェクトの位置を求めます
Vector3 newPosition = mousePosition + offset;
// オブジェクトを移動します
rb2D.MovePosition(new Vector2(newPosition.x, newPosition.y));

・GetMouseWorldPosition()
 マウスの位置をスクリーン座標からワールド座標に変換します。

// 静的クラスInputのプロパティmousePositionを使って現在のマウス位置を取得
Vector3 mouseScreenPosition = Input.mousePosition;
// カメラのZ座標の絶対値を取得(3D空間におけるワールド座標への変換を行うときに必要)
mouseScreenPosition.z = Mathf.Abs(mainCamera.transform.position.z);
// マウスのスクリーン座標をカメラの視点を基準にしたワールド座標に変換
return mainCamera.ScreenToWorldPoint(mouseScreenPosition);

 マウスのドラッグ操作でオブジェクトを動かすためにオブジェクトにアタッチするスクリプトの例を下記に示します。

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

public class DraggableObject : MonoBehaviour
{
    private Vector3 offset; // マウスとオブジェクトの相対位置
    private Camera mainCamera; // メインカメラの参照
    private Rigidbody2D rb2D; // Rigidbody2Dの参照
    // Start is called before the first frame update
    void Start()
    {
        mainCamera = Camera.main; // メインカメラを取得
        rb2D = GetComponent<Rigidbody2D>(); // Rigidbody2Dを取得
    }

    // Update is called once per frame
    void Update()
    {
        
    }
    private void OnMouseDown()
    {
        // マウス位置とオブジェクト位置の相対位置を計算
        Vector3 mousePosition = GetMouseWorldPosition();
        offset = transform.position - mousePosition;
    }
        private void OnMouseDrag()
    {
        // マウスのワールド位置にオフセットを加えてオブジェクトを移動
        Vector3 mousePosition = GetMouseWorldPosition();
        Vector3 newPosition = mousePosition + offset;
        rb2D.MovePosition(new Vector2(newPosition.x, newPosition.y));
    }
    private Vector3 GetMouseWorldPosition()
    {
        // マウス位置をスクリーン座標からワールド座標に変換
        Vector3 mouseScreenPosition = Input.mousePosition;
        mouseScreenPosition.z = Mathf.Abs(mainCamera.transform.position.z);
        return mainCamera.ScreenToWorldPoint(mouseScreenPosition);
    }
}

タイトルとURLをコピーしました