Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

How does one track a target gamobject far enough ahead so it can be hit?

Discussion in '2D' started by SheldonS, Jun 2, 2019.

  1. SheldonS

    SheldonS

    Joined:
    Jul 23, 2015
    Posts:
    21
    Hello everyone, I'm having some struggles with this one.

    To help me learn what I think are basic concepts in Unity I create little basic scenes, not quite a game. So far I have restricted myself to 2D.

    In this case I have a stationary turret that can rotate. I have a target gameobject that moves. The only input I do as a "player" is to fire.

    I want the turret to automatically track the target gameobject so that when I fire a projectile and the target gameobject continues on its path there will be a collision.

    For firing the projectile I kept that simple. It takes the transform of the projectile mount point (on the turret) and just applies force.

    If I try to track the target gameobject the best I can get is the turret to lag a little behind the target gameobject. Of course when I fire the projectile it misses.
     
  2. orxyandcrake

    orxyandcrake

    Joined:
    Feb 15, 2019
    Posts:
    10
    As always there is more than one way to solve this.
    1. have a ghost object that leads the target and that's what the turret shoots at
    2. have the target follow where the turret aims instead of the turret aim following the target.
    3. Adjust the origin point of the target out in front of the target so that the collider follows behind
    4. Do some crazy math to predict where the target will be next. (Probably not though)

    Basically, think outside the box (both figuratively and literally) you want to appear to be shooting at the target, not actually shooting at it.
    example_2.png
     
    Last edited: Jun 3, 2019
  3. Code02

    Code02

    Joined:
    Sep 30, 2018
    Posts:
    4
    From what i understood in your post, you want to make some sort of a homing attack? it's fairly simple but you to know a tiny bit about vectors.

    First you need a direction to your target and hence you'll subtract your current position from your target's and then make sure your vector magnitude is 1.

    and now if you cross product your direction to the target and the vector that holds your bullet movement lets say it always moves right so it's Vector2.up you'll get a product which is the angle needed to rotate in order to reach that object(look at image above), and all you'll have to do is set the Z (since it's 2D) rotation to that angle and you'll get a result that looks like this

    https://thumbs.gfycat.com/SourGrandKentrosaurus.webp
     
  4. SheldonS

    SheldonS

    Joined:
    Jul 23, 2015
    Posts:
    21
    Thank you. Using what you two hinted at I am able to calculate a point that leads my target. I don't know if it leads enough as I now have to get my turret to rotate fast enough.

    I know I am leading the target because I used a deb ray from the turret transform to my new target point.

    As you can see I have tried a few things to get the turret to rotate, it just doesn't go fast enough. Again thank you both for your help.

    Code (CSharp):
    1.     private void UseSlope(Transform target)
    2.     {
    3.         Ball ballScript = target.GetComponent<Ball>();
    4.         Tuple<float, float> riseRun = ballScript.GetRiseRun();
    5.         defaultModifier = Mathf.Sqrt(Mathf.Pow(target.position.x - transform.position.x, 2f) + Mathf.Pow(target.position.y - transform.position.y, 2f));
    6.         float yRise = riseRun.Item1;
    7.         float xRun = riseRun.Item2;
    8.         float slope = 0;
    9.         float xRunModifer = defaultModifier;
    10.         float yRiseModifier = defaultModifier;
    11.  
    12.         if(xRun == 0)
    13.         {
    14.             //Moving up and down
    15.             xRunModifer = 0f;
    16.         }
    17.         else if(yRise == 0)
    18.         {
    19.             //Moving side to side
    20.             slope = yRise / xRun;
    21.             yRiseModifier = 0f;
    22.         }
    23.         else
    24.         {
    25.             //Moving at an angle
    26.             slope = yRise / xRun;
    27.             yRiseModifier = slope;
    28.             xRunModifer = slope;
    29.         }
    30.  
    31.         Vector3 targetPoint = new Vector3(
    32.             target.position.x + xRun * xRunModifer,
    33.             target.position.y + yRise * yRiseModifier,
    34.             transform.position.z);
    35.         Debug.DrawLine(transform.position, targetPoint, Color.magenta);
    36.  
    37.         Vector3 _direction = (targetPoint - transform.position);
    38.         Quaternion _lookRotation = Quaternion.LookRotation(_direction);
    39.         //Quaternion _lookRotation = Quaternion.Euler(targetPoint);
    40.         //Quaternion _lookRotation = Quaternion.LookRotation(targetPoint);
    41.  
    42.         //transform.rotation = Quaternion.Slerp(transform.rotation, _lookRotation, Time.deltaTime * slerpSpeed);
    43.         //transform.rotation = Quaternion.Slerp(transform.rotation, _lookRotation, slerpSpeed);
    44.         transform.rotation = Quaternion.RotateTowards(transform.rotation, _lookRotation, maxRadianDelta);
    45.     }
     
  5. orxyandcrake

    orxyandcrake

    Joined:
    Feb 15, 2019
    Posts:
    10
    There are multiple factors to consider here.
    1. Velocity of target
    2. Direction of target on the x and y axis
    3. Velocity of projectile
    4. Rotational velocity of the turret

    In order to get this to work you need to be balance of all these things.

    But in order to fix the issue you can adjust anyone of them.
    You could:
    A. slow down the target (assuming that the velocity is not linked to the rotation of the turret)
    or,
    B. speed up the projectile (The greater the distance to the target the faster the projectile would need to travel)
    or,
    C. Speed up the rotation of the turret to account for both the velocity of the the target and the velocity of the projectile

    If you have a separate constant for each objects velocity. Then adjusting the velocity value of any one of them will change the balance in either in a positive way or a negative way. From this you can incrementally ascertain the right formula to hit the target by changing just one of the three values, once you have that you can then derive a formula that will always hit the target.

    For example
    If the speed of the target (v1) is 1 and the speed of the turret (v2) is v1 x 2, then the speed of the projectile (v3) needs to be z?

    Once you know what z is by incrementally increasing v3 you then know the ratio you need.
    After that when you change one of the three values you then need to adjust the other values to compensate.
    For example you could speed up the target but you would then need to speed up the projectile. Or increase the projectile and the turret speed proportionately.

    You can think of the the values like the three points on a triangle where moving one point changes it's relationship to the other two points

    Suggestion: Change the speed of the projectile so that it gets to the target at the right moment and then work backwards from there.