EventSystem大家平时主要是用来处理UGUI的输入,但其实也可以使用在一般的3D对象上,Unity API对这个介绍的很少。
在网上找到了一篇介绍不错的文章。
https://www.cnblogs.com/weiqiangwaideshijie/p/6859867.html
以下是我的一些分享:
使用Physics RayCaster组件绑定Camera上
Test脚本如下,只不过Drag事件还未处理,物体还不能拖动
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; public class TestSystemInputMono : MonoBehaviour, IPointerDownHandler, IBeginDragHandler, IDragHandler, IEndDragHandler { // Use this for initialization void Start () { } // Update is called once per frame void Update () { } public void OnPointerDown (PointerEventData eventData) { Debug.Log ("OnPointerDown"); } public void OnBeginDrag(PointerEventData data) { Debug.Log ("OnBeginDrag"); } public void OnDrag(PointerEventData data) { Debug.Log ("OnDrag"); } public void OnEndDrag(PointerEventData eventData) { Debug.Log ("OnEndDrag"); } }
有关PointerEventData的参数,其中了些属性,很重要的
button | The InputButton for this event |
对应Mouse的三个按键
pointerId | Id of the pointer (touch id). |
对应Touch,这里还没有试过多点触屏是否支持,即是否支持同时拖拽两个物体
对对3D物体,最重要应该是PointerCurrentRaycast,其API说明:
https://docs.unity3d.com/ScriptReference/EventSystems.PointerEventData-pointerCurrentRaycast.html
depth | The relative depth of the element. |
distance | Distance to the hit. |
gameObject | The GameObject that was hit by the raycast. |
index | Hit index. |
isValid | Is there an associated module and a hit GameObject. |
module | BaseInputModule that raised the hit. |
screenPosition | The screen position from which the raycast was generated. |
sortingLayer | The SortingLayer of the hit object. |
sortingOrder | The SortingOrder for the hit object. |
worldNormal | The normal at the hit location of the raycast. |
worldPosition | The world position of the where the raycast has hit. |
其中worldPostion就是当前射线碰撞到的点的世界坐标。如果没有碰撞到,比如Drag时拖出物体区域,那isValid值为False
下面看如何进行Drag处理让其动起来
Vector3 oldPos; public void OnDrag(PointerEventData data) { //Debug.Log ("OnDrag " + data.pointerCurrentRaycast.worldPosition + " valid " + data.pointerCurrentRaycast.isValid); Debug.Log ("OnDrag " + data.delta); //var newPos = Camera.main.ScreenToWorldPoint (new Vector3(data.position.x, data.position.y, Camera.main.nearClipPlane)); var newPos = data.pointerCurrentRaycast.worldPosition; var offset = newPos - oldPos; Debug.Log ("offset is " + offset); var projectOffset = Vector3.ProjectOnPlane(offset, data.pointerCurrentRaycast.worldNormal); transform.position += projectOffset; //var dir2 = Camera.main.worldToCameraMatrix.inverse.MultiplyPoint (data.delta) - Camera.main.transform.position; // // var projectDir = Vector3.ProjectOnPlane(dir2, data.pointerCurrentRaycast.worldNormal); // Debug.Log ("dir = " + dir2.ToString() + " projectDir = " + projectDir.ToString()); //TestAnchor.transform.position += projectDir; oldPos = newPos; }大体思路是获取到在物体上的移动的相对偏移,再映射到拖拽的平面上,这里只是简单的取当前物体拖拽点平面。之前的思路有问题,想从Camera的屏幕相对位移出发,但不是想要的效果。