记录:
最近接触到了FingerGesture插件,了解其大致使用方法之后,便想用它做个简单的例子尝试一下,于是便选择了虚拟遥杆。
该demo实现的大致功能如下:1.虚拟遥杆操作界面 2.根据操作移动场景中的物体。大致效果如下,AV画质:
具体实现:首先,遥杆操作界面的实现,其思想是用两张图片,一张做背景,一张做移动杆。这样只需捕获到手指的触屏操作,动态改变移动杆的位置便可模拟出虚拟遥杆。而捕获触摸操作既可以通过unity自带的事件系统,也可以借助一些插件,这里则是使用了FingerGesture插件,用到了其中的FingerDown Detector,FingerUpDetector,FingerMotionDetector.
FingerGesture能够识别的手势有taps, swipes, drags and pinches 等;使用时,首先要在场景中中添加FingerGestures.prefab,它是管理各种手势触屏操作的中心。其次根据需要添加相应的模块,比如识别长按,则可添加脚本Long-Press Recognizer.cs 。监听一些手指操作,则可添加FingerDown Detector,FingerUpDetector等。对于各种触摸操作事件的传递,有以下两种:(使用的Finger Gesture版本是3.1,Unity5.3.6p8)
A gesture recognizer has several ways of firing its events:
-
Using standard .NET delegate-based events. Each gesture recognizer exposes a .NET event that you can subscribe to from code.
-
Using Unity's SendMessage() method
-
The gesture event is broadcast to all the other components on the same GameObject
-
The gesture event can also be forwarded to the scene object currently being interacted with (selection). This however requires the GestureRecognizer to be equipped with a Raycaster component in order to detect scene objects.
-
大意为:手势操作的监听既可通过委托注册相应事件,也可利用Unity广播传递。使用广播机制时,要注意:在没有设置Message Tagert时,消息会默认发送给挂在了该手势事件脚本的游戏体,若指定了,则只发送给指定的对象。使用委托进行事件的注册时,使用的是统一的事件接口,对于手势识别为: FingerGestures.OnGestureEvent;对于手指事件则为 FingerGestures.OnFingerEvent。在触发了事件后,在对应的处理函数中再利用GetType()判断具体的事件类型。
具体使用细节可查看官网文档:http://fingergestures.fatalfrog.com/docs/start。
其次,则是将遥杆的操作作用到场景中的具体对象。物体移动最主要的也就是两个方面:1.移动的方向,2.移动的速度。本例对运动方向的确定由下图可直观的看出,对于速度的控制则采取的是手动设定、匀速的方式;当然也可以根据遥杆距中心点的距离不同设置不同的移动速度。
主要逻辑代码:
using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;
public class CircleMove : MonoBehaviour{
public Transform circle;
public Transform player;
private Vector3 origin;
public float rotate_speed=1.0f;
public float move_speed=1.0f;
//摇杆移动半径
public float move_area = 100.0f;
public GameObject container;
private bool stop=true ;
public Vector2 default_pos = new Vector2(300,300);
private Vector3 last_position;
private Vector3 move_dir;
private int first_finger_index=-1;
// Use this for initialization
void Start () {
container.transform.position = default_pos;
origin = circle.position;
}
// Update is called once per frame
void Update () {
//EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId);//对于EventSystem.current.IsPointerOverGameObject这个函数,
//因为EventSystem是UI的事件系统,所以IsPointerOverGameObject中的GameObject是针对UI的,而不是普遍意义上的GameObject
if(!stop)
MoveGameObj(circle.position);
}
void OnFingerMove(FingerMotionEvent e)
{
if(first_finger_index!=e.Finger.Index)
return ;
if (e.Position.x > Screen.width / 2 || e.Position.y > Screen.height / 2)
return;
float elapsed = e.ElapsedTime;
if (e.Phase == FingerMotionPhase.Started)
Debug.Log(e.Finger + " started moving at " + e.Position);
else if (e.Phase == FingerMotionPhase.Updated)
{
if (Vector2.Distance(origin, Input.mousePosition) <= move_area)
circle.position = e.Position;
else {
Vector2 dir=e.Position- new Vector2(origin.x, origin.y);
circle.position =new Vector2(origin.x, origin.y)+ dir.normalized * move_area;
}
}
else if (e.Phase == FingerMotionPhase.Ended)
{
Debug.Log(e.Finger + " stopped moving at " + e.Position);
last_position = circle.position;
}
}
void OnFingerStationary(FingerMotionEvent e)
{
//float elapsed = e.ElapsedTime;
//if (e.Phase == FingerMotionPhase.Started)
// Debug.Log(e.Finger + " started stationary state at " + e.Position);
//else if (e.Phase == FingerMotionPhase.Updated)
// Debug.Log(e.Finger + " is still stationary at " + e.Position);
//else if (e.Phase == FingerMotionPhase.Ended)
//{
// Debug.Log(e.Finger + " stopped being stationary at " + e.Position);
// circle.position = origin;
//}
}
void OnFingerDown(FingerDownEvent e)
{
if(first_finger_index!=-1)
return ;
first_finger_index = e.Finger.Index;
Debug.Log(" first_finger_index >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" + first_finger_index);
if (e.Position.x < Screen.width / 2 && e.Position.y < Screen.height / 2)//判断出触摸处是否可显示虚拟遥杆,可则显示,不可则退出
{
container.transform.position = e.Position;
origin = circle.position;
stop = false;
}
else {
return;
}
Debug.Log(e.Finger + " Down at " + e.Position + " on object:" + e.Selection.name);
}
void OnFingerUp(FingerUpEvent e)
{
Debug.LogError("tappppppp2555552=====111111111");
if (first_finger_index != e.Finger.Index)
return;
container.transform.position = default_pos;
circle.localPosition=Vector2.zero;
origin = circle.position;
stop = true;
first_finger_index=-1;
}
void MoveGameObj(Vector2 target) {
if (Vector2.Distance(target, last_position) > 0.5) {
Vector2 dir = target - new Vector2(origin.x, origin.y);
move_dir = new Vector3(dir.x, 0, dir.y);
}
player.position += move_dir.normalized * move_speed * Time.deltaTime;
player.rotation = Quaternion.Lerp(player.rotation, Quaternion.LookRotation(move_dir), rotate_speed * Time.deltaTime);
}
void OnTap(TapGesture gesture)
{
// Number of taps performed
Debug.LogError("tappppppp=====");
}
}
工程很乱,没有整理,DEMO下载: http://download.youkuaiyun.com/detail/u012221316/9921999