Search Unity

How to make a missile going in a specific direction

Discussion in '2D' started by DamnNickname, Mar 19, 2016.

  1. DamnNickname

    DamnNickname

    Joined:
    Mar 1, 2016
    Posts:
    16
    Hi,

    So my problem is that i want the missile to go to a specitif point on the map, but once it reach this point, i want it to continue going the same way until he go out of the way

    Quick example : http://puu.sh/nMtsq/ae8f361b7e.png

    The missile ( red dot ) will go his destination ( black dot ), but keep going on forever ( green line ) even after reaching his destination.

    I keep the position of the destination, i used MoveTowards() but the missile stop once reaching his destination

    Any idea ?

    Thank you
     
  2. jc-drile77

    jc-drile77

    Joined:
    Jul 1, 2014
    Posts:
    230
    Use MoveTowards() and then get the vector of the velocity (or the value the transform changes in each frame) and keep aplying them.

    Code (CSharp):
    1.   private  Vector3 direction;
    2.     public Vector3 target;
    3.     public float speed=0.1f;
    4.     // Use this for initialization
    5.     void Start () {
    6.         direction = Vector3.MoveTowards(transform.position, target, speed);
    7.  
    8.     }
    9.  
    10.     // Update is called once per frame
    11.     void Update () {
    12.         transform.position = transform.position + direction;
    13.  
    14.     }
    But I would suggest using rigidbodies if they have colliders, moving a collider or a rigidbody using it´s transform is quite expensive.
     
    Last edited: Mar 20, 2016
  3. DamnNickname

    DamnNickname

    Joined:
    Mar 1, 2016
    Posts:
    16
    So I did as you told me, just modify the target from a Vector3 to a Transform ( since it's the position of the player, that can change every frame )

    But on the inspector, even tho i put the player transform, he always told me that the " target " variable has not been initialized

    Any idea ?


    The missile also go at the speed of light, for some weird reason

    As you said with the rigidbody, the missile do have one

    Code (CSharp):
    1. private  Vector3 direction;
    2. public Transform target;
    3.  
    4.     void Start ()
    5.     {
    6.         direction = Vector3.MoveTowards(transform.position, target.position, speed);
    7.     }
    8.  
    9.  
    10.  
    11.     void Update()
    12.     {
    13.      
    14.         transform.position = transform.position + direction;
    15.  
    16.  
    17.     }
     
    Last edited: Mar 20, 2016
  4. jc-drile77

    jc-drile77

    Joined:
    Jul 1, 2014
    Posts:
    230
    You have to set the target :) to where do you want it to go?
     
  5. DamnNickname

    DamnNickname

    Joined:
    Mar 1, 2016
    Posts:
    16
  6. jc-drile77

    jc-drile77

    Joined:
    Jul 1, 2014
    Posts:
    230
    My bad :C, try this:
    It might not be the best solution but it´s the way I would go, play with it and modify it to your needs, I do not know what you need :)
    Code (CSharp):
    1.  
    2.     private Vector3 direction;
    3.     public Transform target;
    4.     public float speed = 15;
    5.     void Start()
    6.     {
    7.         direction = Vector3.MoveTowards(transform.position, target.position, 2);
    8.         print(direction);
    9.     }
    10.  
    11.  
    12.     public float closeDistance = -1.0F;
    13.     void Update()
    14.     {
    15.         Vector3 offset = target.position - transform.position;
    16.         float sqrLen = offset.sqrMagnitude;
    17.         //Negative values of maxDistanceDelta can be used to push the point away from the target.
    18.         if (sqrLen < closeDistance * closeDistance)
    19.             speed *= -1;
    20.         float step = speed * Time.deltaTime;
    21.  
    22.         transform.position = Vector3.MoveTowards(transform.position, target.position-direction, step);
    23.     }
     
    Last edited: Mar 20, 2016
  7. DamnNickname

    DamnNickname

    Joined:
    Mar 1, 2016
    Posts:
    16
    I have 2 questions

    First one : what is that last parameter in MoveTowards use for ? Why 2 ?

    Second : what is that closeDistance variable ? And what it is use for ?
     
  8. DamnNickname

    DamnNickname

    Joined:
    Mar 1, 2016
    Posts:
    16
    It kinda work but there is one little problem

    The player position is the public Transform target


    Here is a small picture to show you what i'm after : http://puu.sh/nNrvy/2b0fe94540.jpg

    The missile take the position of the player when the missile is being shoot, and will go to the position of the player.
    But if the player move, the missile keep going in the same direction in a straight line

    Wich the code you gave me, in kind of does that, but if the player move, the new missile won't go to his new position.

    Also the missile stop right before getting to that position, they don't keep going on forever
     
  9. jc-drile77

    jc-drile77

    Joined:
    Jul 1, 2014
    Posts:
    230
    Is this what you want to achive?
    You will need to add a rigidbody to the missile (you should already had added) and set it´s gravity scale to 0.
    Code (CSharp):
    1.     private Vector3 direction;
    2.     public Transform target;
    3.     public float speed = 15;
    4.     private bool collided=false;
    5.     public float closeDistance = 1.0F;
    6.  
    7.     void Update()
    8.     {
    9.         float step = speed * Time.deltaTime;
    10.         Vector3 offset = target.position - transform.position;
    11.         float sqrLen = offset.sqrMagnitude;
    12.         if (sqrLen < closeDistance * closeDistance&&!collided)
    13.         {
    14.             collided = true;
    15.             direction = Vector3.MoveTowards(transform.position, target.position, step);
    16.         }
    17.         if (!collided) {        
    18.         transform.position = Vector3.MoveTowards(transform.position, target.position, step);
    19.         }
    20.         else
    21.         {
    22.             GetComponent<Rigidbody2D>().velocity = direction;
    23.  
    24.         }
    25.     }
     
    Last edited: Mar 20, 2016
  10. jc-drile77

    jc-drile77

    Joined:
    Jul 1, 2014
    Posts:
    230
    Instead of all this you could also use rigidbodies, colliders2D and OnTriggerEnter2D or OnCollisionEnter2D...
     
  11. Zaflis

    Zaflis

    Joined:
    May 26, 2014
    Posts:
    438
    This comes to mind:
    Code (CSharp):
    1.     public Transform target;
    2.     public float speed = 15;
    3.  
    4.     Vector3 direction;
    5.     Vector3 pos;
    6.  
    7.     void Start() {
    8.         pos = transform.position;
    9.         direction = target.position - transform.position;
    10.         direction.Normalize();
    11.         direction *= speed;
    12.     }
    13.  
    14.     void Update() {
    15.         pos += direction * Time.deltaTime;
    16.         transform.position = pos;
    17.     }
    And if you use rigidbody, all you need to do is AddForce() to make missile fly. But you still need to count the direction, possibly like this code.
     
    Last edited: Mar 20, 2016
  12. jc-drile77

    jc-drile77

    Joined:
    Jul 1, 2014
    Posts:
    230
    Yes, but if I understood well it has to follow the player till it collides, and that code just shoots its towrds its initial direction
     
  13. Zaflis

    Zaflis

    Joined:
    May 26, 2014
    Posts:
    438
    He showed a picture of player moving to side and avoiding it. Missile kept going straight line. So i assume we don't have a "homing missile" scenario.
     
  14. jc-drile77

    jc-drile77

    Joined:
    Jul 1, 2014
    Posts:
    230
    Oh, my bad ^^, if anyone is interested tho here is the code for what I understood at first:
    Go towards the player and upon reaching it keep the same direction to infinity :S
    Code (CSharp):
    1.    private Vector3 direction;
    2.     public Transform target;
    3.     public float speed = 15;
    4.     private bool collided=false;
    5.     public float closeDistance = 1.0F;
    6.  
    7.     void Update()
    8.     {
    9.         float step = speed * Time.deltaTime;
    10.         Vector3 offset = target.position - transform.position;
    11.         float sqrLen = offset.sqrMagnitude;
    12.         if (sqrLen < closeDistance * closeDistance&&!collided)
    13.         {
    14.             collided = true;
    15.             direction =target.position - transform.position;
    16.         }
    17.         if (!collided) {            
    18.         transform.position = Vector3.MoveTowards(transform.position, target.position, step);
    19.         }
    20.         else
    21.         {
    22.             GetComponent<Rigidbody2D>().velocity = direction.normalized*speed;
    23.  
    24.         }
    25.     }
     
  15. DamnNickname

    DamnNickname

    Joined:
    Mar 1, 2016
    Posts:
    16
    " Go towards the player and upon reaching it keep the same direction to infinity :S "

    How can i do that ?

    Also i don't know if, giving the player from the Unity inspector is a good idea or not, it seem that all the "target" never change, and keep the one of the prefab
     
  16. jc-drile77

    jc-drile77

    Joined:
    Jul 1, 2014
    Posts:
    230
    What you want to do is what Zaflis posted, I understood your question wrong, sorry
    For that use this code
    Code (CSharp):
    1.    private Vector3 direction;
    2.     public Transform target;
    3.     public float speed = 15;
    4.     private bool collided=false;
    5.     public float closeDistance = 1.0F;
    6.  
    7.     void Update()
    8.     {
    9.         float step = speed * Time.deltaTime;
    10.         Vector3 offset = target.position - transform.position;
    11.         float sqrLen = offset.sqrMagnitude;
    12.         if (sqrLen < closeDistance * closeDistance&&!collided)
    13.         {
    14.             collided = true;
    15.             direction =target.position - transform.position;
    16.         }
    17.         if (!collided) {            
    18.         transform.position = Vector3.MoveTowards(transform.position, target.position, step);
    19.         }
    20.         else
    21.         {
    22.             GetComponent<Rigidbody2D>().velocity = direction.normalized*speed;
    23.  
    24.         }
    25.     }
     
  17. DamnNickname

    DamnNickname

    Joined:
    Mar 1, 2016
    Posts:
    16
    I used this code, but the missile go to the player's position, but then don't move, he don't keep going on forever
     
  18. Zaflis

    Zaflis

    Joined:
    May 26, 2014
    Posts:
    438
    The other code also includes the part where missile can explode when it hits player. That's why it stops moving. Try avoiding the hit? My code above keeps going forever, but is there point with missiles that can't hit player?
     
  19. DamnNickname

    DamnNickname

    Joined:
    Mar 1, 2016
    Posts:
    16
    Zaflis : Your code work, but the missile go at the speed of light. No idea why ( also, they keep going on but once they are out of the screen, i delete them )
     
  20. jc-drile77

    jc-drile77

    Joined:
    Jul 1, 2014
    Posts:
    230
    His code works fine, probably you have set the speed too high.
    Mine works fine too, just tested it.

    For the other matter just make a pool.
     
  21. DamnNickname

    DamnNickname

    Joined:
    Mar 1, 2016
    Posts:
    16
    Hmm yhea i lower it a bit ( it was only at 2 tho )

    So this work, but the problem is that, if i move the player to another position, and a new missile is being shoot, this missile won't go to the next player location.

    I gave to the missile ( from the Unity inspector ) the player's transform, do i have to give the player transform tho the code in the Update() function ? Because I feel like the prayer position is never updated and stay fixe
     
  22. DamnNickname

    DamnNickname

    Joined:
    Mar 1, 2016
    Posts:
    16
    I tried

    GameObject tmp = GameObject.Find("Player");
    this.target = tmp.transform.position;


    But it told that it's never the instance of an object.

    Also tried with tmp.GetComponent, same result
     
  23. Zaflis

    Zaflis

    Joined:
    May 26, 2014
    Posts:
    438
    I forgot the deltatime, edited my code above too. Shouldn't go so fast, and you need this for equalizing speed on all computers:
    Code (CSharp):
    1. pos += direction * Time.deltaTime;
    And now it's back to homing missile again? This is what you get when not explaining the problem clearly. It seems we still don't know what kind of game you are really after. What is the big plan for this missile?
     
  24. DamnNickname

    DamnNickname

    Joined:
    Mar 1, 2016
    Posts:
    16
    Sorry, i'm not very good for explaining :D

    To make it clear :

    -> The ennemy shoot a missile where the player is
    -> The missile will go to that position in a straight line, and keep going on forever if he don't touch the player

    So everytime a ennemy shoot a missile, it will go to the known player's position

    Don't know if it's clear now ? x)
     
  25. Zaflis

    Zaflis

    Joined:
    May 26, 2014
    Posts:
    438
    Missile script needs to set the direction vector at the moment of firing a missile. I just assumed that when new missile is launched, it gets its new script loaded and that automatically calls Start() again and again. Use Destroy(gameObject); for missile object when missile goes off screen, and instantiate new missile object when launching one.

    Or give it a public void Fire(GameObject newTarget) that does the same thing as Start(). Then you don't have to destroy old missile, but reuse it. Sounds like you are reusing the old thing currently?
     
  26. DamnNickname

    DamnNickname

    Joined:
    Mar 1, 2016
    Posts:
    16
    "Missile script needs to set the direction vector at the moment of firing a missile"
    That direction vector is ( from your code, in the Start() function ) :
    direction = target.position - transform.position;

    So when i instantiate a new missile, in a ennemy's script, i have to give him the target variable, wich is equal to the player's position ?

    " Sounds like you are reusing the old thing currently? " , I don't, i create a new missile everytime, and delete it if he go out of the screen / touch the player

    So in my EnnemyScript i made this

    GameObject missile = Instantiate (shot, new Vector3(transform.position.x, transform.position.y + 0.5f, 0.0f), shotspawn.rotation) as GameObject;

    missile.GetComponent<MissileScript> ().target = GameObject.Find ("Player").transform;

    But even with that, the missile don't go towards the player's location
     
    Last edited: Mar 20, 2016
  27. Zaflis

    Zaflis

    Joined:
    May 26, 2014
    Posts:
    438
    If you refer to this code:
    GameObject tmp = GameObject.Find("Player");
    this.target = tmp.transform.position;

    change tmp.transform.position to tmp.transform. Because this.target is transform too. And avoid GameObject.Find() as much as you can, it makes game slower. Especially if you use it alot in Update().
     
  28. DamnNickname

    DamnNickname

    Joined:
    Mar 1, 2016
    Posts:
    16
    I don't use it in a Update(), since i only want to save the position of the player when the missile is being shoot by the ennemy ( otherwise it will keep updating the player position and the missile will follow him )

    So i have to use
    GameObject tmp = GameObject.Find("Player");
    this.target = tmp.transform.position;

    in the Start() function of the Missile script right ?
     
  29. Zaflis

    Zaflis

    Joined:
    May 26, 2014
    Posts:
    438
    You missed my tip -.- You can't assign Vector3 to Transform. What code do you have to create a new missile? I'd recommend setting the target there, if it's not already set in Inspector for prefab.
     
  30. DamnNickname

    DamnNickname

    Joined:
    Mar 1, 2016
    Posts:
    16
    Yhea sorry didn't see, i changed it

    I just figure out where my mistake where.

    I was 100% sure GameObject.Find(); took the Tag name as parameter but was not the case . . .

    Thank you so much.

    Just simple question : once again the missile speed was super fast, i had to put it at 0.06
    I don't think it's normal right ?
     
    Last edited: Mar 20, 2016
  31. Zaflis

    Zaflis

    Joined:
    May 26, 2014
    Posts:
    438
    Are you still moving the missile with this code as suggested?
    Code (CSharp):
    1. pos += direction * Time.deltaTime;
    2. transform.position = pos;
    3.  
    4. // And last line in Start()
    5. direction.Normalize();
    It being normal depends on what scale you are using for your objects. But i'd expect speed 1 moving slowly enough generally.
     
    Last edited: Mar 22, 2016
  32. DamnNickname

    DamnNickname

    Joined:
    Mar 1, 2016
    Posts:
    16
    Yhea i moved it with the code you gave me

    Work 100% fine now, thank a lot ! :)