我们可能会经常遇到一个这样的需求, 再3d场景里实现运行时的 相机移动,旋转,缩放拉近等。game下模拟scene里的效果。
对于pc端,或者是unity编辑器,我们可以手写几行代码实现 左键,右键来操作,但是对于移动端,是没有右键的概念的,就没法使用了。这时候可以使用touch类,获取出点,然后计算,触点个数,位移偏差,然后驱动相机实现效果,逻辑也不是很难,关键在于怎么区分双指的滑动,缩放等,双指的单个移动等,这些不是很好处理,当然,对于大佬还是简单的。
南无除此之外还有一种方法,就是找插件。移动端触屏相关的插件还是挺多的,就拿普遍使用的easytouch来讲解,这个知名度,使用度还是不低的
首先呢,这个easytouch有众多版本,unity 2018之后的版本建议使用easytouch1.8以上的版本,2017 及以下可以使用老版本,不然会有很多奇怪的错误。我这里是用2019unity 配合easytouch1.9
easytouch其实并不完善,有很多bug,也有很多坑。 但是它还是很强大,做触屏,遥感很快(前提没遇到坑)
首先,新建场景,create-easytouch -add easytouch 添加一个easytouch控制器,如图:
这里有很多配置,注意,如果你不需要使用3D物体的交互,如拖拽,点击等,吧上图取消勾选不然那影响相机操作
接下来先说一下遇到的坑
1,新版本的easytouch是通过注册事件监听的方式获取信息的 详细可以打开easytouch类查看,我们选择自己要使用的事件进行监听,如 单指滑动,双指滑动,缩放
2,如果有场景跳转等再运行时会导致你的相机控制或者某个其他easytouch功能再一定条件下不使用,需要将事件移除
3,如果同时监听了单指和双指,比如单指点击,双指点击,即只要单双指都有监听事件,那么恭喜你,你只能收到单指的信息,双指呗覆盖了!
4,编辑器下测试:alt键加鼠标模拟 缩放 Ctrl加鼠标模拟双指滑动 但是,如果你想获取touch的个数,返回是0!!!因为touch是只要真机上才能生效!!!
然后关于相机:
我采取将相机挂在一个空物体下,作为子物体的方式,这样的好处可以快速还原,旋转的时候和移动效果更佳!
移动 没什么好说,xy轴的移动就行了
缩放 相机自身向前移动
旋转 相机围绕自身轴旋转即可
接下来上脚本“、
using HedgehogTeam.EasyTouch;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Assertions.Must;
using UnityEngine.UI;
public enum State
{
None,
//单指
Single,
//缩放
Pinch,
//滑动
Swipe
}
public class CameraTouchCtr : MonoBehaviour
{
public float moveSpeed = 1;
public float rotateSpeed = 60;
public float zoomSpeed = 1;
public Transform Camera;
public State state;
Vector2 offset;
Touch[] touches;
int activeCount;
// Start is called before the first frame update
void Start()
{
//OnOneTouch();
OnTwoTouch();
}
// Update is called once per frame
void Update()
{
if(state == State.None)
{
activeCount = 0;
if (Input.touchCount > 0)
{
touches = Input.touches;
for (int i = 0; i < touches.Length; i++)
{
if (touches[i].phase == TouchPhase.Ended || touches[i].phase == TouchPhase.Canceled)
continue;
activeCount++;
}
}
if(activeCount == 1)
{
state = State.Swipe;
OnOneTouch();
}else
{
OnOneTouch(false);
}
}
if (activeCount <= 0 && state != State.None)
{
Reset();
//if (state == State.Pinch)
// Reset();
//else
// state = State.None;
}
//tex.text = state.ToString();
}
//单指
private void OnOneTouch(bool regiest=true )
{
if(regiest)
{
EasyTouch.On_Swipe += On_Swipe;
EasyTouch.On_SwipeEnd += On_SwipeEnd;
}
else
{
EasyTouch.On_Swipe -= On_Swipe;
EasyTouch.On_SwipeEnd -= On_SwipeEnd;
}
}
private void On_SwipeEnd(Gesture gesture)
{
state = State.None;
}
//双指
private void OnTwoTouch(bool regiest = true)
{
if (regiest)
{
EasyTouch.On_Swipe2Fingers += On_Swipe2Fingers;
EasyTouch.On_SwipeEnd2Fingers += On_SwipeEnd;
EasyTouch.On_Pinch += On_Pinch;
EasyTouch.On_PinchEnd += On_SwipeEnd;
}
else
{
EasyTouch.On_Pinch -= On_Pinch;
EasyTouch.On_Swipe2Fingers -= On_Swipe2Fingers;
EasyTouch.On_SwipeEnd2Fingers -= On_SwipeEnd;
EasyTouch.On_PinchEnd -= On_SwipeEnd;
}
}
private void Reset()
{
state = State.None;
Camera.transform.eulerAngles = Vector3.zero;
Camera.transform.localPosition = Vector3.zero; ;
}
/// <summary>
/// 缩放
/// </summary>
/// <param name="ges"></param>
void On_Pinch(Gesture ges)
{
if(state == State.Pinch)
{
int dir = ges.deltaPinch < 0 ? -1 : 1;//如果同时监听单个手指的事件,返回值将获取为0
Camera.transform.position += Camera.transform.forward * zoomSpeed * dir*Time .deltaTime ;
}else
{
//缩放
if (Mathf.Abs(ges.deltaPinch) > 10)
{
state = State.Pinch;
int dir = ges.deltaPinch < 0 ? -1 : 1;
Camera.transform.position += Camera.transform.forward * zoomSpeed * dir * Time.deltaTime;
}
else
{
On_Swipe2Fingers(ges);
}
}
}
/// <summary>
/// 双指滑动
/// </summary>
/// <param name="ges"></param>
void On_Swipe2Fingers(Gesture ges)
{
state = State.Swipe;
if(Mathf .Abs ( ges .deltaPosition .x) > 10)
{
Camera.transform.Rotate(-Vector3 .up *rotateSpeed * ges .deltaPosition.normalized .x * Time.deltaTime);
}else
{
Camera.transform.Rotate(-Vector3 .right * rotateSpeed * ges.deltaPosition.normalized .y * Time.deltaTime);
}
}
/// <summary>
/// 单指滑动
/// </summary>
/// <param name="ges"></param>
void On_Swipe(Gesture ges)
{
state = State.Swipe;
transform.Translate(-ges.deltaPosition.normalized * moveSpeed * Time.deltaTime);
}
}
为了规避单指覆盖问题等,我采取update获取touch个数,进行动态单指监听
然后放一下使用图: