Created
July 19, 2021 18:04
-
-
Save daleth90/f6de5e51ff9fa36335129dc38fb2a1f0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using UnityEngine; | |
public class ScrollCamera : MonoBehaviour { | |
public enum MovementType { | |
Unrestricted, | |
Elastic, | |
Clamped | |
} | |
[Serializable] | |
private struct ScrollBound { | |
public Vector2 center; | |
public Vector2 extents; | |
} | |
[SerializeField] | |
private bool horizontal = true; | |
[SerializeField] | |
private bool vertical = true; | |
[SerializeField] | |
private MovementType movementType = MovementType.Elastic; | |
[SerializeField] | |
[Range( 0f, 1f )] | |
private float elasticity = 0.1f; | |
[SerializeField] | |
private bool inertia = true; | |
[SerializeField] | |
[Range( 0f, 1f )] | |
private float decelerationRate = 0.135f; | |
[SerializeField] | |
private ScrollBound scrollBound; | |
private Camera cameraComponent; | |
private bool isDragging; | |
private Vector2 pointerStartPosition; | |
private Vector2 cameraStartPosition; | |
private Vector2 previousPosition; | |
private Vector2 velocity; | |
private void Awake() { | |
cameraComponent = GetComponent<Camera>(); | |
} | |
private void Update() { | |
if ( Input.GetMouseButtonDown( 0 ) ) { | |
OnBeginDrag(); | |
} | |
else if ( Input.GetMouseButton( 0 ) ) { | |
OnDrag(); | |
} | |
else if ( Input.GetMouseButtonUp( 0 ) ) { | |
OnEndDrag(); | |
} | |
} | |
private void OnBeginDrag() { | |
pointerStartPosition = cameraComponent.ScreenToViewportPoint( Input.mousePosition ); | |
cameraStartPosition = transform.position; | |
isDragging = true; | |
} | |
private void OnEndDrag() { | |
isDragging = false; | |
} | |
private void OnDrag() { | |
Vector2 pointerPosition = cameraComponent.ScreenToViewportPoint( Input.mousePosition ); | |
Vector2 pointerDeltaPosition = pointerPosition - pointerStartPosition; | |
Vector2 position = cameraStartPosition - pointerDeltaPosition * 10; | |
Vector2 offset = CalculateOffset( position ); | |
position += offset; | |
if ( movementType == MovementType.Elastic ) { | |
if ( offset.x != 0 ) | |
position.x = position.x - RubberDelta( offset.x, scrollBound.extents.x ); | |
if ( offset.y != 0 ) | |
position.y = position.y - RubberDelta( offset.y, scrollBound.extents.y ); | |
} | |
SetPosition( position ); | |
} | |
private Vector2 CalculateOffset( Vector2 position ) { | |
Vector2 offset = Vector2.zero; | |
if ( movementType == MovementType.Unrestricted ) | |
return offset; | |
if ( horizontal ) { | |
if ( position.x < -scrollBound.extents.x ) | |
offset.x = -scrollBound.extents.x - position.x; | |
else if ( position.x > scrollBound.extents.x ) | |
offset.x = scrollBound.extents.x - position.x; | |
} | |
if ( vertical ) { | |
if ( position.y < -scrollBound.extents.y ) | |
offset.y = -scrollBound.extents.y - position.y; | |
else if ( position.y > scrollBound.extents.y ) | |
offset.y = scrollBound.extents.y - position.y; | |
} | |
return offset; | |
} | |
private void SetPosition( Vector2 position ) { | |
if ( !horizontal ) | |
position.x = transform.position.x; | |
if ( !vertical ) | |
position.y = transform.position.y; | |
if ( position != (Vector2)transform.position ) { | |
transform.position = new Vector3( position.x, position.y, transform.position.z ); | |
} | |
} | |
private static float RubberDelta( float overStretching, float viewSize ) { | |
return ( 1 - ( 1 / ( ( Mathf.Abs( overStretching ) * 0.55f / viewSize ) + 1 ) ) ) * viewSize * Mathf.Sign( overStretching ); | |
} | |
private void LateUpdate() { | |
float deltaTime = Time.unscaledDeltaTime; | |
Vector2 offset = CalculateOffset( transform.position ); | |
if ( !isDragging && ( offset != Vector2.zero || velocity != Vector2.zero ) ) { | |
Vector2 position = transform.position; | |
for ( int axis = 0; axis < 2; ++axis ) { | |
if ( movementType == MovementType.Elastic && offset[ axis ] != 0 ) { | |
float speed = velocity[ axis ]; | |
position[ axis ] = Mathf.SmoothDamp( transform.position[ axis ], transform.position[ axis ] + offset[ axis ], ref speed, elasticity, Mathf.Infinity, deltaTime ); | |
velocity[ axis ] = speed; | |
} | |
else if ( inertia ) { | |
velocity[ axis ] *= Mathf.Pow( decelerationRate, deltaTime ); | |
if ( Mathf.Abs( velocity[ axis ] ) < 1 ) | |
velocity[ axis ] = 0; | |
position[ axis ] += velocity[ axis ] * deltaTime; | |
} | |
else { | |
velocity[ axis ] = 0; | |
} | |
} | |
if ( velocity != Vector2.zero ) { | |
if ( movementType == MovementType.Clamped ) { | |
offset = CalculateOffset( position ); | |
position += offset; | |
} | |
SetPosition( position ); | |
} | |
} | |
if ( isDragging && inertia ) { | |
Vector2 newVelocity = ( (Vector2)transform.position - previousPosition ) / deltaTime; | |
velocity = Vector2.Lerp( velocity, newVelocity, deltaTime * 10 ); | |
} | |
previousPosition = transform.position; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment