SmoothCameraCrouch
Want to smoothly move the camera down while holding a button, and smoothly move it back up when releasing it.
Got this for as of now but it's an almost instantaneous movement:
if (Input.GetKeyDown(KeyCode.LeftControl))
{
transform.localPosition = new Vector3(0, -1, 0);
}
if (Input.GetKeyUp(KeyCode.LeftControl))
{
transform.localPosition = new Vector3(0, 0, 0);
}
Any help appreciated, all the answers I found are either obsolete or FPS character crouch and I specifically just want to move the camera.
Answer by Hellium · May 02, 2020 at 10:01 PM
For a simpler, and more efficient solution:
[SerializeField] private float crouchSpeed = 1f;
[SerializeField] private Vector3 crouchDeltaPosition = -Vector3.up;
[SerializeField] private KeyCode crouchKey = KeyCode.S;
private Vector3 targetPosition;
private Vector3 initialPosition;
private void Start()
{
initialPosition = transform.localPosition;
}
void Update()
{
if( Input.GetKeyDown( crouchKey ) ) targetPosition = initialPosition + crouchDeltaPosition;
if( Input.GetKeyUp( crouchKey ) ) targetPosition = initialPosition;
// The check isn't really necessary in this situation, it depends on your other code
if(!Mathf.Approximately(0,(transform.localPosition - targetPosition).sqrMagnitude))
transform.localPosition = Vector3.MoveTowards(transform.localPosition, targetPosition, crouchSpeed * Time.deltaTime);
}
Answer by streeetwalker · May 02, 2020 at 09:31 PM
Hi @AlbinoRacoon, well, I took your question as a challenge to create a very generalized way of solving the problem. This is a little overkill for your problem, but not really - the problem is you can let go of the key at any time, so you don't want it to snap back. Either way it should give you the idea even if don't use the complete code:
One easy and very common way to get smooth animation is to employ a LERP - a "Linear Interpolation."
There are several LERPs in unity, and they are are a handy way of finding values between a "from" value and a "to" value based on a fraction that represents the point in between the two.
The general form is LERP( from, to, fraction) .
Some examples:
LERP( 1, 2, 0.0 ) = 0
LERP( 1, 2, 0.5 ) = 1
LERP( 1, 2, 0.75 ) = 1.5
LERP( 1, 2, 0.9 ) = 1.8
and LERP( 1, 2, 1.0 ) = 2
You get the idea?
As long as the fraction is between 0 and 1 inclusive, LERP will return the correct value from the "from" value to the "to" value.
It is common to calculate the fraction based on the the current time of the animation divided by total amount of time that you want the animation to take.
So you have to decide how much time you want the crouch to take.
The code here uses 'speed' as the total time, and you need to enter into the inspector as well as the endPos - end Position. The startPos will use your camera's current position as the start
Note this code will correctly animate even if you let go of the "S" key half way through the animation. To that end, we are employing Vecto3.Lerp instead of Mathf.Lerp which in your situation would might be faster but more difficult because, on the other hand, it does not LERP in negative directions - so we'd have to add more code for moving in the opposite direction.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Crouch : MonoBehaviour {
public float speed = 1f; // speed is the total time to crouch
public Vector3 endPos; // set the low position of the crouch
private Vector3 currentPos;
private Vector3 toPos;
private Vector3 fromPos;
private float currentTime;
private float currentTotalTime;
private float totalDistance;
private Vector3 startPos;
private void Start() {
currentTime = speed + 1; // make sure no LERP at start
currentTotalTime = speed;
startPos = transform.position;
currentPos = transform.position;
totalDistance = Vector3.Distance( endPos, startPos );
}
void Update() {
if( Input.GetKeyDown( KeyCode.S ) ) { // change to your keycode
toPos = endPos;
// this line of code ensures the correct LERP if you let go part way
// through a crouch, so calculate how far we are and convert to remaining time
currentTotalTime = Vector3.Distance( endPos, currentPos ) / totalDistance * speed;
fromPos = currentPos;
currentTime = 0;
}
if( Input.GetKeyUp( KeyCode.S ) ) {
toPos = startPos;
currentTotalTime = Vector3.Distance( startPos, currentPos ) / totalDistance * speed;
fromPos = currentPos;
currentTime = 0;
}
// do the LERP only if you press or let go of your key
if( currentTime <= currentTotalTime ) {
float timeRatio = currentTime / currentTotalTime;
currentPos = Vector3.Lerp( fromPos, toPos, timeRatio );
currentTime += Time.deltaTime;
transform.position = currentPos;
}
}
}
LERP on Dude (or Dudette, what ever your preference)!
Thx a lot man, really helped me understand lerping, marked the other comment "best" tho just cause I feel it's simpler for anyone wanting to just copy paste the code and get the camera moving, but really appreciate the time you took with this!