- Home /
Hi. I'm a new Unity user, and I'm trying to return an object to its initial position after moving it.
After consulting several examples of how to do that, it doesn't seem to work at all. The object just moves towards the indicated axis, but never gets back. Please help me, and suggest to me what I'm doing wrong. Thank you in advance!
Here is the code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class testing : MonoBehaviour
{
public int option;
public float speed;
private Vector3 target;
private Vector3 origin;
void Start(){
speed = 0.5f;
origin = transform.position;
}
void Update(){
if (option == 1)
{
target = new Vector3(1, 0, 0);
transform.position = Vector3.MoveTowards(transform.position, target, speed * Time.deltaTime);
if (transform.position == target)
{
target = origin;
}
Debug.Log("Selected option is " + option + ". Moving on the X axis.");
}
else if (option == 2)
{
target = new Vector3(0, 0, 1);
transform.position = Vector3.MoveTowards(transform.position, target, speed * Time.deltaTime);
if (transform.position == target)
{
target = origin;
}
Debug.Log("Selected option is " + option + ". Moving on the Z axis.");
}
else
{
Debug.Log("Selected option is " + option + ". There is no movement.");
}
}
}
What do you mean by "never gets back"? Like do you mean that the object never goes back to its initial position (when the game started) or something in the code doesn't get called (like the "Debug.Log")
I meant that the object doesn't return to its initial position, although I declared that wrote that the target must equal to the initial position. But I've already learned what was my mistake :)
Answer by Captain_Pineapple · Apr 08 at 02:57 PM
Hey there,
the issue you have with your code is that you always overwrite the target
with the positions that you want to move to. So even if you reach the target position and you set target = origin
on the next Update run you reset target = Vector3(something, 0, someOtherThing)
.
So to solve this you should introduce a new option that you change to when moving back. To make this more readable and easier to understand i suggest you try to look into enumerations
. An enumeration can help you to differentiate different states that otherwise would be plain numbers:
public class testing : MonoBehaviour
{
//here we create an enumeration:
public enum OptionState {
None, // this is equal to "option 0"
MoveOnX, // this is equal to "option 1"
MoveOnZ, // this is equal to "option 2"
MoveToOrigin // and so on...
}
//our "option" is now not an integer but an "OptionState"
//you can always change between OptionState and int by casting from one to the other:
//int integerValueOfOption = (int)option;
//option = (OptionState)2; // <-different way to write "option = OptionState.MoveOnZ;"
public OptionState option;
public float speed;
private Vector3 target;
private Vector3 origin;
void Start()
{
speed = 0.5f;
origin = transform.position;
}
void Update()
{
if (option == OptionState.MoveOnX)
{
target = new Vector3(1, 0, 0);
transform.position = Vector3.MoveTowards(transform.position, target, speed * Time.deltaTime);
if (transform.position == target)
{
//we have reached the target so now we want to move back. For this we change the current state:
option = OptionState.MoveToOrigin;
}
Debug.Log("Selected option is " + option + ". Moving on the X axis.");
}
else if (option == OptionState.MoveTo2)
{
target = new Vector3(0, 0, 1);
transform.position = Vector3.MoveTowards(transform.position, target, speed * Time.deltaTime);
if (transform.position == target)
{
//we have reached the target so now we want to move back. For this we change the current state:
option = OptionState.MoveToOrigin;
}
Debug.Log("Selected option is " + option + ". Moving on the Z axis.");
}
else if (option == OptionState.MoveToOrigin)
{
//if we are in this state we move towards our origin:
transform.position = Vector3.MoveTowards(transform.position, origin, speed * Time.deltaTime);
if (transform.position == origin)
{
//now that we have reached the origin we set the state to "None" so nothing is done until we change the state again:
option = OptionState.None;
}
}
else
{
Debug.Log("Selected option is " + option + ". There is no movement.");
}
}
}
Let me know if something was unclear.
Edit: Same as Hellium answer this is not tested.
Thank you very much, I was a bit confused about how to convert de enum into an int. Instead, I've just assigned a variable and used the || alongside the movement options for every if and it seems to work, I have no idea how good or bad of a practice it is, but it works.
Thank you again, now everything is clear and I'll use this example for my further projects, you are a lifesaver.
Also, I have another question if you can guide me further. I have to do a project where I have a list of options, like an array of numbers, and each time they are randomly rearranged. And in accordance with that list, the object has to do for example actions 1, 4, 2, 3, step by step. It seemed easier to start with something that I know, and then improve it further. What should be my next move in implementing such a project, how do you think, if its okay for you to answer this.
Hey there,
sorry if that was confusing, you can ofc stick to your original integer base solution if you like - my solution is just a suggestion that might be helpful down the road.
Changing the type of a variable into a different type is a so called cast.
Example:
//we have an integer:
int x = 1;
//now convert that to your enum OptionState:
OptionState state = (OptionState)x;
Debug.Log(state); // should now print "MoveOnX"
Other way round:
OptionState state = OptionState.MoveOnX;
//convert to integer:
int x = (int)state;
Debug.Log(x); //should now print "1"
Do i understand your request as follows: you want to have a list of "options" that is randomly mixed and then you want to execute them one after the other from the list. So move your object to one position, then the next and so on? Or should it return to origin between each of the actions?
If you clarify this i can ofc give you some advice on how to start with this.
Yes, after each execution of the movement, the object should return to its initial position.
I was thinking that in order to have a list of random "options", I have to declare an array, then get each position (ex. array[0], array[1], array[2]) and check if they match with any of those numbers (like 1, 2, etc that I really wanted to be printed). That sounds a bit messed up and I'm not sure if that would work. Could you please suggest, if there is any, a more reasonable approach to this problem?
Yes, I've tried to run it and encountered a little typo, but besides that everything worked great. Thank you!
Answer by Hellium · Apr 08 at 03:06 PM
Code not tested
public float speed;
[Min(1)] public int option;
// Edit destinations in inspector
public Vector3[] destinations = new Vector3[]
{
new Vector3(1, 0, 0),
new Vector3(0, 0, 1)
};
private Vector3 target;
private Vector3 origin;
private Vector3 destination;
void Start(){
speed = 0.5f;
origin = transform.position;
if(destinations.Length > 0)
target = destinations[Mathf.Min(option, destinations.Length) - 1)];
else
target = origin;
}
void Update(){
if(destinations.Length > 0)
destination = destinations[Mathf.Min(option, destinations.Length) - 1)];
transform.position = Vector3.MoveTowards(transform.position, target, speed * Time.deltaTime);
if(transform.position == target)
{
if(target == destination)
target = origin;
else
target = destination; // Comment the else and this line if you don't want to loop
// Or more simply
// target = target == origin ? destination : origin;
}
}
I tried to run it, but sadly it doesn't work and I'm not sure where I'm doing it wrong :(, but thank you for your time nonetheless.
Your answer
Follow this Question
Related Questions
Object faces -180 degrees away 1 Answer
Vector3.Lerp doesn't work on build 0 Answers
Whats the best way to get the Distance between two Vector3? 2 Answers
detect if a "Empty" is inside a box or trigger? 1 Answer
Looping through vector3 list slow 1 Answer