1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
| using Cysharp.Threading.Tasks; using FairyGUI; using Framework.Runtime; using GameLogic.Battle.Core.Event; using UnityEngine; using Logger = Framework.Base.Logger;
namespace GameLogic.Home { public class CameraInteractionByGesture { private const float _GroundHeight = 0; private const float _SwipeBrakeThreshold = 10 * 10;
private readonly SwipeGesture _swipeGesture; private readonly PinchGesture _pinchGesture;
private Vector2 _screenDelta; private Camera _idleCamera;
public CameraInteractionByGesture(GObject host, Camera camera) { _swipeGesture = new SwipeGesture(host) { snapping = false }; _pinchGesture = new PinchGesture(host); _idleCamera = camera; BindPinch(); BindSwipe(); }
private void BindPinch() { _pinchGesture.onAction.Set(() => new CameraPinchEvent(-_pinchGesture.delta).Fire()); }
private void BindSwipe() { if (_idleCamera!.orthographic) BindSwipeForOrtho(); else BindSwipeForPerspective(); }
# region 正交相机 private void BindSwipeForOrtho() { if (_idleCamera.IsNullPtr()) return; _swipeGesture.onMove.Set(() => { if (_idleCamera.IsNullPtr()) return; #if UNITY_EDITOR if (_idleCamera.orthographic == false) { BindSwipeForPerspective(); return; } #endif _screenDelta = _swipeGesture.delta * GRoot.contentScaleFactor; var worldPerPixel = _idleCamera.orthographicSize * 2f / Screen.height; var backProjection = 1f / Mathf.Sin(_idleCamera.transform.eulerAngles.x * Mathf.Deg2Rad); var deltaXZ = _screenDelta * worldPerPixel; var deltaXYZ = new Vector3(-deltaXZ.x, 0, deltaXZ.y * backProjection); var worldDelta = Quaternion.Euler(0, _idleCamera.transform.eulerAngles.y, 0) * deltaXYZ; new CameraSwipeEvent(new Vector2(worldDelta.x, worldDelta.z), Vector2.zero, CameraSwipeType.Moving).Fire(); }); _swipeGesture.onEnd.Set(() => { if (_idleCamera.IsNullPtr()) return; if (_screenDelta.sqrMagnitude < _SwipeBrakeThreshold) { new CameraSwipeEvent(Vector2.zero, Vector2.zero, CameraSwipeType.Braking).Fire(); return; } var screenVelocity = _swipeGesture.velocity * GRoot.contentScaleFactor; var worldPerPixel = _idleCamera.orthographicSize * 2f / Screen.height; var backProjection = 1f / Mathf.Sin(_idleCamera.transform.eulerAngles.x * Mathf.Deg2Rad); var velocityXZ = screenVelocity * worldPerPixel; var velocityXYZ = new Vector3(-velocityXZ.x, 0, velocityXZ.y * backProjection); var worldVelocity = Quaternion.Euler(0, _idleCamera.transform.eulerAngles.y, 0) * velocityXYZ; new CameraSwipeEvent(Vector2.zero, new Vector2(worldVelocity.x, worldVelocity.z), CameraSwipeType.Braking).Fire(); }); } # endregion
#region 透视相机 private void BindSwipeForPerspective() { if (_idleCamera.IsNullPtr()) return; _swipeGesture.onMove.Set(context => { #if UNITY_EDITOR if (_idleCamera.orthographic) { BindSwipeForOrtho(); return; } #endif if (_idleCamera.IsNullPtr()) return; _screenDelta = _swipeGesture.delta * GRoot.contentScaleFactor;
var currentScreenPos = context.inputEvent.position; var prevScreenPos = currentScreenPos - _screenDelta; var currentUnityScreenPos = new Vector2(currentScreenPos.x, Screen.height - currentScreenPos.y); var prevUnityScreenPos = new Vector2(prevScreenPos.x, Screen.height - prevScreenPos.y);
var worldCurrent = ScreenToWorldPoint(_idleCamera, currentUnityScreenPos); var worldPrev = ScreenToWorldPoint(_idleCamera, prevUnityScreenPos); var realWorldDelta = worldPrev - worldCurrent; new CameraSwipeEvent(new Vector2(realWorldDelta.x, realWorldDelta.z), Vector2.zero, CameraSwipeType.Moving).Fire(); }); _swipeGesture.onEnd.Set(() => { if (_idleCamera.IsNullPtr()) return; if (_screenDelta.sqrMagnitude < _SwipeBrakeThreshold) { new CameraSwipeEvent(Vector2.zero, Vector2.zero, CameraSwipeType.Braking).Fire(); return; } var screenVelocity = _swipeGesture.velocity * GRoot.contentScaleFactor; float distance = CalculateFocusDistance(_idleCamera.transform.rotation * Vector3.forward, _idleCamera.transform.position.y); var viewHeight = Mathf.Tan( Mathf.Deg2Rad * _idleCamera.fieldOfView / 2) * distance * 2f; var worldPerPixel = viewHeight / Screen.height; var backProjection = 1f / Mathf.Sin(_idleCamera.transform.eulerAngles.x * Mathf.Deg2Rad); var velocityXZ = screenVelocity * worldPerPixel; var velocityXYZ = new Vector3(-velocityXZ.x, 0, velocityXZ.y * backProjection); var worldVelocity = Quaternion.Euler(0, _idleCamera.transform.eulerAngles.y, 0) * velocityXYZ; new CameraSwipeEvent(Vector2.zero, new Vector2(worldVelocity.x, worldVelocity.z), CameraSwipeType.Braking).Fire(); }); }
private static Vector3 ScreenToWorldPoint(Camera camera, Vector2 screenPos) { Ray ray = camera.ScreenPointToRay(screenPos); var dir = ray.direction; var depth = CalculateFocusDistance(dir, camera.transform.position.y); return ray.GetPoint(depth); }
private static float CalculateFocusDistance(Vector3 dir, float cameraY) { Vector3 forward = dir.normalized; if (Mathf.Abs(forward.y) < 0.001f) return 10; float heightDiff = _GroundHeight - cameraY; float distance = heightDiff / forward.y; return distance; } #endregion } }
|