上一篇博客 可以看到Unity自带的EventSystem系统掌管了鼠标输入、触摸输入两大输入类型,并且可根据BaseRayCaster进行射线发射来判断鼠标点击在了哪个物体上,进而可以自定义点击事件响应方法(如下图)来完成一个workflow:
但是现在有一个问题,我的输入类型不是鼠标也不是触摸,比如说我目前的输入就是一个已知的坐标。我该怎么模拟一次点击效果呢?
有朋友可能会说,你要实现什么样的效果= =,比如说正统的鼠标点击我可以这么写,我把这个cs文件挂载到一个cube上,发现当我的鼠标点击到cube以后,cube就会被变色:
void Update()
{
if(Input.GetMouseButtonDown(0))
{
Debug.Log("Input.GetMouseButtonDown response");
}
}
void OnMouseDown()
{
Debug.Log("OnMouseDown response");
//该物体变色
}
void OnGUI()
{
if(Event.current!=null && Event.current.type == EventType.MouseDown)
{
Debug.Log("EventType.mouseDown response");
}
}
如果你的输入不是鼠标而是一个已知的(x,y)坐标,那你直接这么写,不行吗?
public Vector2 position;
void Update()
{
position = xx.GetPosition();
if(position)
OnSimuMouseDown();
}
void OnSimuMouseDown()
{
if(position)
//该物体变色
}
不。这有一个缺陷,在第一个情况里,OnMouseDown()是当鼠标真的点击在cube上的时候才会被触发,但是第二种情况是我获取到了position就会触发OnSimuMouseDown(),如果这个position的位置不在cube身上,却让cube变色了,是不是背离初衷?所以代码就会变成了只能加上判断位置,就会变得相当麻烦。
void OnSimuMouseDown()
{
if(position在Cube身上)
//该物体变色
}
还有一种情况就是,如果我不想让物体变色呢?我是想拖动物体移动呢?真正的鼠标点击很好办,这么写就行了,因为Unity已经给封装好了事件:
void OnMouseDrag()
{
//获取到鼠标的位置(鼠标水平的输入和竖直的输入以及距离)
Vector3 mousePosition = new Vector3(Input.mousePosition.x, Input.mousePosition.y, distance);
//物体的位置,屏幕坐标转换为世界坐标
Vector3 objectPosition = Camera.main.ScreenToWorldPoint(mousePosition);
//把鼠标位置传给物体
transform.position = objectPosition;
}
如果只给你一个坐标,然后每1s给你一个新的坐标,让你“拖动”Cube随着这个坐标运动你会怎么写?是不是想想都觉得头大?万一你的项目中需要很多这样的操作呢?
所以我们要模拟一个假鼠标。这里我们用到了TouchScript插件。首先来看一个例子我们来了解一下TouchScript对Unity的一个基本Event做了哪些改动。
这个Standard Layer是干嘛的,其实就是从摄像机发射射线的,可以判断鼠标点击在了哪个物体上。这里我们只让该射线判断3D物体。
这个组件大概是重写了Unity自带的PhysicsRaycaster组件还有canvas上边的GraphicRaycaster组件:
然后是Cursors这个预制体,一切照常,不用管,TouchManager我们不用StandardInput,而是用TUIO Input,因为这个雷达更能表示一个单纯的坐标,更具有代表性:
EventSystem是神经枢纽,无论是在Unity自带的Event还是在TouchScript里都一样,非常重要。这里我们的EventSystem很简约。是不是发现少了点东西?是的,Standalone Input Module我们没用,个人感觉TouchScript的StandardInput已经把它重写了(虽然我们也没加),TUIOInput算是一个custom Input Module,假装可以被EventSystem处理:
最后是Cube,作为一个3D物体,要想检测到摄像机射线,Collider是少不了的。那么Transformer和Transformer Gesture这两个组件是干嘛?来对比一下右图(上一篇博客)就知道了:
可以看到Unity本身的Event是可以自定义相应函数的,比如说当我监听到PointerClick的时候,我就可以怎么怎么样:
public void OnPointerClickHandler() //在cube上挂上EventTrigger并指定该方法
{
Debug.Log("????");
//获取该物体的材质并让该物体变色
}
那么Transformer和Transformer Gesture有异曲同工之妙,比如说当我的系统里有一个Pointer pressed,那么我就可以怎么怎么样,我们来看Transformer Gesture部分源码:
而Transformer组件是获取Transformer Gesture的transform 数据并apply到真实的物体上的,比如说移动啊,旋转啊,放大缩小啊。我们要想实现该物体变色可以这样写
/**
*┌──────────────────────────────────────────────────────────────┐
*│ Description:
*│ Author:#AUTHOR#
*│ Version:#VERSION#
*│ Date:#DATE#
*│ UnityVersion: #UNITYVERSION#
*└──────────────────────────────────────────────────────────────┘
*┌──────────────────────────────────────────────────────────────┐
*│ ClassName:#SCRIPTFULLNAME#
*└──────────────────────────────────────────────────────────────┘
*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TouchScript;
using TouchScript.Gestures;
using TouchScript.Gestures.TransformGestures;
public class TestTouchScript : TransformGesture
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
private void OnTriggerEnter2D(Collider2D other)
{
Debug.Log(other.name);
}
void OnMouseDown() //针对的是鼠标点击
{
Debug.Log("OnMouseDown");
}
protected override void pointersPressed(IList<TouchScript.Pointers.Pointer> pointers)
{
base.pointersPressed(pointers);
Debug.Log("aaaa");
//获取该物体的材质并让该物体变色
}
protected override void pointersReleased(IList<TouchScript.Pointers.Pointer> pointers)
{
base.pointersReleased(pointers);
Debug.Log("?????????????????");
}
}
可以看到我们定义了一个类继承了TransformGesture,并重写了它的反应函数,就相当于是OnMousedown()函数一样了。也相当于是这种自定义的响应函数,参照上一篇博客:
public void OnPointerDown(PointerEventData eventData)
{
Debug.Log(eventData.button);
Debug.Log(eventData);
Debug.Log(Input.mousePosition);
Debug.Log(eventData.pointerPressRaycast.gameObject.name);
Debug.Log("press");
}
做实验,发现通过雷达模拟器,我们可以让该Cube有所动作,并且可以让Cube随着虚拟指针进行移动:
同样我们不用TUIOInput而是用TouchScript自定义的StandardInput的话:
效果是这样的,依然可以通过鼠标移动Cube,并且还会触发OnMouseDown(),因为这是真实的鼠标点击:
二更:
后来我发现TouchScript有一个Press Gesture组件,已经把点击这一动作给封装好了,所以可以直接在cube上用这个:
重点是Press Action.cs,这个是我自己加的,它就相当于是分发press事件以后,自定义反应的:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using TouchScript;
using TouchScript.Utils;
using TouchScript.Gestures;
using System;
public class PressAction : MonoBehaviour//,IPointerDownHandler
{
private PressGesture pressGesture;
// Start is called before the first frame update
void Start()
{
}
private void OnEnable()
{
pressGesture = GetComponent<PressGesture>();
pressGesture.Pressed += pressedHandler;
}
private void OnDisable()
{
pressGesture.Pressed -= pressedHandler;
}
//相当于是void MouseDown()或者void OnPointerDown(PointerEventData eventData)
private void pressedHandler(object sender, EventArgs e)
{
Debug.Log("变色吧,皮卡丘!");
}
// Update is called once per frame
void Update()
{
}
}
但是很遗憾的是,TouchScript在2017年以后就不再更新了,所以决定不用这个插件了。。。= =。
蛋疼。。。。