- Home /
How do I move an object to the position of another object when a key is pressed?
Hi all,
I'm extremely new to Unity and have tried a lot of different things to do this, but most tutorials for beginners provide instructions on how to create things like rolling balls or moving characters that respond directly to character input (e.g. holding left makes the object move left for the amount of time you hold left for), and the documentation does not provide much help because I can't find specific solutions or answers to problems. I do have a comprehensive understanding of C# and completed and understood tutorials on C# before heading over to Unity, but then I was unable to find Unity tutorials relevant or useful to me, because no tutorials I have found explicitly explain basic functions which can be used in Unity.
For the project that I'm making, I want the arrow keys to make objects move a predetermined amount. For example, pressing the left key once makes an object move left this many spaces. For my specific project, which is in a 3D environment, I have 6 objects, located above each other. These objects are 2D images in a canvas which overlays the game camera as a UI. Imagine that object 1 is at the top, and object 6 is at the bottom. When the user presses the down key, I want object 1 to move to object 2, object 2 to move to object 3, and so on, to create a cycle through the objects. Object 6 would move out of the screen and reappear at the top.
I already understand how to get user inputs through using
if (Input.GetKeyDown(KeyCode.DownArrow)) However, if someone could please explain how to use Vector3 and transform.position, since I have searched forever but no place explains what they mean or how to use them, I would be extremely grateful. Also, I have not searched this, but as a side note, do things like transform.scale or transform.rotation also exist?
Sorry if this question is too long, or if I have used incorrect terminology, but here's a summary of my questions. I'm finding it really difficult to get instructions for things I want to build, and I don't want to sit through youtube tutorials that don't explain how to script, or don't provide a list of methods/functions and how to use them in Unity. I would prefer answers that are more general and explain things in detail, like a written tutorial. Also, when answering these questions, please be specifc in regards to what parameters are required, and what previous parts of code or objects you are referencing, because I find that a lot of tutorials don't explain these basic things.
1. How can you store the position of an object as a variable?
2. How do you move an object to a predetermined position?
3. How do you move an object off-screen and make it reappear from the side of the screen?
4. What does transform.position do, and how do I use it?
I'm getting really frustrated because it's difficult to find simple and useful explanations on how to use Unity. But thank you for reading through this question, and please give me answers (i need help)!
Answer by unity_ek98vnTRplGj8Q · Mar 25, 2020 at 10:37 PM
I'll answer your questions as in-depth as I can given the word limit for responses on this forum, but I will attach my email so feel free to contact me for further questions. Unity can be daunting to learn, but once you get the hang of it its quite simple.
I'll start by answering your last question first. Objects that are placed in the scene are called Game Objects in Unity. Game Objects can be used for many different things, but every game object will have a component attached to it called the transform. This contains information about the position, rotation, and scale of the object it is attached to. Position and scale are straightforward, but rotation is a bit trickier once you dive into it. The Position value of the transform is a Vector3, this is simply a struct that holds 3 numbers (representing a 3-dimensional vector). These numbers indicate how far the object is along each axis (x is left/right, y is up/down, z is forward/backward). You can modify the position of an object by setting this value.
//Move my object up and to the right of the global origin => point 0,0,0 in world coordinates
myObject.transform.postion = new Vector3(1, 1, 0);
You can also add Vector3's together, for example if I want to move Object 1 to be 1 unit above Object 2:
object1.transform.position = object2.transform.position + new Vector3(0,1,0);
You can save the value of the position of an object by creating a Vector3 variable in your script.
public class SaveObjectStartingPosition : Monobehavior {
//You can drag a game object from your scene into this field in the inspector
public GameObject myObject;
private Vector3 savedPosition;
void Start(){
savedPosition = myObject.transform.position;
}
//You can now reset the position of the object to its starting position by calling this function
void MoveToStartingPosition(){
myObject.transform.position = savedPosition;
}
}
That should pretty much cover questions 1, 2, and 4. Feel free to ask for clarification, its ok to not understand this stuff right away. Question 3 is the most complicated and also the most vague, but to answer it briefly -
Your screen view is determined by a Camera in Unity. The camera is in charge of rendering objects in the scene and create a visual projection of the scene from its perspective. You if you want to move an object off-screen you can simply set its position to a position that is not visible to the camera (you can click on the camera in scene view and it will show you some lines that indicate the extents of the camera's field of view). However if you just change the object's position all at once it will just teleport to the commanded position. If you want to achieve Smooth movement you have to change the objects position tiny amounts every frame to give the illusion of a smooth transition to its target position. There are lots of different ways to do this, but here is a simple one -
public class MoveTowardsTargetPosition : Monobehavior {
//Attach this script to the object you want to move
//Set this value in the inspector
public Vector3 targetPosition;
public float moveSpeed; //You can change this value to change the speed the object moves at
void Update(){
//This code is called once every frame
//Lets start by finding the direction between our object and the target position
//You can find the direction from point A to point B via Vector subtraction
//Calling transform by itself grabs the transform that is attached to the game object that this script is attached to
Vector3 directionToMove = targetPosition - transform.position;
//Now we have the direction, but we need to calculate the distance to move.
//We will scale our direction vector to the wanted magnitude
directionToMove = directionToMove.normalized * Time.deltaTime * moveSpeed;
//A normalized vector is a vector with length 1
//Time.deltaTime is the time since Update() was last called. This is used so that we get a constant speed, regardless of frame rate
//Finish by scaling by our desired movement speed
//Now we add our direction to our current position. We are going to clamp the vector here to make sure we don't go past our target destination
float maxDistance = Vector3.Distance(transform.position, targetPosition);
transform.position = transform.position + Vector3.ClampMagnitude(directionToMove, maxDistance);
//You don't have to memorize these kinds of functions, Unity Documentation is your friend
}
}
Again there is still a lot to unpack here if you have zero Unity experience, so feel free to ask for clarification.
$$anonymous$$y email is bdoobie01@gmail.com, so feel free to email me with further questions. I usually check my email every day except on weekends
Here is a script that combines everything from above and will point you in the right direction for moving your 6 objects when you press a button. Put this on an empty game object in your scene, and drag your 6 objects into the corresponding fields in the inspector. Also make sure you attach the $$anonymous$$oveTowardsTargetPosition script to each of the 6 objects as I will use this to achieve smooth movement.
public class CycleObjects : $$anonymous$$onobehavior {
//Drag your objects here in the inspector
//Notice how I never define how many objects you need, you can drag as many object in here as you want
//Just remember that order matters, each object will cycle to the position of the next object in the list
public List<GameObject> objectList;
private List<Vector3> savedPositions;
void Start(){
if(objectList.Count == 0) Debug.Log("You havn't added any objects to the list");
//The object list is initialized for us, but we need to initialize savedPositions
savedPositions = new List<Vector3>();
foreach (GameObject obj in objectList)
{
savedPositions.Add(obj.transform.position);
//While we are looping through each object, lets make sure we set the target position to their current position
//This will keep them from moving as soon as you start the game
obj.GetComponent<$$anonymous$$oveTowardsTargetPosition>().targetPosition = obj.transform.position;
}
}
void Update(){
//When we get the key press, move each object to the next position
if(Input.GetKeyDown(KeyCode.DownArrow)){
if(objectList.Count == 0) return; //Don't do anything if our list is empty
//Loop through all of our game objects by their list index
for(int i=0; i<objectList.Count; i++){
GameObject obj = objectList[i];
//Set the target position to the next saved position
//Use modulus here to loop positions
Vector3 newTarget = savedPositions[(i + 1) % 6];
obj.GetComponent<$$anonymous$$oveTowardsTargetPosition>().targetPosition = newTarget;
}
//Once we have set new target positions for all of them they will begin moving.
//Lets change their order in the list to reflect their new positions
//$$anonymous$$oving the last object in the list to the beginning will do this for us
GameObject lastObj = objectList[objectList.Count - 1];
objectList.RemoveAt(objectList.Count - 1);
objectList.Insert(0, lastObj); //Insert at beginning of list
}
}
}
Thanks so much for your help! That was a lot faster than I expected. I'm currently busy with other things (school) but I looked through your answer and it was exactly what I was looking for. If I have any issues, I'll let you know, but it will probably take a while before I actually get back to it. Once again, thanks so much!