- Home /
My lerp script lerps to a middle point then to the designated point and not just to the designated point
Since I am using kinematic rigid body I can't rely on collisions so I decided to make a custom collision like script that detects how close my player is to the wall. What I want is for my cube to slide against the wall by having lerping to the x y z position disabled depending on the wall's position but now I have a glitchy lerp script that works, but lerps to the target position in a triangle fashion rather then a straight line
what I want:
what I have:
using UnityEngine;
using System.Collections;
//Make the handles more thick
public class Dash : MonoBehaviour
{
private Vector3 RayCastSpawnPositionOffset;
public GameObject Previouscollided;
private GameObject collided;
public LayerMask Wall;
Vector3 newPosition;
public GameObject Wall1;
public GameObject Wall2;
public GameObject Wall3;
public GameObject Wall4;
public GameObject Floor;
public GameObject Ceiling;
public GameObject RecentWall;
public float speed;
[SerializeField]
private int DistanceOfRayCast;
[SerializeField]
private int CornerDistanceOfRayCast;
public bool UpperCornerView = false;
public bool LowerCornerView = false;
public int CurrentCorner;
private Vector3 WallThicknessOffset;
public int CurrentWall;
private bool LerpToPosition;
Rigidbody rb;
private bool LerpToX = true;[SerializeField]
private bool LerpToY = true;[SerializeField]
private bool LerpToZ = true;[SerializeField]
private Vector3 NewPositionX;
private Vector3 NewPositionZ;
private Vector3 NewPositionY;
void Start()
{
newPosition = transform.position;
CurrentWall = 3;
Rigidbody rb = GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
// Debug.Log("CurrentCorner = " + CurrentCorner);
Debug.Log(collided);
if (Input.GetKeyDown("w"))
{
transform.Rotate(1, 0, 0);
}
if (Input.GetKeyDown("s"))
{
transform.Rotate(-1, 0, 0);
}
//This part of the Script handles how the camera handles interactions with corners
RaycastHit HitUp;
Ray UpRay = new Ray(transform.position, Vector3.up * CornerDistanceOfRayCast);
Debug.DrawRay(transform.position, Vector3.up * DistanceOfRayCast, Color.red, 5);
RaycastHit HitDown;
Ray DownRay = new Ray(transform.position, Vector3.down * CornerDistanceOfRayCast);
Debug.DrawRay(transform.position, Vector3.down * DistanceOfRayCast, Color.red, 5);
RaycastHit HitLeft;
Ray LeftRay = new Ray(transform.position, Vector3.left * CornerDistanceOfRayCast);
Debug.DrawRay(transform.position, Vector3.left * CornerDistanceOfRayCast, Color.grey, 5);
RaycastHit HitRight;
Ray RightRay = new Ray(transform.position, Vector3.right * CornerDistanceOfRayCast);
Debug.DrawRay(transform.position, Vector3.right * CornerDistanceOfRayCast, Color.cyan, 5);
RaycastHit HitForward;
Ray ForwardRay = new Ray(transform.position, Vector3.forward * CornerDistanceOfRayCast);
Debug.DrawRay(transform.position, Vector3.forward * CornerDistanceOfRayCast, Color.green, 999);
RaycastHit HitBackward;
Ray BackwardRay = new Ray(transform.position/*newPosition + RayCastSpawnPositionOffset*/, Vector3.back * CornerDistanceOfRayCast);
Debug.DrawRay(transform.position/*newPosition + RayCastSpawnPositionOffset*/, Vector3.back * CornerDistanceOfRayCast, Color.yellow, 999);
if (Physics.Raycast(UpRay, out HitUp, DistanceOfRayCast))
{
UpperCornerView = true;
}
if (Physics.Raycast(DownRay, out HitDown, DistanceOfRayCast))
{
LowerCornerView = true;
}
/*if (Physics.Raycast(ForwardRay, out HitForward, DistanceOfRayCast))
{
if (Vector3.Distance(HitForward.point, transform.position) <= 2)
{
LerpToZ = false;
}
}
if (Physics.Raycast(BackwardRay, out HitBackward, DistanceOfRayCast))
{
if (Vector3.Distance(HitBackward.point, transform.position) <= 2)
{
LerpToZ = false;
}
}
if (Physics.Raycast(RightRay, out HitRight, DistanceOfRayCast))
{
if (Vector3.Distance(HitRight.point, transform.position) <= 2)
{
LerpToX = false;
}
}
if (Physics.Raycast(LeftRay, out HitLeft, DistanceOfRayCast))
{
if (Vector3.Distance(HitLeft.point, transform.position) <= 2)
{
LerpToZ = false;
}
}*/
//Raycast Colors that correspond to their ray
//grey = left
//cyan = right
//green = forward
//yellow = backward
if (Physics.Raycast(LeftRay, out HitLeft, CornerDistanceOfRayCast) && Physics.Raycast(ForwardRay, out HitForward, CornerDistanceOfRayCast))
{
CurrentCorner = 1;
}
if (Physics.Raycast(RightRay, out HitRight, CornerDistanceOfRayCast) && Physics.Raycast(ForwardRay, out HitForward, CornerDistanceOfRayCast))
{
CurrentCorner = 2;
}
if (Physics.Raycast(RightRay, out HitRight, CornerDistanceOfRayCast) && Physics.Raycast(BackwardRay, out HitBackward, CornerDistanceOfRayCast))
{
CurrentCorner = 3;
}
if (Physics.Raycast(LeftRay, out HitLeft, CornerDistanceOfRayCast) && Physics.Raycast(BackwardRay, out HitBackward, CornerDistanceOfRayCast))
{
CurrentCorner = 4;
}
if (Input.GetMouseButtonDown(0))
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit, Wall.value))
{
LerpToX = true;
LerpToZ = true;
LerpToY = true;
CurrentCorner = 0;
UpperCornerView = false;
LowerCornerView = false;
collided = hit.collider.gameObject;
LerpToPosition = true;
RecentWall = collided;
//Debug.Log(collided);
//Cameraposition();
// collided.layer = LayerMask.NameToLayer("Ignore Raycast");
//( ͡° ͜ʖ ͡°)
newPosition = hit.point;
//Debug.Log("test")
Previouscollided.layer = LayerMask.NameToLayer("Wall");
Previouscollided = hit.collider.gameObject;
//Debug.Log(Previousco0llided);
CollidedCheck();
}
}
}
private void CollidedCheck()
{
if (collided == Wall1)
{
//rb.constraints = RigidbodyConstraints.None;
//RayCastSpawnPositionOffset = new Vector3(0, 0, -3);
CurrentWall = 1;
//rb.constraints = RigidbodyConstraints.FreezePositionZ;
//float dist = Vector3.Distance(newPosition, transform.position);
//if(dist <= 2)
//{
//}
StartCoroutine("LerpPos");
// WallThicknessOffset = new Vector3(0, 0, -2);
//transform.position = Vector3.Lerp(transform.position, newPosition + WallThicknessOffset, speed * Time.deltaTime);
}
if (collided == Wall2)
{
//rb.constraints = RigidbodyConstraints.None;
//RayCastSpawnPositionOffset = new Vector3(-3, 0, 0);
CurrentWall = 2;
//rb.constraints = RigidbodyConstraints.FreezePositionX;
StartCoroutine("LerpPos");
}
if (collided == Wall3)
{
//rb.constraints = RigidbodyConstraints.None;
//RayCastSpawnPositionOffset = new Vector3(0, 0, 3);
CurrentWall = 3;
//rb.constraints = RigidbodyConstraints.FreezePositionZ;
StartCoroutine("LerpPos");
}
if (collided == Wall4)
{
//rb.constraints = RigidbodyConstraints.None;
// RayCastSpawnPositionOffset = new Vector3(3, 0, 0);
CurrentWall = 4;
//rb.constraints = RigidbodyConstraints.FreezePositionX;
StartCoroutine("LerpPos");
}
}
private IEnumerator LerpPos()
{
NewPositionX = newPosition;
NewPositionY = newPosition;
NewPositionZ = newPosition;
while (LerpToX == true || LerpToZ == true || LerpToY == true)
{
while (LerpToX == true)
{
NewPositionX.y = 0;
NewPositionX.z = 0;
if (Vector3.Distance(transform.position, NewPositionX) <= 5)
{
LerpToX = false;
yield return null;
}
NewPositionX.y = 0;
NewPositionX.z = 0;
transform.position = Vector3.Lerp(transform.position, NewPositionX, speed);
}
while (LerpToY == true)
{
NewPositionY.x = 0;
NewPositionY.z = 0;
if (Vector3.Distance(transform.position, NewPositionY) <= 5)
{
LerpToY = false;
yield return null;
}
transform.position = Vector3.Lerp(transform.position, NewPositionY, speed);
}
while (LerpToZ == true)
{
NewPositionY.x = 0;
NewPositionY.y = 0;
if (Vector3.Distance(transform.position, NewPositionZ) <= 5)
{
LerpToZ = false;
yield return null;
}
transform.position = Vector3.Lerp(transform.position, NewPositionZ, speed);
}
yield return null;
}
}
}
Answer by RibsNGibs · Apr 12, 2017 at 05:40 PM
You have two problems here.
1) You are not using lerp correctly: it takes two vectors and then a value T, which is the interpolant not a speed - the function returns the first vector if T is 0, the second vector if T is 1, and returns positions smoothly interpolating between the two vectors for values between 0 and 1. You are passing it a speed instead. Since speed*Time.deltaTime is (I assume) always less than 1 and never changes, your while loop never exits, so you are indeed in an infinite loop. You really should be keeping track of your own interpolant T, and then adding some small amount to it every pass through the while loop.
2) You never yield out of the coroutine during your while loop, so even if you were using Lerp correctly, it still wouldn't work right - you need to yield out every step of the interpolation (so move the player, yield, move the player, yield, etc.) See https://docs.unity3d.com/Manual/Coroutines.html for more info on how to use them.
How exactly do I make the coroutine wait for each iteration of the interlope?
See https://docs.unity3d.com/$$anonymous$$anual/Coroutines.html for an intro on coroutines. You need to have a yield every time you want to "pause" execution of your code until the next game loop step.
e.g. you would do
while (<ship hasn't reached target yet>) {
<move ship a little closer>
yield return null;
}
Then on frame 1, your ship will move a little closer to its target, then yield out of the coroutine. On frame 2, the ship will move a little closer again, then yield out again. Until the ship has reached the target, at which point the while loop would end and the coroutine would exit. If you don't yield inside your interpolation loop, then the ship will simply move all the way from the start to the end point in a single frame.
Yea I see the problem now. I'm not having my loop check if the LerpZ Y and Z are true or false so the loop crashes. Fixed it but my cube becomes stuck after moving to my first clicked position. I will update the script and update you on any further details while I am coding. Send me an answer if you know what I'm doing wrong
Answer by Rhyusaky · Apr 13, 2017 at 03:06 PM
You can make a lerp like this:
IEnumerator lerp(Vector3 start,Vector3 end,float speed)
{
float t = 0;
while(t <= 1f)
{
Vector3 pos = Vector3.Lerp(start,end,t);
transform.position = pos;
t = Time.deltaTime*speed;
yield return null;
}
}
This is basically removing all the extra features I needed. NewPositionX Y and Z were needed because non-kinematic bodies don't have collisions and I need something to keep my player/camera from clipping through my walls. Could you tell me what seems to be wrong with my loop ins$$anonymous$$d...