I have a squash and stretch effect on my player, it works well but when you hit something (for example the floor) it just returns to the default size, which slightly ruins the dynamic. I want it so that when you hit something it stretches (or sort of absorbs/bounces the impact). I found a really cool video for a game that has the sort of effect i want. See 0:00 to around 0:10. Ive tried multiple different methods most that have failed, here is my current script:
public class PlayerFX : MonoBehaviour
{
[Header("Squash and Stretch Settings")]
[Range(0, 1)] public float stretchEffectAmount = 0.1f;
[Range(0, 15)] public float rotationEffectAmount = 1f;
public float rotationStiffness = 8f;
public Transform sprite;
public Vector3 originalScale { get; private set; }
public Vector2 originalScaleAnchor { get; private set; }
public Transform anchor;
public bool jumpCoiling;
public float jumpCoilingTime = 0.05f;
[Range(0, 5)] public float jumpCoilingEffectAmount = 1f;
// internals
private bool coiling = false;
PlayerController pc;
private Rigidbody2D rb;
void Start() {
rb = GetComponent<Rigidbody2D>();
if (sprite != null) {
originalScale = sprite.transform.localScale;
originalScaleAnchor = anchor.transform.localScale;
}
pc = GetComponent<PlayerController>();
}
void Update() {
if (pc.jumpCoilTimer >= pc.jumpCoilDelay) coiling = false;
SquishAndStretchUpdate();
if (pc != null && jumpCoiling) {
pc.jumpCoilEnabled = true;
pc.jumpCoilDelay = jumpCoilingTime;
}
}
/// <summary>
/// Function for updating the squish and stretch effect.
/// </summary>
private void SquishAndStretchUpdate() {
if (sprite != null) {
if (!coiling) {
// scaling
Vector2 velo = pc.rb.velocity;
float newX = originalScaleAnchor.x - (velo.y * stretchEffectAmount);
float newY = (velo.y * stretchEffectAmount) + originalScaleAnchor.y;
anchor.localScale = new Vector2(newX, newY);
// rotation
float rotZ = velo.y;
rotZ *= pc.xInput;
rotZ *= rotationEffectAmount;
if (!pc.grounded)
anchor.localRotation = Quaternion.Lerp(Quaternion.identity, Quaternion.Euler(0, 0, rotZ), rotationStiffness * Time.deltaTime);
else
anchor.localRotation = Quaternion.identity;
}
}
}
public void Coil(float time) {
coiling = true;
time *= 0.5f;
float x = time * jumpCoilingEffectAmount * 1.1f;
float y = time * jumpCoilingEffectAmount;
float newX = x + originalScaleAnchor.x;
float newY = originalScaleAnchor.y - y;
anchor.localScale = new Vector2(newX, newY);
}
}
So I tried detecting when i was grounded and then decreasing the scale for an amount of time, but how can i make it return to the original shape after?
just save the dimensions of the original shape on startup in a variable and have it scale back to that when needed?