Last active
April 14, 2022 16:51
-
-
Save sebtoun/60035fb1c9270a0a362a85f0f5bb6fb5 to your computer and use it in GitHub Desktop.
Stretch With Velocity Animation for Unity
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 UnityEngine; | |
public class StretchWithVelocity : MonoBehaviour | |
{ | |
public float MaxVelocity = 10; | |
public float MaxSpeedStretch = 0.5f; | |
public bool CompensatePosition = true; | |
public float MinVelocity = 0.1f; | |
public float Smoothing = 0.1f; | |
private Vector2 _lastPosition; | |
private Transform _childTransform; | |
private Bounds _childBounds; | |
private float _currentStretchVelocity; | |
private float _targetStretch; | |
private float _currentStretch; | |
private Vector2 _currentDirection; | |
#if UNITY_EDITOR | |
// just for debugging purposes | |
[ SerializeField ] | |
#pragma warning disable 0414 // private field assigned but not used. | |
private Vector2 _percievedVelocity; | |
#endif | |
private void Awake() | |
{ | |
_childTransform = transform.GetChild( 0 ); | |
} | |
private void Start() | |
{ | |
_childBounds = _childTransform.GetComponent<Renderer>().bounds; | |
_currentDirection = Vector2.right; | |
} | |
private void OnEnable() | |
{ | |
_lastPosition = transform.position; | |
_currentStretch = 1; | |
} | |
private void OnDisable() | |
{ | |
ResetStretch(); | |
} | |
private void LateUpdate() | |
{ | |
if ( Time.deltaTime <= 0 ) return; | |
var position = (Vector2) transform.position; | |
var velocity = ( position - _lastPosition ) / Time.deltaTime; | |
if ( velocity.sqrMagnitude >= MinVelocity * MinVelocity ) | |
{ | |
_currentDirection = velocity; | |
} | |
else | |
{ | |
_currentDirection = Vector2.right; | |
} | |
#if UNITY_EDITOR | |
_percievedVelocity = velocity; | |
#endif | |
_lastPosition = position; | |
_targetStretch = 1 + Mathf.Lerp( 0, MaxSpeedStretch, Mathf.Clamp01( velocity.magnitude / MaxVelocity ) ); | |
_currentStretch = Mathf.SmoothDamp( _currentStretch, _targetStretch, ref _currentStretchVelocity, Smoothing ); | |
ApplyStretch( _currentDirection, _currentStretch ); | |
} | |
private void ResetStretch() | |
{ | |
transform.localScale = Vector3.one; | |
transform.localRotation = Quaternion.identity; | |
_childTransform.localRotation = Quaternion.identity; | |
_currentStretch = 1; | |
} | |
private void ApplyStretch( Vector2 direction, float stretch ) | |
{ | |
var parentScaleSign = Signs( transform.parent.lossyScale ); | |
direction.Scale( parentScaleSign ); | |
var angle = Mathf.Atan2( direction.y, direction.x ) * Mathf.Rad2Deg; | |
var scale = new Vector3( stretch, 1 / stretch, 1 ); | |
var rotation = Quaternion.AngleAxis( angle, Vector3.forward ); | |
transform.localScale = scale; | |
transform.localRotation = rotation; | |
_childTransform.localRotation = Quaternion.Inverse( rotation ); | |
if ( CompensatePosition ) | |
{ | |
var offsetX = Mathf.Abs( Mathf.Cos( angle * Mathf.Deg2Rad ) ) * ( 1 - 1 / stretch ) * _childBounds.size.y * | |
0.5f; | |
var offsetY = Mathf.Sin( angle * Mathf.Deg2Rad ) * ( stretch - 1 ) * _childBounds.size.y * 0.5f; | |
var pos = transform.position; | |
pos.y -= offsetX; | |
pos.y -= offsetY; | |
_childTransform.position = pos; | |
} | |
} | |
public static Vector3 Signs( Vector3 v ) | |
{ | |
return new Vector3( Mathf.Sign( v.x ), Mathf.Sign( v.y ), Mathf.Sign( v.z ) ); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
But how would you only stretch on the Y axis?