1、在package manager中先安装Input system 包。
2、安装完成之后,创建input action。创建单手指操作,创建一个获取单手指位置的action,一个获取单手指交互的action。

3、创建双手指的操作,创建一个获取第一个手指位置的action,一个获取第二个手指位置的action,一个获取第二个手指交互的action。

4、创建InputManager.cs脚本,用来管理所有的操作信息。
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.InputSystem;
[DefaultExecutionOrder(-1)]
public class InputManager : MonoBehaviourSingleton<InputManager>
{
public Action<Vector2, Vector2> pinchStarted;
public Action<Vector2, Vector2> pinchChanged;
public Action<Vector2, Vector2> pinchEnd;
public Action<Vector2, float> swipeStarted;
public Action<Vector2, float> swipeChanged;
public Action<Vector2, float> swipeEnd;
private InputControls _inputControl;
private Coroutine _swipeCoroutine;
private Coroutine _pinchCoroutine;
private void Awake()
{
_inputControl = new InputControls();
}
private void OnEnable()
{
_inputControl.Enable();
}
private void OnDisable()
{
_inputControl.Disable();
}
// Start is called before the first frame update
void Start()
{
_inputControl.Touch.SecondaryTouchContact.started += _ => PinchStart();
_inputControl.Touch.SecondaryTouchContact.canceled += _ => PinchEnd();
_inputControl.Touch.PrimaryContact.started += SwipeStart;
_inputControl.Touch.PrimaryContact.canceled += SwipeEnd;
}
private void SwipeStart(InputAction.CallbackContext ctx)
{
swipeStarted?.Invoke(_inputControl.Touch.PrimaryPosition.ReadValue<Vector2>(), (float)ctx.startTime);
_swipeCoroutine = StartCoroutine(SwipeDetection(ctx));
}
private void SwipeEnd(InputAction.CallbackContext ctx)
{
swipeEnd?.Invoke(_inputControl.Touch.PrimaryPosition.ReadValue<Vector2>(), (float)ctx.time);
StopCoroutine(_swipeCoroutine);
}
IEnumerator SwipeDetection(InputAction.CallbackContext ctx)
{
while (true)
{
if (Input.touchCount > 1)
{
break;
}
swipeChanged?.Invoke(_inputControl.Touch.PrimaryPosition.ReadValue<Vector2>(), (float)ctx.time);
yield return null;
}
}
private void PinchStart()
{
pinchStarted?.Invoke(_inputControl.Touch.PrimaryFingerPosition.ReadValue<Vector2>(), _inputControl.Touch.SecondaryFingerPosition.ReadValue<Vector2>());
_pinchCoroutine = StartCoroutine(PinchDetection());
}
private void PinchEnd()
{
pinchEnd?.Invoke(_inputControl.Touch.PrimaryFingerPosition.ReadValue<Vector2>(), _inputControl.Touch.SecondaryFingerPosition.ReadValue<Vector2>());
StopCoroutine(_pinchCoroutine);
}
IEnumerator PinchDetection()
{
while (true)
{
if(Input.touchCount == 2)
{
pinchChanged?.Invoke(_inputControl.Touch.PrimaryFingerPosition.ReadValue<Vector2>(), _inputControl.Touch.SecondaryFingerPosition.ReadValue<Vector2>());
}
yield return null;
}
}
}
5、在InputManger中,所有的手指触发操作都会有回调,创建单手指滑动的操作,让相机沿着正方体进行旋转。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SwipeDetection : MonoBehaviour
{
[SerializeField]
private Camera mainCamera;
[SerializeField]
private float minDistance = 4f;
[SerializeField]
float sensitivity = 20f;
[SerializeField]
private GameObject targetAnchor;
private InputManager _inputManager;
private float _startTime;
private float _endTime;
private Vector2 _startPosition;
private Vector2 _endPosition;
private Vector2 _previousPosition;
private void Awake()
{
_inputManager = InputManager.Instance;
}
private void OnEnable()
{
_inputManager.swipeStarted += OnSwipeStarted;
_inputManager.swipeEnd += OnSwipeEnd;
_inputManager.swipeChanged += OnSwipeChanged;
}
private void OnDisable()
{
_inputManager.swipeStarted -= OnSwipeStarted;
_inputManager.swipeEnd -= OnSwipeEnd;
_inputManager.swipeChanged -= OnSwipeChanged;
}
private void OnSwipeStarted(Vector2 position, float time)
{
_startPosition = position;
_previousPosition = position;
_startTime = time;
}
private void OnSwipeEnd(Vector2 position, float time)
{
_endPosition = position;
_endTime = time;
Debug.DrawLine(_startPosition, _endPosition, Color.red, 5f);
}
private void OnSwipeChanged(Vector2 position, float time)
{
Vector2 curPosition = position;
if(Vector2.Distance(curPosition, _previousPosition) < minDistance)
{
return;
}
float angle = Vector2.Angle(curPosition - _startPosition, Vector2.up);
if(angle > 45.0 && angle < 135.0)
{
float x = (curPosition.x - _previousPosition.x) / Screen.width * sensitivity;
mainCamera.transform.RotateAround(targetAnchor.transform.position, Vector3.up, x);
} else
{
float y = (curPosition.y - _previousPosition.y) / Screen.height * sensitivity;
mainCamera.transform.RotateAround(targetAnchor.transform.position, transform.right, -y);
}
_previousPosition = curPosition;
}
}
6、Unity提供了RotateAround(targetAnchor.transform.position, Vector3.up, x);函数可以沿着某个物体旋转。我们也可以自己实现这个函数。
void MyRotateAround(Vector3 center, Vector3 axis, float angle)
{
Vector3 pos = transform.position;
Quaternion rot = Quaternion.AngleAxis(angle, axis);
Vector3 dir = pos - center; //计算从圆心指向摄像头的朝向向量
dir = rot * dir; //旋转此向量
transform.position = center + dir;//移动摄像机位置
var myrot = transform.rotation;
//transform.rotation *= Quaternion.Inverse(myrot) * rot *myrot;//设置角度另一种方法
transform.rotation = rot * myrot; //设置角度
}
7、双手指操作,相机沿着正方体的方向进行拉近拉远的操作。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PinchDetection : MonoBehaviour
{
[SerializeField]
private Camera mainCamera;
[SerializeField]
private float cameraSpeed = 4f;
[SerializeField]
private GameObject targetAnchor;
private InputManager _inputManager;
private float _previousDistance;
private void Awake()
{
_inputManager = InputManager.Instance;
}
private void OnEnable()
{
_inputManager.pinchStarted += OnPinchStarted;
_inputManager.pinchChanged += OnPinchChanged;
}
private void OnDisable()
{
_inputManager.pinchStarted -= OnPinchStarted;
_inputManager.pinchChanged -= OnPinchChanged;
}
public void OnPinchStarted(Vector2 position1, Vector2 position2)
{
_previousDistance = Vector2.Distance(position1, position2);
}
public void OnPinchChanged(Vector2 position1, Vector2 position2)
{
float distance = Vector2.Distance(position1, position2);
if (distance > _previousDistance)
{
Vector3 forward = targetAnchor.transform.position - mainCamera.transform.position;
mainCamera.transform.Translate(forward.normalized * Time.deltaTime * cameraSpeed, Space.World);
}
else
{
Vector3 forward = mainCamera.transform.position - targetAnchor.transform.position;
mainCamera.transform.Translate(forward.normalized * Time.deltaTime * cameraSpeed, Space.World);
}
_previousDistance = distance;
}
}
8、脚本都已经就位,我们就在Unity操作界面上进行绑定。

9、在PC端我们先调试一下单手指的操作。

10、最后在手机上展示一下我们的成功。

案例下载地址:
https://download.csdn.net/download/grace_yi/20559035?spm=1001.2014.3001.5501
参考文献:
https://www.cnblogs.com/tangzhenqiang/p/8966882.html
https://www.cnblogs.com/lichuangblog/p/7967307.html
|