- Home /
Setting target position in Vector3.MoveTowards
I would simply like to open a door, but after spending 3 hours on this very simple piece of code, I have realised I need help, and it may not be a door I want to open.
In any case...
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SlidingLeftDoor : MonoBehaviour
{
public Transform doorLeft; // takes the transform of the door GameObject
Transform doorLeftClosed, doorLeftOpen; // sets open and closed positions, for opening then returning to being closed
public float openSpeed;
void Start()
{
// I expect I've initialised all this crap in the wrong place.
doorLeftClosed = doorLeft;
doorLeftOpen = doorLeft;
//The line below is my attempt to set the target position. Instead, it just opens the door:
doorLeftOpen.position = doorLeft.position + new Vector3(-1.3f,0f,0f);
//The line below is my next attempt...I think it equates to the same thing as the line above. It also just opens the door:
doorLeftOpen.position = new Vector3(doorLeft.position.x-1.3f,doorLeft.position.y,doorLeft.position.z);
}
void Update()
{
// The line below probably works, but I wouldn't know for sure because the door is already open by this point.
doorLeft.position = Vector3.MoveTowards(doorLeftClosed.position, doorLeftOpen.position, openSpeed*Time.deltaTime);
}
}
It's pretty simple. All I want to do is set the MoveTowards target as doorLeftOpen. How do I do that please?
Answer by xxmariofer · May 21, 2019 at 07:31 AM
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SlidingLeftDoor : MonoBehaviour
{
public Transform doorLeft; // takes the transform of the door GameObject
Vector3 doorLeftClosed, doorLeftOpen; // sets open and closed positions, for opening then returning to being closed
public float openSpeed;
private Vector3 target;
void Start()
{
// I expect I've initialised all this crap in the wrong place.
doorLeftClosed = doorLeft.position;
//The line below is my attempt to set the target position. Instead, it just opens the door:
doorLeftOpen = doorLeft.position + new Vector3(-1.3f,0f,0f);
target = doorLeftOpen;
}
void Update()
{
// The line below probably works, but I wouldn't know for sure because the door is already open by this point.
doorLeft.position = Vector3.MoveTowards(doorLeft.position, target, openSpeed*Time.deltaTime);
if(target == doorLeft.position)
{
if(target == doorLeftOpen)
target = doorLeftClosed;
else
target = doorLeftOpen;
}
}
}
to be honest i dont remmember if the movetowards reachs 100% target destination so maybe you need to use aproximation. Your solution wasnt working because transform is a reference not a copy, transform is a reference but the position is a copy :) and the move towards was being used as a mix of movetowards/lerp since movetowards doesnt lerp between position just adds an extra step towards the target you need to use the door transform.position as the initial pose
move towards does get there if triggered in Update, because it is checked every frame and moves, multiplied by Time.deltaTime.
I don't follow what you mean by "transform is a reference but the position is a copy". $$anonymous$$oveTowards does what Lerp does, it just does it in even steps ins$$anonymous$$d of using linear interpolation.
$$anonymous$$oveTowards needs (initial_position, target_position, moveSpeed) - initial position is doorLeft.position - moveSpeed is moveSpeed * Time.deltaTime - how the hell do I store the target position?!??
That's all I'm asking.
not sure if i really explained that bad haha, i wasnt talking about reaching the line code, but reaching the target position, since it moves step by step but i have just checked the code and is completly working did you try it? by transform is a reference but the position is a copy i mean exactly that, transform has a reference to the component, not a copy, if you move the second transform it will also move the first one (with the position is always a copy, thats just how unityengine works thats why you said "The line below is my attempt to set the target position. Ins$$anonymous$$d, it just opens the door"), second by the lerp/movetowards i was trying to explain that you were trying to use the movetowards method as if it was an interpolation method, trying to interpolate from a position A to a position B gradually, but it doesnt interpolate like lerp those, it just adds an step from the initial position in B direction so what you are using as initial pose should be the actual position of the object. to store the target position juust store it in a vector3 but the code i provided is working 100% not sure why you didnt even try it
Hi xxmariofer,
The code doesn't seem to be working for me, unfortunately.
doorLeftClosed = doorLeft.position //Error - Cannot implicitly conver type "UnityEngine.Vector3" to "UnityEngine.Transform"
Same error with: target = doorLeftOpen;
Also, warning: Field "doorLeftOpen is never assigned to, and will always have its default value null".
Answer by Meishin · May 21, 2019 at 07:51 AM
Hello @Altissimus, If i understand properly, you want to move the door from it's "Closed" Position to it's "Open" Position.
The issue in your Start is that you define the "Closed" Transform & the "Open" Transform as being the door Transform itself (pointers), and then you change the position of the "Open" transform which therefore change the position of you door.
doorLeftClosed = doorLeft;
doorLeftOpen = doorLeft;
There are thousands or possible methods, this is one (not tested but should work if you remove typos :p) ;
public class SlidingLeftDoor : MonoBehaviour
{
public Transform doorLeft;
public float openSpeed;
// You can define the translation here it its constant, otherwise you can define it in a Start Method
private vector3 doorLeftOpen = New Vector3(-1.3f,0f,0f) // Define the position you want to move to
private bool isOpen = false; // State boolean -- For the sake of the test
private bool isEnabled = true; // State boolean -- For the sake of the test
// Then apply a generic translate method whenever you see fit
// For the sake of the example, the door will loop open - close sequence
void Update()
{
// Open
if (!isOpen && isEnable){
Translate(doorLeft, doorLeftOpen, openSpeed);
// We dont want anything to interact while door is opening/closing
StartCoroutine(OpenDoorDelay(openSpeed));
}
// Close
elseif(isOpen && isEnable){
Translate(doorLeft, -doorLeftOpen, openSpeed);
StartCoroutine(OpenDoorDelay(openSpeed));
}
}
// Define a generic method you'll use on whatever object (note that it doesnt need to be in the door class)
public void Translate(Transform myObjectTransform, Vector3 myNewRelativePosition, Float openSpeed){
// From relative to absolute position
Vector3 EndPosition = myObjectTransform.Position + myNewRelativePosition;
// Move object
myObjectTransform.position = Vector3.MoveTowards(myObjectTransform.position, EndPosition, openSpeed*Time.deltaTime);
}
// Use Corouting to delay interactions while door opening/closing -- for the example
IEnumerator OpenDoorDelay(float Speed)
{
isEnable = false; // Forbid door to be opened/closed again
yield return new WaitForSeconds(Speed);
isOpen = !isOpen ; //Switch Open/Close state
isEnable = true; // Allow door to be opened/closed again
}
}
Thank you for this $$anonymous$$eishin.
I still can't make this work , however. Your code above contains a bunch of coolio coroutines and such, but parking all that, it still doesn't address the delicate subject of how we set the target position for the doorLeftOpen position.
You suggested: private Vector3 doorLeftOpen = new Vector3(-1.3f,0f,0f)
which, adjusted for capitalisation, simply sets the target position as the same location forever, rather than relative to the door's starting position. So if doorLeft was at Vector3(100,100,100) it would move a helluva long way. Ins$$anonymous$$d, all I'd really like it to do is shift 1.3 units on the x axis.
Using your inspiration I tried intialising doorLeftOpen as such: Vector3 doorLeftOpen = new Vector3 (doorLeft.position.x-1.3f, doorLeft.position.y, doorLeft.position.z);
however...
...if I initialise this in the forward declares, it says "A field initializer cannot reference the non-static field, method or proerty"
...if I chuck it in Start then Update says "The name 'doorLeftOpen' does not exist in the current context", and
...if I pop it in to Update then the doorLeftOpen moves beautifully...and keeps going, forever.
Here's the code, clean.
public class SlidingDoor : $$anonymous$$onoBehaviour
{
public Transform doorLeft;
Transform doorLeftClosed;
public float openSpeed;
void Start()
{
doorLeftClosed = doorLeft;
}
void Update()
{
Vector3 doorLeftOpen = new Vector3(doorLeft.position.x-1.3f, doorLeft.position.y, doorLeft.position.z);
doorLeft.position = Vector3.$$anonymous$$oveTowards(doorLeftClosed.position, doorLeftOpen, openSpeed*Time.deltaTime);
}
}
ALL I want to do is set the target position of the Vector3.$$anonymous$$oveTowards. Leaving aside Coroutines, bools, and if statements, and using just transform/vector3/position, how do I do this?
Hello @Altissumus,
Well in my code the position is relative since when you use "Translate" it add up to the current position of your transform.
Tho i guess my code is not working because the Time.deltaTime needs to be called every frame (in Update).
You can just modify your code a little: - Put Vector3 doorLeftOpen = new Vector3(-1.3f,0f,0f) in your class declaration - then you just have to add it to your original game object position before moving it (otherwise it will translate infinitely since it will move your object and add the vector in a loop fashion), something like:
in Start : doorLeftOpen = doorLeftOpen + doorLeft.position
Then in update: doorLeft.position = Vector3.$$anonymous$$oveTowards(doorLeftClosed.position, doorLeftOpen, openSpeed*Time.deltaTime);
Your answer
Follow this Question
Related Questions
How to smooth movement object in one-axis? 1 Answer
2D Background Stop Moving on BoundingBox Exit? 2 Answers
Moving an Object - The right way. 2D 1 Answer
Reposition to minimum distance from target 2 Answers
Circle inside Circle 1 Answer