- Home /
Move object to several locations
Hi! Trying to learn JS here.
What I want is to be able to (press left/right) and move my object to another object (or Vector3 position).
With the code
var target:Transform; var smooth = 0.8; function Update () { transform.position = Vector3.Lerp (transform.position, target.position, Time.deltaTime * smooth); }
I can move the object towards one target, and ease out the speed (fine so far), but if I want to move further to another and third object, if I press the left/right keys.
Example: targets 1 2 3 4 5
So if I start at 1, pressing right brings me to target 2, pressing right again to target 3 and if pressing left, then back to 2...
Answer by save · Jan 11, 2012 at 11:50 AM
You need some sort of array to iterate through, I made a simple script doing this:
#pragma strict
enum REPEAT {
Yes,
No
}
var repeat : REPEAT = REPEAT.Yes; //Set the default enum value
var waitForFinish : boolean = true; //Wait for acceptable range to continue
var finishArea : float = 0.5; //The range for testing if object is close
var locations : Vector3[]; //An array with Vector3 locations in world space
var currentLocation : int = 0; //The current location in the array
var speed : int = 2; //The speed of the moving object
private var myTransform : Transform; //Cache the transform as an optimization
function Start () {
myTransform = transform; //Set myTransform to object's transform component
}
function Update () {
if (Input.GetKeyDown(KeyCode.LeftArrow) || Input.GetKeyDown(KeyCode.RightArrow)) CheckInput(); //Check if the user has given input
myTransform.position = Vector3.Lerp(myTransform.position, locations[currentLocation], speed*Time.deltaTime); //Lerp to new locations in the array
}
function CheckInput () {
if (waitForFinish) {
var sqrLen = (myTransform.position - locations[currentLocation]).sqrMagnitude; //Using sqrMagnitude to check if the object is in close range
if (sqrLen > finishArea) return; //If it isn't then exit the function
}
if (Input.GetKeyDown(KeyCode.LeftArrow)) currentLocation--;
if (Input.GetKeyDown(KeyCode.RightArrow)) currentLocation++;
switch (repeat) {
case REPEAT.Yes:
if (currentLocation<0) currentLocation=locations.Length-1; //Set the location in the array to the number of objects in the array
currentLocation = currentLocation%locations.Length; //Repeat when exhaust all objects
break;
case REPEAT.No:
currentLocation = Mathf.Clamp(currentLocation, 0, locations.Length-1); //Clamp the value if we don't want the position to loop through the array
break;
}
}
}
Also added an enum for repeating or clamping (this could be a boolean, but if you want some other sort of logic to the iteration through the array this is a good start). The waitForFinish is a boolean for testing the acceptable close range to continue to the next Vector3 in the array and the finishArea is the range for that.
If you want to target existing positions of GameObjects then change the Vector3's:
var locations : Vector3[]; to var locations : Transform[];
Then the Lerp and the sqrMagnitude-test:
myTransform.position = Vector3.Lerp(myTransform.position, locations[currentLocation].position, speed*Time.deltaTime);
var sqrLen = (myTransform.position - locations[currentLocation].position).sqrMagnitude;
Have fun!
Added waitForFinish which checks if the object is in close range to be able to continue to the next item in the array. Would come in handy if you don't want the player to just press quickly and move directly to new positions.
As you said you're trying to learn js I also added some comments for what happens in the script.
You could also, ins$$anonymous$$d of using sqr$$anonymous$$agnitude to hold between movements, do this:
yield WaitForSeconds(1);
If the time lapse always is the same (using lerp usually is). Read up on coroutines & yields here.
SmoothDamp might be nicer than Lerp here, except if you want precision, then you would need a snap I suppose.
The Lerp movement is nicer for, let's say jumping through selections of something in world space, but costs quite much in terms of performance. Personally I like SmoothStep better, I'll post another script where you can try out the difference between them using the same logic as above.
Answer by save · Jan 12, 2012 at 12:38 PM
So here's another version of the earlier posted script. Here you can choose between Unity's moving algorithms at runtime to see which one you think fits the best to your implementation.
Keep in mind that the speed variable differs between them.
#pragma strict
enum REPEAT {
Yes,
No
}
enum MOVEMENTTYPE {
Lerp,
SmoothDamp,
SmoothStep,
MoveTowards
}
var repeat : REPEAT = REPEAT.Yes;
var movementType : MOVEMENTTYPE = MOVEMENTTYPE.Lerp;
var waitForFinish : boolean = true;
var finishArea : float = 0.5;
var locations : Vector3[];
var currentLocation : int = 0;
var speed : int = 2; //Keep in mind speed differs depending on selected MOVEMENTTYPE
private var currentVelocity : Vector3 = Vector3.zero;
private var myTransform : Transform;
function Start () {
myTransform = transform;
myTransform.position = locations[currentLocation];
}
function Update () {
if (Input.GetKeyDown(KeyCode.LeftArrow) || Input.GetKeyDown(KeyCode.RightArrow)) CheckInput();
myTransform.position = MoveMe(myTransform.position);
}
function CheckInput () {
if (waitForFinish) {
var sqrLen = (myTransform.position - locations[currentLocation]).sqrMagnitude;
if (sqrLen > finishArea) return;
}
if (Input.GetKeyDown(KeyCode.LeftArrow)) currentLocation--;
if (Input.GetKeyDown(KeyCode.RightArrow)) currentLocation++;
switch (repeat) {
case REPEAT.Yes:
if (currentLocation<0) currentLocation=locations.Length-1;
currentLocation = currentLocation%locations.Length;
break;
case REPEAT.No:
currentLocation = Mathf.Clamp(currentLocation, 0, locations.Length-1);
break;
}
}
function MoveMe (newCoord : Vector3) {
switch (movementType) {
case MOVEMENTTYPE.Lerp:
newCoord = Vector3.Lerp(newCoord, locations[currentLocation], speed*Time.deltaTime);
break;
case MOVEMENTTYPE.SmoothDamp:
var smoothTime : float = 0.1;
newCoord = Vector3.SmoothDamp(newCoord, locations[currentLocation], currentVelocity, smoothTime, speed, Time.deltaTime);
break;
case MOVEMENTTYPE.SmoothStep:
newCoord.x = Mathf.SmoothStep(newCoord.x, locations[currentLocation].x, speed*Time.deltaTime);
newCoord.y = Mathf.SmoothStep(newCoord.y, locations[currentLocation].y, speed*Time.deltaTime);
newCoord.z = Mathf.SmoothStep(newCoord.z, locations[currentLocation].z, speed*Time.deltaTime);
break;
case MOVEMENTTYPE.MoveTowards:
newCoord = Vector3.MoveTowards(newCoord, locations[currentLocation], speed*Time.deltaTime);
break;
}
return newCoord;
}
function OnDrawGizmos () {
if (locations.Length>0) {
for (var i = 0; i < locations.Length; i++) {
Gizmos.color = Color.yellow;
Gizmos.DrawWireCube (locations[i], Vector3(.5,.5,.5));
}
}
}
Updated this with a single Vector3 reference ins$$anonymous$$d of separation of each axis (don't know why I did that) and gizmos so you'll see the points. If you want to know why and how in any bit of the script just ask, good luck!
Your answer
Follow this Question
Related Questions
Move a object and then return , like loop 2 Answers
Implementing Counter-Movement 0 Answers
Move Object A towards Object B at a definite speed 1 Answer
Moving Object by touching it? 1 Answer
PROBLEM need Fix! 0 Answers