From 83ce65aec08bb49f2bbbf84ff42ad2b1d2e02e62 Mon Sep 17 00:00:00 2001 From: Jakob Feldmann Date: Tue, 14 May 2024 14:56:40 +0200 Subject: [PATCH] fix: smoother and faster zoom for the MatchCamera --- Assets/Prefabs/Match Camera.prefab | 226 ++++++++++++++++++++++++ Assets/Prefabs/Match Camera.prefab.meta | 7 + Assets/Scripts/CameraOperator.cs | 124 ++++++++----- 3 files changed, 316 insertions(+), 41 deletions(-) create mode 100644 Assets/Prefabs/Match Camera.prefab create mode 100644 Assets/Prefabs/Match Camera.prefab.meta diff --git a/Assets/Prefabs/Match Camera.prefab b/Assets/Prefabs/Match Camera.prefab new file mode 100644 index 0000000..095782b --- /dev/null +++ b/Assets/Prefabs/Match Camera.prefab @@ -0,0 +1,226 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &8410204819688929699 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 3759513694494416429} + - component: {fileID: 2058217877728095057} + - component: {fileID: 1721132222636882756} + - component: {fileID: 3108387510587612718} + - component: {fileID: 5958274672626741238} + m_Layer: 0 + m_Name: Match Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &3759513694494416429 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8410204819688929699} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -35} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 7402812915359008431} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!20 &2058217877728095057 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8410204819688929699} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0, g: 0, b: 0, a: 1} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_Iso: 200 + m_ShutterSpeed: 0.005 + m_Aperture: 16 + m_FocusDistance: 10 + m_FocalLength: 17.185572 + m_BladeCount: 5 + m_Curvature: {x: 2, y: 11} + m_BarrelClipping: 0.25 + m_Anamorphism: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.01 + far clip plane: 5000 + field of view: 65 + orthographic: 0 + orthographic size: 100 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 1 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!81 &1721132222636882756 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8410204819688929699} + m_Enabled: 1 +--- !u!114 &3108387510587612718 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8410204819688929699} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 20df0926ff00f0e4dab5fd8ea03a31d2, type: 3} + m_Name: + m_EditorClassIdentifier: + MaxAdditionalDistance: 22 + FarOutBias: 0.1 + MaxFollowDistance: -1 + FollowSpeed: 2 + TiltFactor: 1.5 + ZoomOutMargin: 0.8 + ZoomInMargin: 0.3 + MinZoomSpeed: 0.8 + MaxZoomSpeed: 0.8 + TimeUntilZoomIn: 0.3 + TimeUntilZoomOut: 0.3 +--- !u!114 &5958274672626741238 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8410204819688929699} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: a79441f348de89743a2939f4d699eac1, type: 3} + m_Name: + m_EditorClassIdentifier: + m_RenderShadows: 0 + m_RequiresDepthTextureOption: 0 + m_RequiresOpaqueTextureOption: 1 + m_CameraType: 0 + m_Cameras: [] + m_RendererIndex: 0 + m_VolumeLayerMask: + serializedVersion: 2 + m_Bits: 1 + m_VolumeTrigger: {fileID: 0} + m_VolumeFrameworkUpdateModeOption: 2 + m_RenderPostProcessing: 1 + m_Antialiasing: 0 + m_AntialiasingQuality: 2 + m_StopNaN: 0 + m_Dithering: 0 + m_ClearDepth: 1 + m_AllowXRRendering: 1 + m_AllowHDROutput: 1 + m_UseScreenCoordOverride: 0 + m_ScreenSizeOverride: {x: 0, y: 0, z: 0, w: 0} + m_ScreenCoordScaleBias: {x: 0, y: 0, z: 0, w: 0} + m_RequiresDepthTexture: 0 + m_RequiresColorTexture: 0 + m_Version: 2 + m_TaaSettings: + quality: 3 + frameInfluence: 0.1 + jitterScale: 1 + mipBias: 0 + varianceClampScale: 0.9 + contrastAdaptiveSharpening: 0 +--- !u!1001 &60773133580181416 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 3759513694494416429} + m_Modifications: + - target: {fileID: 3749816391370857719, guid: 86949d7de375bf64a812cbb78cab3b0a, type: 3} + propertyPath: m_Name + value: Star Particles + objectReference: {fileID: 0} + - target: {fileID: 7380269251330496775, guid: 86949d7de375bf64a812cbb78cab3b0a, type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7380269251330496775, guid: 86949d7de375bf64a812cbb78cab3b0a, type: 3} + propertyPath: m_LocalPosition.y + value: -100 + objectReference: {fileID: 0} + - target: {fileID: 7380269251330496775, guid: 86949d7de375bf64a812cbb78cab3b0a, type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7380269251330496775, guid: 86949d7de375bf64a812cbb78cab3b0a, type: 3} + propertyPath: m_LocalRotation.w + value: 0.24189089 + objectReference: {fileID: 0} + - target: {fileID: 7380269251330496775, guid: 86949d7de375bf64a812cbb78cab3b0a, type: 3} + propertyPath: m_LocalRotation.x + value: -0.18702833 + objectReference: {fileID: 0} + - target: {fileID: 7380269251330496775, guid: 86949d7de375bf64a812cbb78cab3b0a, type: 3} + propertyPath: m_LocalRotation.y + value: -0.6103804 + objectReference: {fileID: 0} + - target: {fileID: 7380269251330496775, guid: 86949d7de375bf64a812cbb78cab3b0a, type: 3} + propertyPath: m_LocalRotation.z + value: -0.7307155 + objectReference: {fileID: 0} + - target: {fileID: 7380269251330496775, guid: 86949d7de375bf64a812cbb78cab3b0a, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 280.732 + objectReference: {fileID: 0} + - target: {fileID: 7380269251330496775, guid: 86949d7de375bf64a812cbb78cab3b0a, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: -6.773 + objectReference: {fileID: 0} + - target: {fileID: 7380269251330496775, guid: 86949d7de375bf64a812cbb78cab3b0a, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: -137.755 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: 86949d7de375bf64a812cbb78cab3b0a, type: 3} +--- !u!4 &7402812915359008431 stripped +Transform: + m_CorrespondingSourceObject: {fileID: 7380269251330496775, guid: 86949d7de375bf64a812cbb78cab3b0a, type: 3} + m_PrefabInstance: {fileID: 60773133580181416} + m_PrefabAsset: {fileID: 0} diff --git a/Assets/Prefabs/Match Camera.prefab.meta b/Assets/Prefabs/Match Camera.prefab.meta new file mode 100644 index 0000000..348a15e --- /dev/null +++ b/Assets/Prefabs/Match Camera.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 6d819d49a851e2c47b79a5964f456027 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/CameraOperator.cs b/Assets/Scripts/CameraOperator.cs index 4332056..ab584b7 100644 --- a/Assets/Scripts/CameraOperator.cs +++ b/Assets/Scripts/CameraOperator.cs @@ -4,6 +4,8 @@ using System.Collections.Generic; using System.Data.Common; using System.Linq; using System.Reflection; +using Edgegap.Editor; +using GameKit.Dependencies.Utilities; using log4net; using PrimeTween; using Unity.Mathematics; @@ -32,13 +34,25 @@ public class CameraOperator : MonoBehaviour [Tooltip("Lower values make the camera tilt harder to keep the mid point centered")] private float TiltFactor = 1.5f; [SerializeField] - private float ZoomOutMargin = Screen.height / 4; + [Range(0.0f, 1f)] + private float ZoomOutMargin = 0.5f; [SerializeField] - private float ZoomInMargin = Screen.height / 3; + [Range(0.0f, 1f)] + private float ZoomInMargin = 0.3f; [SerializeField] - private float MinZoomSpeed = 0.4f; + private float ZoomInSpeed = 0.4f; [SerializeField] - private float MaxZoomSpeed = 0.5f; + private float ZoomOutSpeed = 0.5f; + [SerializeField] + private float TimeUntilZoomIn = 0.3f; + [SerializeField] + private float TimeUntilZoomOut = 0.3f; + + + private float _switchZoomInTime = 0f; + private float _switchZoomOutTime = 0f; + private Vector2 _zoomInPixels = new(); + private Vector2 _zoomOutPixels = new(); private Vector3 _currentZoomSpeed = Vector3.zero; @@ -56,6 +70,16 @@ public class CameraOperator : MonoBehaviour // Distance here is in the negative direction on the z axis InitialDistance = transform.localPosition.z; MaxDistance = InitialDistance - MaxAdditionalDistance; + _zoomInPixels.x = Screen.width * 0.5f * ZoomInMargin; + _zoomInPixels.y = Screen.height * 0.5f * ZoomInMargin; + _zoomOutPixels.x = Screen.width * 0.5f * ZoomOutMargin; + _zoomOutPixels.y = Screen.height * 0.5f * ZoomOutMargin; + } + + public void ShakeCam(float strength = 0.1f, float duration = 0.05f, float frequency = 50f) + { + Tween.ShakeLocalPosition(cam.transform, new Vector2(strength, strength), duration, frequency); + //Tween.ShakeLocalRotation(cam.transform, new Vector2(strength, strength), duration); } public void AddCharacter(GameObject ship) @@ -77,7 +101,10 @@ public class CameraOperator : MonoBehaviour /// private void FixedUpdate() { + Vector3 center = CalculatePlayersCenter(); + if (center.IsNan()) + return; if (players.Count == 1) { FollowPosition(players.First().Value.transform.localPosition); @@ -117,7 +144,6 @@ public class CameraOperator : MonoBehaviour } center /= players.Count(); - // TODO: Competing furthest points cause jitter if (FarOutBias > 0 && players.Count > 2) { center += (center - furthestPoint) * FarOutBias; @@ -133,6 +159,8 @@ public class CameraOperator : MonoBehaviour var z = center.z; x /= players.Count(); y /= players.Count(); + + float a = z - transform.localPosition.z * TiltFactor; float cXAxis = (float)Sqrt(Pow(a, 2) + Pow(x, 2)); float cYAxis = (float)Sqrt(Pow(a, 2) + Pow(y, 2)); @@ -151,7 +179,6 @@ public class CameraOperator : MonoBehaviour { return; } - float Margin = Screen.height / 2; float maxXDistance = 0; float maxYDistance = 0; @@ -183,59 +210,74 @@ public class CameraOperator : MonoBehaviour return; } - float maxXPos = 0; - float maxYPos = 0; - float minXPos = -1; - float minYPos = -1; + Vector2 maxDistance = new Vector2(0, 0); + Vector2 minDistance = new Vector2(-1, -1); foreach (GameObject player in players.Values) { var screenPos = cam.WorldToScreenPoint(player.transform.position); - if (minXPos == -1) - minXPos = screenPos.x; - if (minYPos == -1) - minYPos = screenPos.y; - if (screenPos.x < minXPos) - minXPos = screenPos.x; - if (screenPos.y < minYPos) - minYPos = screenPos.y; - if (screenPos.x > maxXPos) - maxXPos = screenPos.x; - if (screenPos.y > maxYPos) - maxYPos = screenPos.y; + var screenMiddle = new Vector2(Screen.width / 2, Screen.height / 2); + var distance = new Vector2 + { + x = Math.Abs(screenMiddle.x - screenPos.x), + y = Math.Abs(screenMiddle.y - screenPos.y) + }; + + if (minDistance.x == -1) + minDistance.x = distance.x; + if (minDistance.y == -1) + minDistance.y = distance.y; + + if (distance.x < minDistance.x) + minDistance.x = distance.x; + if (distance.y < minDistance.y) + minDistance.y = distance.y; + + if (distance.x > maxDistance.x) + maxDistance.x = distance.x; + if (distance.y > maxDistance.y) + maxDistance.y = distance.y; } + //Log.Debug(maxDistance); - - - if (maxXPos < Screen.width - ZoomInMargin - && maxYPos < Screen.height - ZoomInMargin - && minXPos > ZoomInMargin - && minYPos > ZoomInMargin) - // Anti-Shake - // && (ZoomTriggerXDistance < maxXDistance - 3f - // || ZoomTriggerYDistance < maxYDistance - 3f)) + if (maxDistance.x < _zoomInPixels.x + && maxDistance.y < _zoomInPixels.y) { + _switchZoomOutTime = TimeUntilZoomOut; + if (_switchZoomInTime > 0) + { + _switchZoomInTime -= Time.deltaTime; + return; + } + if (transform.localPosition.z < InitialDistance) { - Vector3 target = transform.localPosition + new Vector3(0, 0, MinZoomSpeed); - transform.localPosition = - Vector3.SmoothDamp(transform.localPosition, target, ref _currentZoomSpeed, 0.0003f); + transform.localPosition += new Vector3(0, 0, ZoomInSpeed); + //Vector3 target = transform.localPosition + new Vector3(0, 0, MinZoomSpeed); + // transform.localPosition = + // Vector3.SmoothDamp(transform.localPosition, target, ref _currentZoomSpeed, 0.0008f); } return; } - if (maxXPos > Screen.width - ZoomOutMargin - || maxYPos > Screen.height - ZoomOutMargin - || minXPos < ZoomOutMargin - || minYPos < ZoomOutMargin) + if (maxDistance.x > _zoomOutPixels.x + || maxDistance.y > _zoomOutPixels.y) { + _switchZoomInTime = TimeUntilZoomIn; + // if (_switchZoomOutTime > 0) + // { + // _switchZoomOutTime -= Time.deltaTime; + // return; + // } + if (transform.localPosition.z > MaxDistance) { - Vector3 target = transform.localPosition - new Vector3(0, 0, MaxZoomSpeed); - transform.localPosition = - Vector3.SmoothDamp(transform.localPosition, target, ref _currentZoomSpeed, 0.0007f); + transform.localPosition -= new Vector3(0, 0, ZoomOutSpeed); + //Vector3.SmoothDamp(transform.localPosition, target, ref _currentZoomSpeed, 0.0003f); + // transform.localPosition = + // Vector3.SmoothDamp(transform.localPosition, target, ref _currentZoomSpeed, MaxZoomSpeed); } }