在zSpace上使用鼠标控制相机旋转和鼠标指引式放大缩小,在触屏上手势位置为中心放大缩小

鼠标和触屏的操作

下面展示一些 内联代码片

using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityInput = UnityEngine.Input;
using zSpace.Core.Input;
using zSpace.Core;namespace CamControl
{/// <summary>/// Class to manage tap/drag/pinch gestures and other controls/// </summary>public class InputController : MonoBehaviour{/// <summary>/// All the touches we're tracking/// </summary>private List<TouchInfo> m_Touches = new List<TouchInfo>();/// <summary>/// Mouse button info/// </summary>private List<MouseButtonInfo> m_MouseInfo;/// <summary>/// zStylus/// </summary>private ZStylus m_ZStylus;/// <summary>/// Gets the number of active touches/// </summary>public int ActiveTouchCount => m_Touches.Count;/// <summary>/// Tracks if any of the mouse buttons were pressed this frame/// </summary>public bool MouseButtonPressedThisFrame { get; private set; }/// <summary>/// Tracks if the mouse moved this frame/// </summary>public bool MouseMovedOnThisFrame { get; private set; }/// <summary>/// Tracks if a touch began this frame/// </summary>public bool TouchPressedThisFrame { get; private set; }/// <summary>/// Current mouse pointer info/// </summary>public PointerInfo BasicMouseInfo { get; private set; }/// <summary>/// Event called when a pointer press is detected/// </summary>public event Action<PointerActionInfo> Pressed;/// <summary>/// Event called when a pointer is released/// </summary>public event Action<PointerActionInfo> Released;/// <summary>/// Event called when a pointer is tapped/// </summary>public event Action<PointerActionInfo> Tapped;/// <summary>/// Event called when a drag starts/// </summary>public event Action<PointerActionInfo> StartedDrag;/// <summary>/// Event called when a pointer is dragged/// </summary>public event Action<PointerActionInfo> Dragged;/// <summary>/// Event called when a pointer starts a hold/// </summary>public event Action<PointerActionInfo> StartedHold;/// <summary>/// Event called when the user scrolls the mouse wheel/// </summary>public event Action<WheelInfo> SpunWheel;/// <summary>/// Event called when the user performs a pinch gesture/// </summary>public event Action<PinchInfo> Pinched;/// <summary>/// Event called whenever the mouse is moved/// </summary>public event Action<PointerInfo> MouseMoved;/// <summary>/// 按下zSpace触控笔上的按键/// </summary>public event Action<int> ZStylusPressed;private void Awake(){// Mouse specific initializationif (UnityInput.mousePresent){m_MouseInfo = new List<MouseButtonInfo>();BasicMouseInfo = new MouseCursorInfo { currentPosition = UnityInput.mousePosition };for (int i = 0; i < 3; ++i){m_MouseInfo.Add(new MouseButtonInfo{currentPosition = UnityInput.mousePosition,mouseButtonId = i});}}UnityInput.simulateMouseWithTouches = false;}private void Start(){if (ZProvider.IsInitialized){m_ZStylus = FindObjectOfType<ZStylus>();if (m_ZStylus != null){m_ZStylus.OnButtonPressed.AddListener(OnZStylusButtonPressed);}}}private void OnZStylusButtonPressed(ZPointer zPointer, int buttonId){ZStylusPressed?.Invoke(buttonId);}/// <summary>/// Update all input/// </summary>private void Update(){if (BasicMouseInfo != null){// Mouse was detected as presentUpdateMouse();}// Handle touchesUpdateTouches();}/// <summary>/// Perform logic to update mouse/pointing device/// </summary>private void UpdateMouse(){BasicMouseInfo.previousPosition = BasicMouseInfo.currentPosition;BasicMouseInfo.currentPosition = UnityInput.mousePosition;BasicMouseInfo.delta = BasicMouseInfo.currentPosition - BasicMouseInfo.previousPosition;MouseMovedOnThisFrame = BasicMouseInfo.delta.sqrMagnitude >= Mathf.Epsilon;MouseButtonPressedThisFrame = false;// Move eventif (BasicMouseInfo.delta.sqrMagnitude > Mathf.Epsilon){MouseMoved?.Invoke(BasicMouseInfo);}// Button eventsfor (int i = 0; i < 3; ++i){MouseButtonInfo mouseButton = m_MouseInfo[i];mouseButton.delta = BasicMouseInfo.delta;mouseButton.previousPosition = BasicMouseInfo.previousPosition;mouseButton.currentPosition = BasicMouseInfo.currentPosition;if (UnityInput.GetMouseButton(i)){if (!mouseButton.isDown){// First pressMouseButtonPressedThisFrame = true;mouseButton.isDown = true;mouseButton.startPosition = UnityInput.mousePosition;mouseButton.startTime = Time.realtimeSinceStartup;mouseButton.startedOverUI = EventSystem.current.IsPointerOverGameObject(-mouseButton.mouseButtonId - 1);// Reset some stuffmouseButton.totalMovement = 0;mouseButton.isDrag = false;mouseButton.wasHold = false;mouseButton.isHold = false;mouseButton.flickVelocity = Vector2.zero;Pressed?.Invoke(mouseButton);}else{float moveDist = mouseButton.delta.magnitude;// Dragging?mouseButton.totalMovement += moveDist;if (mouseButton.totalMovement > 0f){bool wasDrag = mouseButton.isDrag;mouseButton.isDrag = true;if (mouseButton.isHold){mouseButton.wasHold = mouseButton.isHold;mouseButton.isHold = false;}// Did it just start now?if (!wasDrag){StartedDrag?.Invoke(mouseButton);}Dragged?.Invoke(mouseButton);// Flick?if (moveDist > 2f){mouseButton.flickVelocity = (mouseButton.flickVelocity * 0.2f) + (mouseButton.delta * 0.8f);}else{mouseButton.flickVelocity = Vector2.zero;}}else{// Stationary?if (!mouseButton.isHold && !mouseButton.isDrag && Time.realtimeSinceStartup - mouseButton.startTime >= 0.8f){mouseButton.isHold = true;StartedHold?.Invoke(mouseButton);}}}}else // Mouse button not up{if (mouseButton.isDown) // Released{mouseButton.isDown = false;// Quick enough (with no drift) to be a tap?if (!mouseButton.isDrag && Time.realtimeSinceStartup - mouseButton.startTime < 0.2f){Tapped?.Invoke(mouseButton);}Released?.Invoke(mouseButton);}}}// Mouse wheelif (Mathf.Abs(UnityInput.GetAxis("Mouse ScrollWheel")) > Mathf.Epsilon){SpunWheel?.Invoke(new WheelInfo{zoomAmount = UnityInput.GetAxis("Mouse ScrollWheel")});}}private void OnDisable(){for (int i = 0; i < m_MouseInfo.Count; i++){m_MouseInfo[i].isDown = false;}m_Touches.Clear();}/// <summary>/// Update all touches/// </summary>private void UpdateTouches(){ClearNoUseTouchInWebGL();TouchPressedThisFrame = false;for (int i = 0; i < UnityInput.touchCount; ++i){Touch touch = UnityInput.GetTouch(i);// Find existing touch, or create new oneTouchInfo existingTouch = m_Touches.FirstOrDefault(t => t.touchId == touch.fingerId);if (existingTouch == null){existingTouch = new TouchInfo{touchId = touch.fingerId,startPosition = touch.position,currentPosition = touch.position,previousPosition = touch.position,startTime = Time.realtimeSinceStartup,startedOverUI = EventSystem.current.IsPointerOverGameObject(touch.fingerId)};m_Touches.Add(existingTouch);}switch (touch.phase){case TouchPhase.Began:TouchPressedThisFrame = true;Pressed?.Invoke(existingTouch);break;case TouchPhase.Moved:bool wasDrag = existingTouch.isDrag;UpdateMovingFinger(touch, existingTouch);// Is this a drag?existingTouch.isDrag = existingTouch.totalMovement >= 5f;if (existingTouch.isDrag){if (existingTouch.isHold){existingTouch.wasHold = existingTouch.isHold;existingTouch.isHold = false;}// Did it just start now?if (!wasDrag){StartedDrag?.Invoke(existingTouch);}Dragged?.Invoke(existingTouch);if (existingTouch.delta.sqrMagnitude > 2f * 2f){existingTouch.flickVelocity = existingTouch.flickVelocity * 0.2f + existingTouch.delta * 0.8f;}else{existingTouch.flickVelocity = Vector2.zero;}}else{UpdateHoldingFinger(existingTouch);}break;case TouchPhase.Canceled:case TouchPhase.Ended:// Could have moved a bitUpdateMovingFinger(touch, existingTouch);// Quick enough (with no drift) to be a tap?if (!existingTouch.isDrag && Time.realtimeSinceStartup - existingTouch.startTime < 0.2f){Tapped?.Invoke(existingTouch);}Released?.Invoke(existingTouch);// Remove from track listm_Touches.Remove(existingTouch);break;case TouchPhase.Stationary:UpdateMovingFinger(touch, existingTouch);UpdateHoldingFinger(existingTouch);existingTouch.flickVelocity = Vector2.zero;break;}}if (ActiveTouchCount >= 2 && (m_Touches[0].isDrag || m_Touches[1].isDrag)){Pinched?.Invoke(new PinchInfo{touch1 = m_Touches[0],touch2 = m_Touches[1]});}}/// <summary>/// 清除webgl上多指离开屏幕,但是未触发离开事件,导致的无效触控信息/// </summary>private void ClearNoUseTouchInWebGL(){#if UNITY_WEBGLif (m_Touches.Count == 0){return;}// 找出没有用到的TouchesList<TouchInfo> noUseTouches = new List<TouchInfo>(m_Touches.ToArray());for (int i = 0; i < UnityInput.touchCount; ++i){Touch touch = UnityInput.GetTouch(i);// Find existing touchTouchInfo existingTouch = noUseTouches.FirstOrDefault(t => t.touchId == touch.fingerId);if (existingTouch != null){noUseTouches.Remove(existingTouch);}}// 进行移除(执行移除相关的事件后再移除)for (int i = 0; i < noUseTouches.Count; i++){TouchInfo noUseTouchInfo = noUseTouches[i];TouchInfo existingTouch = m_Touches.FirstOrDefault(t => t.touchId == noUseTouchInfo.touchId);if (existingTouch != null){m_Touches.Remove(existingTouch);}}
#endif}/// <summary>/// Update a TouchInfo that might be holding/// </summary>/// <param name="existingTouch"></param>private void UpdateHoldingFinger(PointerActionInfo existingTouch){if (!existingTouch.isHold && !existingTouch.isDrag && Time.realtimeSinceStartup - existingTouch.startTime >= 0.8f){existingTouch.isHold = true;StartedHold?.Invoke(existingTouch);}}/// <summary>/// Update a TouchInfo with movement/// </summary>/// <param name="touch">The Unity touch object</param>/// <param name="existingTouch">The object that's tracking Unity's touch</param>private void UpdateMovingFinger(Touch touch, PointerActionInfo existingTouch){existingTouch.previousPosition = existingTouch.currentPosition;existingTouch.currentPosition = touch.position;existingTouch.delta = existingTouch.currentPosition - existingTouch.previousPosition;existingTouch.totalMovement += existingTouch.delta.magnitude;}}#region 输入相关类/// <summary>/// Class to track information about a passive pointer input/// </summary>public abstract class PointerInfo{/// <summary>/// Current pointer position/// </summary>public Vector2 currentPosition;/// <summary>/// Previous frame's pointer position/// </summary>public Vector2 previousPosition;/// <summary>/// Movement delta for this frame/// </summary>public Vector2 delta;/// <summary>/// Tracks if this pointer began over UI/// </summary>public bool startedOverUI;}/// <summary>/// Class to track information about an active pointer input/// </summary>public class PointerActionInfo : PointerInfo{/// <summary>/// Position where the input started/// </summary>public Vector2 startPosition;/// <summary>/// Flick velocity is a moving average of deltas/// </summary>public Vector2 flickVelocity;/// <summary>/// Total movement for this pointer, since being held down/// </summary>public float totalMovement;/// <summary>/// Time hold started/// </summary>public float startTime;/// <summary>/// Has this input been dragged?/// </summary>public bool isDrag;/// <summary>/// Is this input holding?/// </summary>public bool isHold;/// <summary>/// Was this input previously holding, then dragged?/// </summary>public bool wasHold;}/// <summary>/// Information about a pinch gesture/// </summary>public struct PinchInfo{/// <summary>/// The first touch involved in the pinch/// </summary>public TouchInfo touch1;/// <summary>/// The second touch involved in the pinch/// </summary>public TouchInfo touch2;}/// <summary>/// Touch info/// </summary>public class TouchInfo : PointerActionInfo{/// <summary>/// Our touch ID/// </summary>public int touchId;}class MouseCursorInfo : PointerInfo{}/// <summary>/// Info for mouse/// </summary>public class MouseButtonInfo : PointerActionInfo{/// <summary>/// Is this mouse button down/// </summary>public bool isDown;/// <summary>/// Our mouse button id/// </summary>public int mouseButtonId;}/// <summary>/// Information about a zoom action (usually mouse-wheel or button based)/// </summary>public struct WheelInfo{/// <summary>/// Amount of zoom/// </summary>public float zoomAmount;}#endregion
}

