- Home /
Vector3.Lerp not working unless interpolant t is 1.
I have started a new FPS project in unity and I have been trying to add recoil to the gun. I am calling the recoil function in the Update method like this:
void Update()
{
if(Input.GetButtonDown("Fire1"))
{
Shoot();
Recoil();
}
}
This is what the recoil function currently looks like:
void Recoil()
{
Vector3 recoilRotation = new Vector3(-recoil, 0, 0);
Vector3 gunRotation = transform.rotation.eulerAngles;
transform.localEulerAngles = Vector3.Lerp(gunRotation, recoilRotation, 1);
}
When I left click while running the game the gun rotates upwards like it should, but when i try to change the interpolant 1 to anything other than 1, or something like recoilSpeed * Time.deltaTime (recoilSpeed is a float i have set as 1), the gun will rotate in random directions at every axis. I try to change the interpolant because I want a smooth recoil and not instant. After I get it working in one direction I will do it in reverse so it goes back to the original position. Please tell me if i missed anything and I would love your advice!
Answer by KevinDover · Jan 06, 2020 at 10:48 AM
In case anyone else had the same problem, this is what I did to fix it.
Here is just the code (related to the recoil):
public class GunScript : MonoBehaviour {
public float recoil = 10f;
public float recoilSpeed = 1f;
private float lerpPct;
private bool checkRecoilLerp;
void Update()
{
if (Input.GetButtonDown("Fire1"))
{
checkRecoilLerp = true;
}
if (checkRecoilLerp)
{
Recoil();
}
}
void Recoil()
{
if (lerpPct < 1)
{
lerpPct += Time.deltaTime * recoilSpeed;
transform.localEulerAngles = new Vector3(lerpPct * -recoil, 0, 0);
}
else
{
checkRecoilLerp = false;
}
}
}
I would explain more but I don't completely understand how it works, I just know it does. Read the other replies for a better explanation.
The percentage parameter to Lerp is clamped at a value between 0 and 1 inclusive. 0 meaning 0% and 1 meaning 100%. The idea behind Lerp is to provide a starting state for an object (this can be a position, a rotation, a size, a color, etc.) as well as provide an ending state for the object.
When calling Lerp, the value between 0 and 1 deter$$anonymous$$es, using a linear equation, what the new value(s) of the object's state should be. So, let's say you have a cube which is 1m x 1m x 1m as its starting state and you want it to be 5m x 5m x 5m (in other words grow) at its ending state.
If you pass 0 as the parameter for Lerp, then the cube will be in its starting state of 1m x 1m x 1m. If you pass in 1 as the parameter, it will be in its ending state of 5m x 5m x 5m. If, however, you pass in a value of 0.5, then it will be half-way through its state change and linearly, the length, width and height will be 1/2 of its final state. So at 0.5, the size of the cube will be 2.5m x 2.5m x 2.5m.
Now, you have a way to calculate the values of the state of the object between the start and the end in order to see a smooth transition. However, that is only part of the problem. The second part is to deter$$anonymous$$e what value of the percentage you should pass to the Lerp function to get the new values for your object. This usually includes adding a factor of time. So, you need to deter$$anonymous$$e how long you want the change from the first state of your object to the final state of your object to take. So, I might want my cube to take 3 seconds to go from its small size to its larger size, or I might want it to grow over the period of a $$anonymous$$ute.
Let's say I want it to go from its starting size to its full size in 3 seconds. I'd set a starting time, then in each update, subtract the starting time from the next time measurement (i.e. Time.deltaTime - startTime), then divide that value by 3. This would give the percentage of seconds that have elapsed within a 3-second window. However, I could use some logic or $$anonymous$$ath.Clamp() on the value to make sure the result of the division is between 0 and 1 inclusive.
Just trying to provide an explanation of how Lerp works --it just gives you the value to assign to your object (as I noted, it doesn't just have to be position), at some percentage between the start and end state.
Answer by Developer061 · Jan 06, 2020 at 06:22 AM
//Call Your Recoil in UPDATE, consider the below snippet, below is for position but you can try your code for rotation too. //Play with the variables P.S: check out the syntax as i am writing it here, so mistakes are inevitable
private Vector3 pos1;
//in start or from where you want to start lerp, initialize pos1
//e.g.
pos1 = this.trasform.position;
//call this from update
if (somebool) {
LerpFunc(Pos2);
}
//the function, your recoil in your case
void LerpFunc(Vector3 pos2)
{
if (lerpPct < 1)
{
lerpPct += Time.deltaTime * lerpMultiplier;
ObjectToMove.position = Vector3.Lerp(pos1, pos2, lerpPct);
}
else
{
somebool = false;
}
}
private bool CheckLerp;
if(Input.GetButtonDown("Fire1"))
{
Shoot();
CheckLerp = true;
}
if(ChecLerp){
Recoil();
}
void Recoil()
{
Vector3 recoilRotation = new Vector3(-recoil, 0, 0);
Vector3 gunRotation = transform.rotation.eulerAngles;
//in here Implement the lerpPct from my code and replace the position lerp with you below line and then set the CheckLerp to false when lerpPct >=1
if (lerpPct < 1)
{
lerpPct += Time.deltaTime * lerp$$anonymous$$ultiplier;
transform.localEulerAngles = Vector3.Lerp(gunRotation, recoilRotation, lerpPct);
}
else
{
CheckLerp = false;
}
}
I tried that but the gun still rotates on multiple axis, but atleast it now smoothly rotates. I tried to send a vid but you can't send videos