Homing missiles issues : Never hits the target
Hello, something is incorrect about my code, my homing missiles never hits the target they pass by the target rotate and pass from the side, they end up doing an atom animation .. just like this http://bit.ly/1Jb3zrf this is my code :
Rigidbody2D rb2d; public float Speed; public float TTL; public Vector3 fakeTarget_01;
private GameObject targetEN;
private Vector2 dist;
private Vector2 dir;
private float angle;
void Start () {
rb2d = GetComponent<Rigidbody2D>();
targetEN = GameObject.Find("EN_TUT_01");
Destroy(gameObject, TTL);
fakeTarget_01 = new Vector3(transform.position.x + 3, transform.position.y, transform.position.z);
}
void Update ()
{
dir = rb2d.velocity;
angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
HomingPhysics();
}
public void HomingPhysics()
{
if (targetEN != null)
{
transform.rotation = Quaternion.AngleAxis(angle, Vector3.forward);
dist = fakeTarget_01 - transform.position;
dist = dist.normalized;
//rb2d.AddForce(fakeTarget_01 * Speed);
rb2d.AddForce(dist * Speed);
StartCoroutine(Fly());
}
}
public IEnumerator Fly()
{
yield return new WaitForSeconds(0.5f);
fakeTarget_01 = targetEN.transform.position;
}
Answer by Kiwasi · Aug 22, 2015 at 01:55 AM
This is normal behaviour for seeking type misiles. Once they get too close to the target then there own speed keeps them moving faster then the targeting system can adjust, producing orbit like behaviour.
Typically you would solve this by turning guidance off once you are within a certian distance of the target.
Thanks @Bored$$anonymous$$ormon , however the targeted object is not moving at all ! and the missiles keeps going around it ins$$anonymous$$d of hitting it, I will try what you suggested in a $$anonymous$$ute and post the result.
I turned ho$$anonymous$$g off and still no matter what .. changing speed moving right or left while shooting still the ho$$anonymous$$g missiles are too friendly to hit the target .. only if real life weapons were like this -.- no one would have died.
I am having the exact same issues. Obviously the missile shoots past the target, then turns and seeks the target again, except this is happening so quickly that it just orbit the target. I've added a fuse to my missile so they self destruct after 10 seconds, but I don't want it to circle the target for 8 seconds and then blow up.
I tried turning off guidance when it's within a certain range, but that isn't working quite right either.
Incidentally, my code seems to be much simpler than this. Not better, but simpler:
float distance = Vector3.Distance(Target.position, $$anonymous$$issile.position);
if (distance > StopDistance)
{
transform.LookAt(Target);
}
Force = $$anonymous$$athf.Clamp(Force * Acceleration, 0, $$anonymous$$axForce);
$$anonymous$$issile.AddRelativeForce(Vector3.forward * Force);
Basically, I just look at the target, then blast thrusters.
Answer by Teravisor · Jan 22, 2016 at 08:18 PM
The problem is, you're trying to hit something while applying force directly to it. Let me give you a different system that actually guides your rockets to target instead blindly 'gravitating' towards it like planets.
Let's divide force into two components: forward acceleration and rotation. Force you apply to rocket is sum of them. Rotation force should always act perpendicular(either left or right) to your speed vector while acceleration force must act to increase speed(forward).
First, we calculate if we need to rotate our speed vector(usually RigidBody2D.velocity
) to face target. If we need to rotate our velocity, we apply full force perpendicular to target (making a circular trajectory so that our speed targets where we need). If our velocity is directed almost into enemy, we start 'rebalancing' force from rotation into acceleration. So when we're nearly at set angle, we decrease our perpendicular force and increase forward force so we rotate slower but start to actually accelerate. At some point we don't need to rotate anymore and we just accelerate at full speed.
If your target is moving, instead of adjusting to target you simply adjust to target position+target velocity * coefficient where coefficient depends on distance from rocket to enemy (limited from maximum though, otherwise you'll see rockets flying in parallel to enemy sometimes) and is 0 when rocket is very very close to enemy.
Everything I wrote here is introduction into steering behariours, you might want to look into them.
I have one piece of additional advice: fast moving projectiles should use raycasting instead of physics as even with interpolation mode I've seen a lot of projectiles missing target at high speeds even though they should've hit them.
That sounds exactly like what I'm doing. The problem is, even with what you're saying, that if the rocket is not 100% on target and moves past the target, it's going to go back to rotational force and turn the rocket again to face the target, then go back to thrust and go at the target. This process repeats and you end up with the rocket orbiting the target again.
We've seen two different approaches, one using movement (fsoufi), and my version which uses actual forces. Back in the day, before I used an engine with physics, I'd just write a simple "if target is above rocket, then rocket.Y +=1" (and it's opposite) which continues until no adjustment is needed for the vertical axis. But here, we have physics, and both of these systems still amount to slightly missing the target, correcting, missing, correcting.... orbit.
Perhaps I don't understand the difference between what you're proposing and what we're doing, but I would think a LookAt
statement with AddRelativeForce
in the forward direction would hit the target, especially when it's very far away and there's been plenty of time for it to make those course corrections. $$anonymous$$y practice target is stationary, and I've fired from about 1km to 5km away, with plenty of time for the missile to line up properly, and yet, 100% of the time, it comes in below the target, then rotates around it in a decaying orbit before hitting the target.
If you're suggesting turning off the AddRelativeForce while applying the LookAt, then when it's looking at the target, turning AddRelativeForce back on, I can try that, but I don't believe the result will differ.
/// New idea Hmmm... It seems to me that what we're working with here might be accomplished using a simple Lerp command with the Target and the Rocket's coordinates, and the lerp amount being the speed of the rocket. Then detonating when the distance between Rocket and Target is a certain amount, or in the OnCollision.
@Tanoshimi2000 Don't know, in my case I've had rockets with model I described above with raycasting to decide if they hit or not, and they did hit in about 90% cases(rest 10% were they were too close so they had to do what previous answer described - fly away and then return). In your code I've only seen applying force forward towards target. That's exactly same planets do to sun. Then don't actually hit sun, do they? What I propose you first apply force perpendicular to target. Not forward, but right or left to correct it so direction of speed vector will actually face target. And only when forward vector of current speed(not rotation of object!) targets exactly at target we apply force forward. By speed I mean Rigidbody2D.velocity
Also, lerp might work, but if your target is moving and lerp between initial position and target position rocket's side drag will become visible as drastic speed increase, especially by the end of path. In some cases that is what you want (accelerating rocket) but sometimes you don't want that (airplane following airplane uses same mechanics plus deceleration when near target - that's what steering behaviours are about).
@Teravisor UPDATE: So, I changed to a Lerp Routine, and it actually works as you'd expect. The missile flies straight at the target, and does not go past it. There is one caveat. If the Lerp Amount is high, the missile will actually make it to the target, but so quickly it doesn't look real. Lower Lerp Amounts don't get the missile all the way to the target. What I've done, is started with a low LerpAmount and increased it each iteration, giving us that acceleration you'd expect from a missile. But the Rigidbody has to be off, and the missile never touches the target, so I have it explode within a certain distance of the target.
void FixedUpdate () {
if (!IsFired) return;
transform.LookAt(Target.position); // So rocket isn't flying sideways. could Lerp this, but it's so quick it's not worth the "turning"
transform.position = Vector3.Lerp(transform.position, Target.position, Speed * Time.deltaTime);
Speed = Speed * (1 + Time.deltaTime); // Increase speed to account for acceleration.
// Check for contact
float Dist = Vector3.Distance(transform.position, Target.position);
if (Dist<1)
Explode();
// Detonate after 5 seconds
if ((Time.time - LaunchTime) > Fuse) Explode();
}
Couple things I may try to improve it are adding a non Rigidbody collider, moving this from FixedUpdate to Update (since no physics are being used), doing a raycast towards Target so that it could chase chaff, and playing with the LerpAmount and Speed as well as the distance to cause explosion.
I did want to comment on the last post from Teravisor: You mention planets orbiting the sun, but that's not accurate here because those are being acted upon by the gravitation force of the sun. The Target is not pulling the missile towards it. Also, you mention no force perpendicular to the target, but that's all that's being applied because of the LookAt. Basically, if the missile is facing the target (and it is always because the LookAt comes before the application of force), then the current force vector being applied is directly towards the target. Sure it has to overcome the prior force vector which has built up, but it should never reach that point since it should've been aimed at the target well before it got "too close" to turn. Not sure why it was always co$$anonymous$$g in low, unless gravity was playing too large a role. But it's like the old Asteroids game, and that's how my system worked: You face the direction you want to go, then you hit the thrusters. There will be some sliding as you overcome the direction you were already going but you eventually end up going in the direction you want. Unfortunately, with the missile, it was never getting on track.
But at least there's a version I can use that will hit a moving target and explode.
Answer by LucasFamelli · Jan 02, 2017 at 03:44 PM
Same thing here. I solved using "Transform.Translate" instead of using AddForce.
private void Propel() {
//m_rb.AddForce(m_rb.transform.up * m_acceleration * Time.fixedDeltaTime, ForceMode2D.Impulse);
transform.Translate(transform.up * m_acceleration * Time.fixedDeltaTime);
}