Ok, so I have spent hours trying to figure this out on my own with no luck, and as you will soon see, I am very new to JavaScript.
I am trying to move an object up to a specific spot when I push up, and down to a specific spot when i push down.
The problem with my code is that it just jumps to the locations and does not use the Mathf.Lerp to move it over time.
Any help would be super.
var Startspot = 0.0;
var Endspot = 1.0;
function Update(){
if (Input.GetKey("up")){
transform.position.y = Mathf.Lerp(Startspot,Endspot,Time.time);
}
if (Input.GetKey("down")){
transform.position.y = Mathf.Lerp(Endspot,Startspot,Time.time);
}
}
As the docs say, the third parameter in Lerp is a float clamped between 0 and 1. So using Time.time won’t work at all, since it will always evaluate as 1 (once past the first second anyway). Basically, don’t use Update…that runs every frame regardless, you just want to have a routine that runs only while moving from point A to point B. So use a coroutine with a loop that goes from 0 to 1, so Lerp will work. If you do some searching you will find many code examples in the forums of coroutines doing things similar to this.
I went through this recently with another forum user here. I’d recommend reading through his final code to get a good idea of how to use Lerp for moving your object.
On a side note, he took the exact same approach as you, placing Time.time as the t value. Can I ask why you put that there? The reason I ask is that more than one person trying that generally means they have got the same wrong information, and would it would be worth fixing that information if possible so future users don’t fall into this same trap.
Honestly, I think that is what you get when animators decide to become coders. As I go through the script references I get a definition that includes terms that I need definitions for, that lead to more unknown terms…
Anyway, I did manage to get things working! If you have any recommendations on how to optimize my code I would appreciate it. Also, how would I go about disabling the input commands while the transition is in progress?
var startspot : Transform;
var endspot : Transform;
function Update () {
if(Input.GetKey("down")){
Select();
}
if(Input.GetKey("up")){
DeSelect();
}
}
function Select () {
var t = 0.0;
while (t <= 1.0) {
t += Time.deltaTime/1;
transform.rotation = Quaternion.Lerp(startspot.rotation, endspot.rotation, Mathf.SmoothStep(0.0, 1.0, t));
transform.position = Vector3.Lerp(startspot.position, endspot.position, Mathf.SmoothStep(0.0, 1.0, t));
yield;
}
}
function DeSelect () {
var t = 0.0;
while (t <= 1.0) {
t += Time.deltaTime/1;
transform.rotation = Quaternion.Lerp(endspot.rotation, startspot.rotation, Mathf.SmoothStep(0.0, 1.0, t));
transform.position = Vector3.Lerp(endspot.position, startspot.position, Mathf.SmoothStep(0.0, 1.0, t));
yield;
}
}
var startspot : Transform;
var endspot : Transform;
var isMoving : boolean;
function Awake() {
isMoving = false;
}
function Update () {
// Just test to see if it's already moving
if(!isMoving){
if(Input.GetKey("down")){
isMoving = true;
Select();
}
if(Input.GetKey("up")){
isMoving = true;
DeSelect();
}
}
}
function Select () {
var t = 0.0;
while (t <= 1.0) {
t += Time.deltaTime/1;
transform.rotation = Quaternion.Lerp(startspot.rotation, endspot.rotation, Mathf.SmoothStep(0.0, 1.0, t));
transform.position = Vector3.Lerp(startspot.position, endspot.position, Mathf.SmoothStep(0.0, 1.0, t));
yield;
}
// Set isMoving back to false so we can start moving again
isMoving = false;
}
function DeSelect () {
var t = 0.0;
while (t <= 1.0) {
t += Time.deltaTime/1;
transform.rotation = Quaternion.Lerp(endspot.rotation, startspot.rotation, Mathf.SmoothStep(0.0, 1.0, t));
transform.position = Vector3.Lerp(endspot.position, startspot.position, Mathf.SmoothStep(0.0, 1.0, t));
yield;
}
// Set isMoving back to false so we can start moving again
isMoving = false;
}
In the interests of teaching, I took your code and made some changes. It should work a bit better now, and there’s less duplication. I’ve commented all my changes, but I can further explain anything that isn’t clear.
var startspot : Transform;
var endspot : Transform;
//"private" stops the variable from being shown in the Inspector
// booleans start as false, but it's best to be explicit
private var isMoving : boolean = false;
// records whether we are at the start or end
private var atStart : boolean = true;
//put us at the start spot to begin
function Start() {
transform.position = startspot.position;
transform.rotation = startspot.rotation;
}
function Update() {
if (!isMoving) {
if (atStart Input.GetKey("down")) {
Move(true); //move forwards
atStart = false;
} else if (!atStart Input.GetKey("up")) {
Move(false); //move backwards
atStart = true;
}
}
}
// Just one function with the option to move backwards instead
function Move(forward : boolean) {
// All handling of isMoving in this function, so it's safe and self-contained.
if (isMoving) {
return; //just abort if we're already moving
}
isMoving = true;
//Get start and end points (basically just swapped if necessary)
//I'm using the ternary operator here, which is an inline if/then/else:
// (if this is true) ? (then use this) : (else use this)
var currentStart = forward ? startspot : endspot;
var currentEnd = forward ? endspot : startspot;
//for loops are clearer than while loops if you are keeping a loop variable
for (var t = 0.0; t < 1.0; t += Time.deltaTime) {
//s is a smoothed t
var s = Mathf.SmoothStep(0.0, 1.0, t);
//Spherical linear interpolation (Slerp) will give us a better rotation
//if the rotations are far apart
transform.rotation = Quaternion.Slerp(currentStart.rotation, currentEnd.rotation, s);
transform.position = Vector3.Lerp(currentStart.position, currentEnd.position, s);
yield;
}
// Put us at the end in case we overshot, which could happen at low frame rates
transform.rotation = currentEnd.rotation;
transform.position = currentEnd.position;
// Set isMoving back to false so we can start moving again
isMoving = false;
}
The function Mathf.SmoothStep talked about on this thread helped me figure out the issue of “Lerp will only ever work once in the very first second of the game” that was talked about here