动态控制相机的位置

下面展示一些 内联代码片

using Ardez.Hotfix;
using ArdezEvent;
using UnityEngine;
using UnityEngine.EventSystems;
using zSpace.Core;namespace CamControl
{public enum ZoomPanPolicy{/// <summary>/// 沿着视野正对的平面平移/// </summary>LockToScreenAlignedPlane = 0,/// <summary>/// 沿着目标所在的XZ平面平移(水平面移动)/// </summary>LockTargetPlane = 1,}[RequireComponent(typeof(InputController))][DefaultExecutionOrder(ZCameraRig.ScriptPriority - 1)]public class CameraControl : MonoBehaviour{[SerializeField, Tooltip("ZFrame,用于控制缩放")]private ZFrame m_ZFrame = null;[SerializeField, Tooltip("主相机ZCamera")]private Camera m_MainCamera = null;[SerializeField, Tooltip("缩放范围,默认1视野最小适合观察小模型,20视野最大适合观察大模型")]private Vector2 m_ZoomRange = new Vector2(1, 20);[SerializeField, Tooltip("垂直方向最小值和最大值")]private Vector2 m_AngleLimit = new Vector2(-20f, 80f);[SerializeField, Tooltip("缩放速率")]private float m_ZoomRate = 60f;[SerializeField, Tooltip("平移策略(大地形建议使用LockTargetPlane方式,只在目标点XZ平面上移动)")]private ZoomPanPolicy m_ZoomPanPolicy = ZoomPanPolicy.LockToScreenAlignedPlane;[SerializeField, Tooltip("放大时的移动速率")]private float m_ZoomPanRate = 65f;[SerializeField, Tooltip("水平方向旋转速率")]private float m_HorizontalRotateRate = 60;[SerializeField, Tooltip("垂直方向旋转速率")]private float m_VerticalRotateRate = 30;[SerializeField]private float RotateLerpSpeed = 4f;[SerializeField]private float ZoomLerpSpeed = 4f;[SerializeField]private float MoveLerpSpeed = 4f;[SerializeField, Tooltip("是否使用角度插值")]private bool m_UseAngleLerp = false;                                    // 是否使用角度插值[SerializeField, Tooltip("非zSpace是否使用缩放平移")]private bool m_UseZoomMove = false;                                     // 是否使用缩放平移[SerializeField]private bool m_IgnoreStartOverUI = false;                               // 是否忽略从UI上面开始滑动private InputController m_InputController;private Vector3 m_StartPosition;                                // 初始位置private Vector3 m_StartAngles;                                  // 初始角度private float m_StartZoomScale;                                 // 初始缩放private float m_CurrentZoomScale;                               // 当前的ZFrame缩放private float m_DesiredZoomScale;                               // 期望的ZFrame缩放private float m_StartAxisZValue;                                // 初始Z轴距离private float m_CurrentAxisZValue;private float m_DesiredAxisZValue;private Vector3 m_CurrentAngles;                                // 当前角度private Vector3 m_DesiredAngles;                                // 期望角度private Vector3 m_CurrentPosition;                              // CameraControl当前位置(缩放平移用)private Vector3 m_DesiredPosition;                              // CameraControl期望位置(缩放平移用)public float ZoomMaxRange => m_ZoomRange.y - m_ZoomRange.x;private void Awake(){if (m_MainCamera == null){m_MainCamera = Camera.main;}// 初始化参数m_StartPosition = m_CurrentPosition = m_DesiredPosition = transform.position;m_StartZoomScale = m_CurrentZoomScale = m_DesiredZoomScale = m_ZFrame.ViewerScale;m_StartAxisZValue = m_CurrentAxisZValue = m_DesiredAxisZValue = m_ZFrame.transform.parent.localPosition.z;m_CurrentAngles = m_DesiredAngles = transform.eulerAngles;Revert();// 订阅拖拽、滚轮、双指捏合事件、笔按下事件m_InputController = GetComponent<InputController>();m_InputController.Dragged += Dragged;m_InputController.SpunWheel += SpunWheel;m_InputController.Pinched += Pinched;m_InputController.ZStylusPressed += ZStylusPressed;// 订阅复位事件//EventUtil.AddListener(EventID.EVENT_REFRESHBTN, OnRevert);}private void OnRevert(ArdezEvent.EventArgs eventArgs){Revert();}private void ZStylusPressed(int buttonId){if (buttonId == 2){//m_UseAngleLerp = true;// 左键m_DesiredAngles.y -= 30f;}else if (buttonId == 1){// m_UseAngleLerp = true;// 右键m_DesiredAngles.y += 30f;}if (m_UseAngleLerp){//m_DesiredAngles.y = WrapAngle360(m_DesiredAngles.y);//m_CurrentAngles.y = WrapAngle360(m_CurrentAngles.y);//m_UseAngleLerp = false;}}/// <summary>/// 设置新的目标位置/// </summary>/// <param name="viewConfig">视野配置</param>public void SetNewPos(ViewConfig viewConfig){SetNewPos(viewConfig.transform, viewConfig.TargetDis, viewConfig.TargetZValue, viewConfig.MinViewScale, viewConfig.MaxViewScale, viewConfig.MinAngle, viewConfig.MaxAngle, viewConfig.UseSmoothMove);SetUseZoomMove(viewConfig.UseZoomMove);}/// <summary>/// 设置是否使用缩放平移/// </summary>public void SetUseZoomMove(bool useZoomMove){m_UseZoomMove = useZoomMove;}/// <summary>/// 设置新的目标位置/// </summary>/// <param name="targetTrans">目标Transform</param>/// <param name="targetZFrameViewScale">相机缩放</param>/// <param name="targetZSpaceAxisZValue">zSpace局部Z坐标,非zSpace设备上固定为0</param>/// <param name="minViewScale">相机最小缩放值,默认为1,物体显得很大</param>/// <param name="maxViewScale">相机最大缩放值,默认为20, 物体显得很小</param>/// <param name="minAngle">相机垂直方向最小角度,默认-20</param>/// <param name="maxAngle">相机垂直方向最大角度,默认80</param>public void SetNewPos(Transform targetTrans, float? targetZFrameViewScale = null, float? targetZSpaceAxisZValue = null, float? minViewScale = null, float? maxViewScale = null, float? minAngle = null, float? maxAngle = null, bool useSmoothMove = true){SetNewPos(targetTrans.position, targetTrans.eulerAngles, targetZFrameViewScale, targetZSpaceAxisZValue, minViewScale, maxViewScale, minAngle, maxAngle, useSmoothMove);}/// <summary>/// 设置新的目标位置/// </summary>/// <param name="position">目标位置</param>/// <param name="eulerAngles">目标位置的欧拉角</param>/// <param name="targetZFrameViewScale">相机缩放</param>/// <param name="targetZSpaceAxisZValue">zSpace局部Z坐标,非zSpace设备上固定为0</param>/// <param name="minViewScale">相机最小缩放值,默认为1,物体显得很大</param>/// <param name="maxViewScale">相机最大缩放值,默认为20, 物体显得很小</param>/// <param name="minAngle">相机垂直方向最小角度,默认-20</param>/// <param name="maxAngle">相机垂直方向最大角度,默认80</param>public void SetNewPos(Vector3 position, Vector3 eulerAngles, float? targetZFrameViewScale = null, float? targetZSpaceAxisZValue = null, float? minViewScale = null, float? maxViewScale = null, float? minAngle = null, float? maxAngle = null, bool useSmoothMove = true){m_StartPosition = position;m_StartAngles = eulerAngles;if (targetZFrameViewScale != null) m_StartZoomScale = targetZFrameViewScale.Value;if (targetZSpaceAxisZValue != null) m_StartAxisZValue = targetZSpaceAxisZValue.Value;if (minViewScale != null) m_ZoomRange.x = minViewScale.Value;if (maxViewScale != null) m_ZoomRange.y = maxViewScale.Value;if (minAngle != null) m_AngleLimit.x = minAngle.Value;if (maxAngle != null) m_AngleLimit.y = maxAngle.Value;if (useSmoothMove == false){m_CurrentPosition = m_DesiredPosition = m_StartPosition;m_CurrentAngles = m_DesiredAngles = m_StartAngles;m_CurrentZoomScale = m_DesiredZoomScale = m_StartZoomScale;m_CurrentAxisZValue = m_DesiredAxisZValue = m_StartAxisZValue;}// 非zSpace设备上固定为0//if (ZProvider.IsInitialized == false)//{//    m_StartAxisZValue = 0f;//}#region 校验// 缩放范围校验if (m_ZoomRange.x > m_ZoomRange.y){Debug.LogErrorFormat("MinViewScale: {0} > MaxViewScale: {1}, 请检查!", m_ZoomRange.x, m_ZoomRange.y);}if (m_StartZoomScale < m_ZoomRange.x){Debug.LogErrorFormat("StartZoomScale: {0} < MinViewScale: {1}, 请检查!", m_StartZoomScale, m_ZoomRange.x);}if (m_StartZoomScale > m_ZoomRange.y){Debug.LogErrorFormat("StartZoomScale: {0} > MaxViewScale: {1}, 请检查!", m_StartZoomScale, m_ZoomRange.y);}// 俯仰角范围校验if (m_AngleLimit.x > m_AngleLimit.y){Debug.LogErrorFormat("MinAngle: {0} > MaxAngle: {1}, 请检查!", m_AngleLimit.x, m_AngleLimit.y);}if (WrapAngle180(m_StartAngles.x) < m_AngleLimit.x){Debug.LogErrorFormat("StartAngle: {0} < MinAngle: {1}, 请检查!", WrapAngle180(m_StartAngles.x), m_AngleLimit.x);}if (WrapAngle180(m_StartAngles.x) > m_AngleLimit.y){Debug.LogErrorFormat("StartAngle: {0} > MaxAngle: {1}, 请检查!", WrapAngle180(m_StartAngles.x), m_AngleLimit.y);}// Z轴坐标校验if (m_StartAxisZValue > 0){Debug.LogErrorFormat("TargetZValue: {0}, 建议使用0或者负值, 请检查!", m_StartAxisZValue);}#endregionRevert();}/// <summary>/// 复位/// </summary>public void Revert(){m_DesiredPosition = m_StartPosition;m_DesiredAngles = m_StartAngles;m_DesiredZoomScale = m_StartZoomScale;m_DesiredAxisZValue = m_StartAxisZValue;m_UseAngleLerp = true;}/// <summary>/// 滑动屏幕旋转/// </summary>private void Dragged(PointerActionInfo pointerActionInfo){if (Input.touchCount > 1){return;}if (m_IgnoreStartOverUI == false && pointerActionInfo.startedOverUI){return;}// 垂直方向,Camera的X轴角度m_DesiredAngles.x -= pointerActionInfo.delta.y * m_VerticalRotateRate * Time.deltaTime;m_DesiredAngles.x = WrapAngle180(m_DesiredAngles.x);m_DesiredAngles.x = Mathf.Clamp(m_DesiredAngles.x, m_AngleLimit.x, m_AngleLimit.y);// 水平方向,Camera的Y轴角度m_DesiredAngles.y += pointerActionInfo.delta.x * m_HorizontalRotateRate * Time.deltaTime;if (m_UseAngleLerp){m_CurrentAngles.y = WrapAngle360(m_CurrentAngles.y);m_DesiredAngles.y = WrapAngle360(m_DesiredAngles.y);m_DesiredAngles.y = FindNearestAngle(m_CurrentAngles.y, m_DesiredAngles.y);m_UseAngleLerp = false;}}/// <summary>/// 滚动鼠标/// </summary>private void SpunWheel(WheelInfo wheelInfo){if (m_IgnoreStartOverUI == false && IsPointerOverUI()){return;}m_DesiredZoomScale -= wheelInfo.zoomAmount * m_ZoomRate * Time.deltaTime * Mathf.Abs(m_DesiredZoomScale);if (m_UseZoomMove){ZoomMove(wheelInfo.zoomAmount, Input.mousePosition);}}/// <summary>/// 双指捏合缩放/// </summary>private void Pinched(PinchInfo pinchInfo){if (m_IgnoreStartOverUI == false && (pinchInfo.touch1.startedOverUI || pinchInfo.touch2.startedOverUI)){return;}Vector2 center = 0.5f * (pinchInfo.touch1.currentPosition + pinchInfo.touch2.currentPosition);float currentDistance = (pinchInfo.touch1.currentPosition - pinchInfo.touch2.currentPosition).magnitude;float prevDistance = (pinchInfo.touch1.previousPosition - pinchInfo.touch2.previousPosition).magnitude;float zoomChange = prevDistance / currentDistance;float zoomAmount = 1 - zoomChange;m_DesiredZoomScale -= zoomAmount * m_ZoomRate * Time.deltaTime * Mathf.Abs(m_DesiredZoomScale);if (m_UseZoomMove){ZoomMove(zoomAmount, center);}}/// <summary>/// 放大时平移到鼠标指定位置,缩小时平移到初始位置/// </summary>private void ZoomMove(float zoomAmount, Vector2 center){m_DesiredZoomScale = Mathf.Clamp(m_DesiredZoomScale, m_ZoomRange.x, m_ZoomRange.y);if (zoomAmount > 0 && m_DesiredZoomScale > m_ZoomRange.x){// 放大,平移至center位置Ray ray = m_MainCamera.ScreenPointToRay(center);Plane plane = new Plane(transform.forward, transform.position);switch (m_ZoomPanPolicy){case ZoomPanPolicy.LockToScreenAlignedPlane:plane = new Plane(transform.forward, transform.position);break;case ZoomPanPolicy.LockTargetPlane:plane = new Plane(Vector3.up, transform.position);break;}if (plane.Raycast(ray, out float enter)){Vector3 mousePoint = ray.GetPoint(enter);Vector3 direction = mousePoint - transform.position;float length = Mathf.Min(direction.magnitude, 50f);m_DesiredPosition += m_ZoomPanRate * zoomAmount * Time.deltaTime * length * direction.normalized;}}else if (zoomAmount < 0 && m_DesiredZoomScale < m_ZoomRange.y){// 缩小,复位到初始位置m_DesiredPosition = Vector3.Lerp(m_DesiredPosition, m_StartPosition, Time.deltaTime * GetZoomRate() * 10f);}}private void Update(){// 复位和切换位置时使用角度插值if (m_UseAngleLerp){m_CurrentAngles.y = Mathf.LerpAngle(m_CurrentAngles.y, m_DesiredAngles.y, Time.deltaTime * RotateLerpSpeed);}else{m_CurrentAngles.y = Mathf.Lerp(m_CurrentAngles.y, m_DesiredAngles.y, Time.deltaTime * RotateLerpSpeed);}m_CurrentAngles.x = Mathf.LerpAngle(m_CurrentAngles.x, m_DesiredAngles.x, Time.deltaTime * RotateLerpSpeed);transform.eulerAngles = m_CurrentAngles;// 缩放m_DesiredZoomScale = Mathf.Clamp(m_DesiredZoomScale, m_ZoomRange.x, m_ZoomRange.y);m_CurrentZoomScale = Mathf.Lerp(m_CurrentZoomScale, m_DesiredZoomScale, Time.deltaTime * ZoomLerpSpeed);m_ZFrame.ViewerScale = m_CurrentZoomScale;// z坐标m_CurrentAxisZValue = Mathf.Lerp(m_CurrentAxisZValue, m_DesiredAxisZValue, Time.deltaTime * ZoomLerpSpeed);SetLocalPositionZ(m_ZFrame.transform.parent, m_CurrentAxisZValue);// 位置m_CurrentPosition = Vector3.Lerp(m_CurrentPosition, m_DesiredPosition, Time.deltaTime * MoveLerpSpeed);transform.position = m_CurrentPosition;}#region 工具方法/// <summary>/// 是否点在UI上/// </summary>private bool IsPointerOverUI(){return EventSystem.current.IsPointerOverGameObject();}/// <summary>/// 角度转换(-180到180)/// </summary>private float WrapAngle180(float angle){angle %= 360;if (angle > 180){angle -= 360;}return angle;}/// <summary>/// 角度转换(0到360)/// </summary>private float WrapAngle360(float angle){angle %= 360;if (angle < 0){angle += 360;}return angle;}/// <summary>/// 找最快到达的角度,例如10°到180°,直接10插值到180就是最快/// 例如10°到200°,那么10直接插值到200,就不如10插值到-160°快/// </summary>/// <param name="current">输入范围0-360°</param>/// <param name="target">输入范围0-360°</param>/// <returns></returns>private float FindNearestAngle(float current, float target){float min = target - current;if (min > 180){target -= 360;}if (min < -180){target += 360;}return target;}/// <summary>/// 根据zoom获取比例/// </summary>private float GetZoomRate(){return 1 - (m_DesiredZoomScale - m_ZoomRange.x) / ZoomMaxRange;}/// <summary>/// 设置局部Z坐标/// </summary>private void SetLocalPositionZ(Transform target, float newValue){Vector3 v = target.localPosition;v.z = newValue;target.localPosition = v;}#endregion}
}

图片:

Unity 在zSpace上使用鼠标控制相机旋转和鼠标指引式放大缩小,在触屏上手势位置为中心放大缩小相关推荐

  1. unity鼠标控制镜头旋转_unity3D鼠标滚轮来实现镜头拉近拉远及视角旋转

    镜头拉近拉远的代码(无限拉远拉近) 代码如下: if( Input.GetAxis("Mouse ScrollWheel") != 0 ) { this.gameObject.tr ...

  2. Unity 基础 之 鼠标控制 相机(摄像机Camera)的旋转,移动和 fov 的简单使用整理

    Unity 基础 之 鼠标控制 相机(摄像机Camera)的旋转,移动和 fov 的简单使用整理 目录 Unity 基础 之 鼠标控制 相机(摄像机Camera)的旋转,移动和 fov 的简单使用整理 ...

  3. Unity Window触摸屏电脑和移动端Input触控,控制相机旋转缩放

    Unity Window触摸屏电脑和移动端Input触控,控制相机旋转缩放 原理就是获取手指滑动的偏移量,来计算 代码帖出来 using UnityEngine; using System; usin ...

  4. Unity3d实现鼠标控制相机绕物体旋转(带阻尼)

    Unity3d实现鼠标控制相机绕物体旋转(带阻尼) 本来想的是用四元数实现球性插值实现阻尼效果,但是不知道四元数怎么绕定点旋转.因此用速度衰减的方法进行实现. 1.实现鼠标控制相机带阻尼旋转 2.实现 ...

  5. Cesium 键盘鼠标控制相机漫游(源码+原理讲解)

    Cesium 键盘鼠标控制相机漫游(源码+原理讲解) 在各大博客平台上,Cesium使用键盘控制相机漫游的源码已经有不少人贴出源码,本人在浏览这些源码的过程中发现大家采用的方式基本一致,大部分代码都是 ...

  6. 3d 数学(叉乘、四元素、四元素旋转、四元素和四元素相乘、鼠标控制物体旋转、发射子弹、环形发射子弹、子弹缓冲池)

    目录 1.叉乘 2.四元素 3.四元素旋转 4.四元素和四元素相乘 5.鼠标控制物体旋转 6.发射子弹 7.环形发射子弹 8.子弹缓冲池 1.叉乘 两个向量叉乘,得到一个新的向量,新向量跟原始两个向量 ...

  7. OpenGL之鼠标控制坐标系旋转、缩放、移动

    OpenGL之鼠标控制坐标系旋转.缩放.移动 1.实现代码 void CMyStatic::OnMouseMove(UINT nFlags, CPoint point) { // TODO: 在此添加 ...

  8. WPF技术触屏上的应用系列(二): 嵌入百度地图、API调用及结合本地数据库在地图上进行自定义标点的实现...

    原文:WPF技术触屏上的应用系列(二): 嵌入百度地图.API调用及结合本地数据库在地图上进行自定义标点的实现 去年某客户单位要做个大屏触屏应用,要对档案资源进行展示之用.客户端是Window7操作系 ...

  9. boostrap 鼠标滚轮滑动图片_Bootstrap幻灯片轮播图支持触屏左右手势滑动的实现方法...

    最近ytkah在学习用bootstrap搭建网站,Bootstrap能自适应pc端和手机端,并且移动设备优先,适合现如今移动营销.bootstrap是封装好的框架,需要某些功能只需调用相应的组件就可以 ...

最新文章

  1. Python基础(1) - 初识Python
  2. STM32 不断进入串口中断问题 解决方法
  3. COG、XR、X5R、Y5V电容器分类
  4. android左右旋转动画效果图,Android新姿势:3D翻转效果原理
  5. SqlServer 时间格式化
  6. 字符串处理 —— AC 自动机
  7. UI设计实用临摹素材|APP设计的信息可视化!
  8. java正则表达式 后顾,正则表达式:从Copy到手写
  9. Java之正則表達式【使用语法】
  10. CSND如何转载别人的文章
  11. 心理们-位大师的50本书
  12. 基于多任务深度学习的时空网络流量预测
  13. 表格OCR相关资源整理【ICDAR】【表格识别】【持续更新...】
  14. 初入编程 - HTML + CSS
  15. 电容充放电时间的计算方法(重点是对于恒流充放电的常用公式:⊿Vc=I*⊿t/C,其出自公式:Vc=Q/C=I*t/C。)电荷泵(无电感)中电容恒流放电的滤波可以参考4-20毫安的采集中RC滤波电路
  16. tmdb电影票房_TMDb Vue.js应用程序:电影数据库应用程序
  17. 【服务器数据恢复】服务器断电导致RAID报错的数据恢复案例
  18. c语言13 6,C语言学习笔记13
  19. 麒麟系统挂载文件、麒麟系统挂载windows共享文件夹
  20. C#窗体控件—pictureBox使用

热门文章

  1. 如何设置弧度 html,JavaScript中弧度和角度的转换
  2. CSDN社群专属公开课课表
  3. 易企秀上传图片不成功!提示非法图片,问题解决!
  4. Java中重写和重载有哪些区别
  5. challenge是什么意思_challenge是什么意思_challenge中文意思_challenge英译汉_英汉词典...
  6. 第一条台电子计算机,2001年4月全国计算机等级考试一级笔试试题Windows
  7. CodeCraft-19 and Codeforces Round #537 (Div. 2) Editorial
  8. python中星号(*)的用法
  9. 高等代数_证明_两个矩阵乘积为0,则两个矩阵的秩之和小于等于n
  10. 区块链技术交流群,欢迎大家进群交流