EventSystem应用于3D GameObject,实现拖拽效果

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的屏幕相对位移出发,但不是想要的效果。

猜你喜欢

转载自blog.csdn.net/feibin2013/article/details/80262119