UIからオブジェクトをUnityでドラッグアンドドロップして、配置およびドラッグします



Unity Drag Drop Objects From Ui Place



要件:UIをクリックして、シーンに3Dオブジェクトを生成します。オブジェクトはマウスで移動します。配置後、オブジェクトをもう一度ドラッグして位置を変更できます。以下に示すように、小さなデモを作成しました。

画像

一般的な考え方:



  • 光線衝突検出
  • オブジェクト空間座標変換(ワールド座標->画面座標、画面座標->ワールド座標)

まず、UIのマウスリスニングイベントを追加して3Dオブジェクトを生成します。スクリプトは、次のとおりです。

SelectImage.cs



using System.Collections using System.Collections.Generic using UnityEngine using UnityEngine.EventSystems public class SelectImage : MonoBehaviour,IPointerDownHandler{ //Prefabs that need to be instantiated public GameObject inistatePrefab //Instantiated object private GameObject inistateObj // Use this for initialization void Start () { if (inistatePrefab==null)return //Instantiate prefab inistateObj=Instantiate(inistatePrefab) as GameObject inistateObj.SetActive(false) } //Realize the mouse down interface public void OnPointerDown(PointerEventData eventData) { inistateObj.SetActive(true) //Pass the object that needs to be instantiated to the manager SelectObjManager.Instance.AttachNewObject(inistateObj) } }

スクリプトをUIオブジェクトにマウントします。

配置のドラッグのロジックを処理するオブジェクト配置マネージャーを作成します。

SelectObjManager.cs



using System.Collections using System.Collections.Generic using UnityEngine public class SelectObjManager : MonoBehaviour { private static SelectObjManager _instance public static SelectObjManager Instance { get { return _instance } } //The length of the z axis of the object from the camera public float _zDistance = 50f //The scaling factor of the object public float _scaleFactor=1.2f //Ground level public LayerMask _groundLayerMask int touchID bool isDragging = false bool isTouchInput = false //Whether it is a valid placement (True if placed on the ground, otherwise False) bool isPlaceSuccess = false //The current object to be placed public GameObject currentPlaceObj = null //The offset of the coordinate on the Y axis public float _YOffset=0.5F void Awake () { _instance = this } void Update () { if (currentPlaceObj == null) return if (CheckUserInput()){ MoveCurrentPlaceObj() }else if (isDragging){ CheckIfPlaceSuccess() } } /// ///Detect user's current input /// /// bool CheckUserInput () { #if !UNITY_EDITOR&&(UNITY_ANDROID||UNITY_IOS) if (Input.touches.Length > 0) { if (!isTouchInput) { isTouchInput = true touchID = Input.touches[0].fingerId return true } else if (Input.GetTouch (touchID).phase == TouchPhase.Ended) { isTouchInput = false return false } else { return true } } return false #else return Input.GetMouseButton (0) #endif } /// ///Make the current object follow the mouse /// void MoveCurrentPlaceObj () { isDragging = true Vector3 point Vector3 screenPosition #if !UNITY_EDITOR&&(UNITY_ANDROID||UNITY_IOS) Touch touch = Input.GetTouch (touchID) screenPosition = new Vector3 (touch.position.x, touch.position.y, 0) #else screenPosition = Input.mousePosition #endif Ray ray = Camera.main.ScreenPointToRay (screenPosition) RaycastHit hitInfo if (Physics.Raycast (ray, out hitInfo, 1000, _groundLayerMask)) { point = hitInfo.point isPlaceSuccess = true } else { point = ray.GetPoint (_zDistance) isPlaceSuccess = false } currentPlaceObj.transform.position = point+new Vector3(0,_YOffset,0) currentPlaceObj.transform.localEulerAngles = new Vector3 (0, 60, 0) } /// ///Make an object at a specified position /// void CreatePlaceObj(){ GameObject obj=Instantiate(currentPlaceObj) as GameObject obj.transform.position=currentPlaceObj.transform.position obj.transform.localEulerAngles=currentPlaceObj.transform.localEulerAngles obj.transform.localScale*=_scaleFactor //Change the Layer of this object to Drag for subsequent drag detection obj.layer=LayerMask.NameToLayer('Drag') } /// ///Check if the placement is successful /// void CheckIfPlaceSuccess(){ if (isPlaceSuccess){ CreatePlaceObj() } isDragging=false currentPlaceObj.SetActive(false) currentPlaceObj=null } /// /// Pass the object to be created to the current object manager /// /// public void AttachNewObject(GameObject newObject){ if (currentPlaceObj){ currentPlaceObj.SetActive(false) } currentPlaceObj=newObject } }

スクリプトには詳細なコメントがあるので、あまり説明しません。

配置が成功した後、位置を再度変更するロジックを処理するスクリプトを作成します。

DragObject.cs

using System.Collections using System.Collections.Generic using UnityEngine public class DragObject : MonoBehaviour { //Drag only for the specified level public LayerMask _dragLayerMask //Specify the object to be dragged public Transform currentTransform //Whether the current object can be dragged public bool isDrag = false //Used to store the coordinates of the object that needs to be dragged in the screen space Vector3 screenPos = Vector3.zero //The offset of the coordinates of the object that needs to be dragged relative to the mouse in world space coordinates Vector3 offset = Vector3.zero void Update () { if (Input.GetMouseButtonDown (0)) { //Convert the mouse input point into a ray Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition) RaycastHit hitinfo //If the current object collides with the specified level, it means that the current object can be dragged if (Physics.Raycast (ray, out hitinfo, 1000f, _dragLayerMask)) { isDrag = true //Assign the object that needs to be dragged to the object that the ray collides with currentTransform = hitinfo.transform //Convert the current object's world coordinates to screen coordinates screenPos = Camera.main.WorldToScreenPoint (currentTransform.position) //Convert the mouse's screen coordinates to world space coordinates, and then calculate the offset between them and the object to be dragged offset = currentTransform.position - Camera.main.ScreenToWorldPoint (new Vector3 (Input.mousePosition.x, Input.mousePosition.y, screenPos.z)) } else { isDrag = false } } if (Input.GetMouseButton (0)) { if (isDrag == true) { var currentScreenPos = new Vector3 (Input.mousePosition.x, Input.mousePosition.y, screenPos.z) //Mouse's screen space coordinates are converted to world coordinates, plus the offset var currentPos = Camera.main.ScreenToWorldPoint (currentScreenPos) + offset currentTransform.position = currentPos } } if (Input.GetMouseButtonUp (0)) { isDrag = false currentTransform = null } } }

これは主に、ある座標空間の変換と計算です。

冗長なものについては話しません。スクリプトには非常に詳細なコメントがあります。デモアドレスは、現在の記事の最後でスキャンされます。

その他のコンテンツについては、以下に注意を払うことを歓迎します。

画像