- Home /
Lerp Movement Forward Help
I am trying to make a game similar to Escape Velocity, a top down, shooter / rpg. After hours of cruising the internet, I finally got the Rotation to lerp exactly the way I want... I am looking for my controls to be as follows: Up = accelerate from current speed to max speed gradually and move in the direction the object is facing Down = decelerate from my current speed gradually, if current speed is 0, then this is reverse Left / Right = Rotate the ship left or right.
(example for clarity: when Up is pressed and held, it would increment from 0 to 100(maxspeed), press Up 3 times would set your forward velocity to 30, press down twice, your velocity would then be 10, press down twice more, you are now moving backwards slowly)
Please forgive this code... I dont really get javascript (and thats what the FPSInputController is written in)
function Update () {
if(Input.GetKeyUp(KeyCode.UpArrow)){
destSpeed += 10;
}
if (Input.GetKey(KeyCode.UpArrow)&&(curSpeed < maxSpeed))
{
destSpeed += 10;
rigidbody.velocity = transform.forward * destSpeed;
}
if(Input.GetKey(KeyCode.RightArrow))
{
destAngle += 1;
}
if(Input.GetKey(KeyCode.DownArrow))
{
destSpeed -= 10;
}
if(Input.GetKey(KeyCode.LeftArrow))
{
destAngle -= 1;
}
// choose the shortest distance:
var difAngle = destAngle - curAngle;
if (difAngle > 180) curAngle += 360;
if (difAngle < -180) curAngle -= 360;
// lerp curAngle to the destAngle each Update:
curAngle = Mathf.Lerp(curAngle, destAngle, Time.deltaTime);
// copy curAngle to the object Y angle:
transform.eulerAngles = Vector3(0, curAngle, 0);
// Are you Travelling MaxSpeed? Set this variable to the difference
var difSpeed = destSpeed - curSpeed;
if (difSpeed > curSpeed && curSpeed > maxSpeed) curSpeed +=1;
if (difSpeed < curSpeed ) curSpeed -= 1;
// lerp curSpeed to the destSpeed each Update:
curSpeed = Mathf.Lerp(curSpeed, destSpeed, Acceleration);
// move?
transform.position = Vector3.Lerp(transform.position, end.position, Time.deltaTime * curSpeed);
}
I imagined this to be easy when I started, but after my recent results I am beginning to feel epileptic. I read many Unity Forums posts but the all seem to be seeking something completely different from my desired effect or are too specific an answer to be of help to me. If anyone can point me on the right track id be very grateful.
Answer by robertbu · Jan 31, 2013 at 06:36 AM
I see one issues you might want to look into. Read carefully the reference on Lerp(). It is intended that the start and end values be setup in the beginning and then the t value go from 0 to 1. You are recalculating the start values on each Update(), but your t parameter is fairly constant. That is Time.deltaTime varies a bit, but it doesn't climb from 0 to 1. I don't see the code here, but I'll bet Acceleration is also pretty constant as well.
For the logic you have here, I think you would be much happier with Vector3.MoveTowards();
Acceleration is indeed pretty standard, it only changes for power ups, or when they buy a new ship. as for using Lerp... I had no idea what I was doing, but based on the information I had, I was trying to get the player ship to read what the destination would be if it traveled the theoretical path in a theoretical amount of time. so i was attempting to set the player ships current position, where its trying to go and give a time to travel. I see how I will use Lerp in the future, but you are correct that it is not ideal for what I want right here. Vector3.$$anonymous$$oveTowards(); does look more like what im trying to do, but Im still unsure of how to use it to get the ship to just move in the direction it is facing.
You would use $$anonymous$$oveTowards() pretty much as you tried to use Lerp() here. You give it a start and and end position, but unlike Lerp, you update the start position each frame. The last parameter is the limit to how far you want to move it. You want to scale it by Time.deltaTime. So your call would look something like this:
transform.position = Vector3.$$anonymous$$oveTowards(transform.position, v3Destination, max$$anonymous$$ovementPerSecond * Time.deltaTime);
although it wasnt exactly what I was looking for, your answers lead me to the right path to solving my problem. So I accepted yours as the answer. Thanks for taking the time, its appreciated.
Answer by 3itg · Feb 01, 2013 at 01:21 AM
I pretty much got what I want now. but is "gradually accelerating in the direction the player is facing" really this hard to do??? its beginning to seem insane. Move Towards yielded almost identical results... and I couldnt get it to move without a lerp somewhere...
as I said before... I am HORRIBLE with javascript... So while the code compiles and executes, its probably laden with inefficiencies and lines of code that do nothing... and it just feels like Im doing this the hardest way possible.
So I made an empty game object (as a child of the player) and positioned directly in front of the player. I get its coords, and attempt to move there at whatever speed. and I got it moving, gradually based on a number I increment.
The only thing I am still trying to figure out is how to be able to freely rotate, without affecting the trajectory while not pressing "Up". if there is an easier way... please let me know... the code looks like this now...
private var motor : CharacterMotor;
var playerStats : CharacterMotorMovement;
var curAngle: float;
var destAngle: float = 0;
var curSpeed: float;
var maxSpeed: float = 100;
var destSpeed: float = 0;
var difSpeed = destSpeed - curSpeed;
var difAngle = destAngle - curAngle;
var end : Transform;
var accel : float = 10;
var positionArray ;
// Use this for initialization
function Awake () {
positionArray = GameObject.Find("GoForward");
motor = GetComponent(CharacterMotor);
playerStats = GetComponent(CharacterMotorMovement);
}
function Start ()
{
rigidbody.useGravity = false;
}
function FixedUpdate ()
{
if (Input.GetKey(KeyCode.UpArrow)&&(curSpeed < maxSpeed))
{
destSpeed += 1;
}
if(Input.GetKey(KeyCode.RightArrow))
{
destAngle += 1;
}
if(Input.GetKey(KeyCode.DownArrow))
{
destSpeed -= 1;
}
if(Input.GetKey(KeyCode.LeftArrow))
{
destAngle -= 1;
}
// choose the shortest distance:
if (difAngle > 180) curAngle += 360;
if (difAngle < -180) curAngle -= 360;
// lerp curAngle to the destAngle each Update:
curAngle = Mathf.Lerp(curAngle, destAngle, Time.deltaTime);
// copy curAngle to the object Y angle:
transform.eulerAngles = Vector3(0, curAngle, 0);
if(destSpeed > maxSpeed)
{
destSpeed = maxSpeed;
}
if(destSpeed < 0-maxSpeed)
{
destSpeed = (maxSpeed*0.5) - maxSpeed;
}
if (curSpeed != destSpeed || destSpeed != 0)
{
destPosition = Vector3(end.transform.position.x,end.transform.position.y,end.transform.position.z);
curSpeed = Mathf.Lerp(curSpeed, destSpeed, maxSpeed * Time.deltaTime);
transform.position = Vector3.Lerp(transform.position,destPosition,curSpeed*Time.deltaTime/100);
}
}
// Require a character controller to be attached to the same game object
@script RequireComponent (CharacterMotor)
@script AddComponentMenu ("Character/FPS Input Controller")