Files
pgs/Assets/ProCamera2D/Code/Extensions/ProCamera2DSpeedBasedZoom.cs

129 lines
4.8 KiB
C#
Raw Permalink Normal View History

2026-02-21 16:58:22 -08:00
using UnityEngine;
namespace Com.LuisPedroFonseca.ProCamera2D
{
#if UNITY_5_3_OR_NEWER
[HelpURLAttribute("http://www.procamera2d.com/user-guide/extension-speed-based-zoom/")]
#endif
public class ProCamera2DSpeedBasedZoom : BasePC2D, ISizeDeltaChanger
{
public static string ExtensionName = "Speed Based Zoom";
[Tooltip("The speed at which the camera will reach it's max zoom out.")]
public float CamVelocityForZoomOut = 5f;
[Tooltip("Below this speed the camera zooms in. Above this speed the camera will start zooming out.")]
public float CamVelocityForZoomIn = 2f;
[Tooltip("Represents how smooth the zoom in of the camera should be. The lower the number the quickest the zoom is.")]
[Range(0f, 3f)]
public float ZoomInSmoothness = 1f;
[Tooltip("Represents how smooth the zoom out of the camera should be. The lower the number the quickest the zoom is.")]
[Range(0f, 3f)]
public float ZoomOutSmoothness = 1f;
[Tooltip("Represents the maximum amount the camera should zoom in when the camera speed is below SpeedForZoomIn")]
public float MaxZoomInAmount = 2f;
[Tooltip("Represents the maximum amount the camera should zoom out when the camera speed is equal to SpeedForZoomOut")]
public float MaxZoomOutAmount = 2f;
float _zoomVelocity;
float _initialCamSize;
float _previousCamSize;
Vector3 _previousCameraPosition;
[HideInInspector]
public float CurrentVelocity;
override protected void Awake()
{
base.Awake();
if (ProCamera2D == null)
return;
_initialCamSize = ProCamera2D.ScreenSizeInWorldCoordinates.y * .5f;
_previousCamSize = _initialCamSize;
_previousCameraPosition = VectorHV(Vector3H(ProCamera2D.LocalPosition), Vector3V(ProCamera2D.LocalPosition));
ProCamera2D.AddSizeDeltaChanger(this);
}
protected override void OnDestroy()
{
base.OnDestroy();
if(ProCamera2D)
ProCamera2D.RemoveSizeDeltaChanger(this);
}
#region ISizeDeltaChanger implementation
public float AdjustSize(float deltaTime, float originalDelta)
{
if (!enabled)
return originalDelta;
// If the camera is bounded, reset the easing
if (_previousCamSize == ProCamera2D.ScreenSizeInWorldCoordinates.y)
{
_zoomVelocity = 0f;
}
// Get camera velocity
CurrentVelocity = (_previousCameraPosition - VectorHV(Vector3H(ProCamera2D.LocalPosition), Vector3V(ProCamera2D.LocalPosition))).magnitude / deltaTime;
_previousCameraPosition = VectorHV(Vector3H(ProCamera2D.LocalPosition), Vector3V(ProCamera2D.LocalPosition));
var currentSize = ProCamera2D.ScreenSizeInWorldCoordinates.y * 0.5f;
var targetSize = currentSize;
// Zoom out
if (CurrentVelocity > CamVelocityForZoomIn)
{
var speedPercentage = (CurrentVelocity - CamVelocityForZoomIn) / (CamVelocityForZoomOut - CamVelocityForZoomIn);
var newSize = _initialCamSize * (1 + MaxZoomOutAmount - 1) * Mathf.Clamp01(speedPercentage);
if (newSize > currentSize)
targetSize = newSize;
}
// Zoom in
else
{
var speedPercentage = (1 - (CurrentVelocity / CamVelocityForZoomIn)).Remap(0.0f, 1.0f, 0.5f, 1.0f);
var newSize = _initialCamSize / (MaxZoomInAmount * speedPercentage);
if (newSize < currentSize)
targetSize = newSize;
}
if (Mathf.Abs(currentSize - targetSize) > .0001f)
{
float smoothness = (targetSize < currentSize) ? ZoomInSmoothness : ZoomOutSmoothness;
targetSize = Mathf.SmoothDamp(currentSize, targetSize, ref _zoomVelocity, smoothness, Mathf.Infinity, deltaTime);
}
var zoomAmount = targetSize - (ProCamera2D.ScreenSizeInWorldCoordinates.y / 2);
// Detect if the camera size is bounded
_previousCamSize = ProCamera2D.ScreenSizeInWorldCoordinates.y;
// Return the zoom delta - delta already factored in by SmoothDamp
return originalDelta + zoomAmount;
}
public int SDCOrder { get { return _sdcOrder; } set { _sdcOrder = value; } }
int _sdcOrder = 1000;
#endregion
override public void OnReset()
{
_previousCamSize = _initialCamSize;
_previousCameraPosition = VectorHV(Vector3H(ProCamera2D.LocalPosition), Vector3V(ProCamera2D.LocalPosition));
_zoomVelocity = 0;
}
}
}