# Unity Missile Tracking

This topic is 3287 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I've been adding guided missiles to the game I'm working on, but have run into something of a snag. I'm basing the method on this thread: http://www.gamedev.net/community/forums/topic.asp?topic_id=419681 The code I'm using follows:
// This is the fun part -- track target
SF3dVector heretotarget = target->GetPos() - Position;
heretotarget = Normalize3dVector(heretotarget);

SF3dVector facingDifference = heretotarget - ViewDir;
float yawdirection = DotProduct(facingDifference, RightVector);
float pitchdirection = DotProduct(facingDifference, UpVector);

RotateX((yawdirection * 90)/fps);
RotateY((pitchdirection * 90)/fps);


The function DotProduct is defined as follows
float DotProduct(SF3dVector u, SF3dVector v)
{
return (u.x * v.x) + (u.y * v.y) + (u.z * v.z);
}


Normalize3dVector is defined as follows
SF3dVector Normalize3dVector( SF3dVector v)
{
SF3dVector res;
float l = GetF3dVectorLength(&v);
if (l == 0.0f) return NULL_VECTOR;
res.x = v.x / l;
res.y = v.y / l;
res.z = v.z / l;
return res;
}


When I spawn a missile object sending it off towards its target, it seems to spiral in an attempt at course correction, but ends up spiraling off into the distance at some funny angle instead. Does anyone see a problem in my code anywhere?

##### Share on other sites
At first glance, it appears as though you've mistakenly swapped rotating on the X axis for Yaw (should be Pitch) and Y for Pitch (should be Yaw).

Also, make sure you normalize your vectors before performing a dot product (to get a proper cosine of the angle between them).

##### Share on other sites
Ok, fixed the swapped x and y as well as normalized the Up and Right vectors. This seems to have helped somewhat, but not completely...

I can't quite tell whats going on... it seems that after I change targets (the first being destroyed), the missiles start acting wonky again. Perhaps they are trying to track the old destroyed enemy... but I don't see why that should be happening... relevant code below:

Constructor
Rotatable *target;    Guided_Missile_Launcher(float vel, float rt, float dmg, Rotatable *par, float dispx, float dispy, float dispz, float rx, float ry, int *a, Rotatable *targ)    {        speed = vel;        damage = dmg;        dx = dispx;        dy = dispy;        dz = dispz;        pitch = rx;        yaw = ry;        reloadtime = rt;        timelastfired = 0;        parent = par;        Position = parent->GetPos();        UpVector = parent->GetUp();        RightVector = parent->GetRight();        ViewDir = parent->GetView();        MoveForward(-dz);        StrafeRight(dx);        MoveUpward(dy);        RotateX(pitch);        RotateY(yaw);        ammo = a;        target = targ;    }

spawning the missile object
allprojectiles.push_back(new Guided_Missile(speed, damage, this, target));

Creating the weapon instance
Weapons.push_back(new Guided_Missile_Launcher(-0.95, 0.5, 10, this, 0.05, 0.05, 0.1, -1.0, 1.0, &pammo, playertarget));

where playertarget is a pointer to a rotatable object (Rotatable *playertarget)

##### Share on other sites
Did you normalize facingDifference?

##### Share on other sites
oops, just did. all that did was tighten up the turning for the case where it works... but it still misbehaves as before. Watching it carefully, on new targets it turns towards it but then continues turning in a wide arc and misses

##### Share on other sites
Just remembered to normalize ViewDir as well but that has no effect. I'm pretty certain that the weapon refuses to change targets for some reason.

##### Share on other sites
I'm pretty sure I'm passing a reference incorrectly somewhere... always have so much trouble tracking those errors down.

##### Share on other sites
It's spiraling because when it's near the target it can't turn fast enough to move towards it. You can fix it with a combination of any of the following:

1) Make the missile turn faster.
2) Make it start far away from the target, giving it time to lock on (by the time it reaches the target it should be going straight at it).
3) (And this one's really important) Make sure the collision area is not too tiny, because unless you're implementing a proper missile control system (like the ones used in real life [grin] give me a beep if you wanna implement one of those) it will never hit the target with 100% accuracy.

4) Another work-around (harder to implement) is to have a finer simulation step (ie, more FPS for the physics).

##### Share on other sites
Just tried messing with turn speed... it is definitely not the turn speed at this point (though increasing the turn speed gives the missile a much cooler looking path). I am 100% sure that the missile launcher's target is not updating properly for some reason.

##### Share on other sites
Sounds like you'll need to step thru with a debugger. The actual tracking code looks pretty good to me, without having run it myself.

##### Share on other sites
Ran through the code with a friend last night. The problem stems from the way I try to pass the target pointer to the Guided_Missile_Launcher object. The way I want it written is so that I don't have to manually update it when the target changes. I had thought that passing the pointer (roughly: Rotatable *playertarget = *iterator) like as a pointer argument (..., Rotatable *targ) should work, but it does not update when the original pointer does. What I'm looking for is the proper way to pass the pointer.

##### Share on other sites
So you're caching the pointer to the target? If you do that, and the original pointer changes, you need to update the cached copy. You need some kind of UpdateTarget(Rotatable* target) call that resets the cached copy.

I'm not sure why you want to cache the target in the launcher itself. The missiles should have a pointer to it's target, but the launcher only needs to know about the target when it fires a missile, so it can pass it to the missile. Caching it is just asking for trouble later, if the target is deallocated/invalidated.

##### Share on other sites
the launcher's pointer to the target should be equal to the playertarget pointer (that is to say they should ultimately point to the same place. that way, when I change targets elswhere, the change should propagate on its own). That way it wouldn't require updates (which I don't give it). So I'm definitely passing the pointer incorrectly. I just haven't a clue how to properly write it to do what I want (ugh, I can get everything else working [grin]). I can post the relevant code in its entirely this evening if you think it will help.

##### Share on other sites
I think if you post the relevant code, we can help you with that.

This is just a guess, but I think you're doing the pointer thing wrong:

MissileLauncher:
-keeps a pointer to the target: eg Rotatable *m_pTarget

Rocket:
-keeps a pointer to the target: eg Rotatable *m_pTarget

If I understood you correctly, you do 'change the target elsewhere', say:
MissileLauncher::setTarget( Rotatable *pTarget ) { m_pTarget = pTarget; }

Now this is what I think you're doing wrong (if it's not the case, spare my life please):
Changing the literal value of the pointer (eg. making it point to another address) anywhere else won't change the the literal value of the pointer of your rocket. The rocket's target will still point towards the first target, but it can react on changes of the first target's position for example (because the object m_pTarget points to changes its position). You will need to update the target for the rocket as well, in order to react on changing targets.

##### Share on other sites
I wouldn't recommend that approach, as you are increasing coupling between two objects. This will only give you nightmares in the future. Not to mention, you have no way of knowing when the data the pointer is pointing to gets destroyed. There are certainly other ways of having the propagation happen "automatically", using a more secure design. However, theoretically, you could pass a pointer to a pointer, and cache that instead.

Rotatable **mTarget = ⌖

Then, to get the active target, you just dereference it like so:
Rotatabe *curTarget = *mTarget;

Still, I seriously don't recommend this approach. You should re-design your objects to communicate through interfaces, instead of fondling each other's data in inappropriate ways ;)

##### Share on other sites
I will post the code this evening (when I am on my dev machine). For now, I will try to clarify what I am doing.

I have a pointer *playertarget which points (at any given time) to the player's attack target. The player can change targets at will by pressing 't' or if the current dies. In either of these cases the object *playertarget points two changes.

The Guided_Missile_Launcher object's *target pointer needs to point to the same object as *playertarget. Once it does, as *playertarget changes (totally outside the scope of the weapons subsystem) so should *target. When a new missile object is spawned, it should point at the current target (so, it should point to what *target and *playertarget point to). If the current target dies before the missile hits it, no matter, the missiles are not designed to redirect to new targets once fired. the big thing is that all new missiles should fire towards whatever *playertarget is pointing towards at any given time.

Here's a bit of scope information

MAIN GAME (GLOBAL)
-- SHIPS SUBSYSTEM contains *playertarget
-- WEAPONS SUBSYSTEM contains Guided_Missile_Launcher and Guided_Missile, etc
-- launcher gets passed *playertarget in construction, should point *target through it.
-- Etc etc etc.

The game's core can see the public parts of these subsystems and issue commands that way, but the subsystems have no means of communication with eachother. So, ideally, updates to *playertarget should be totally transparently propagate through *target as if *target actually was *playertarget. The individual missiles don't need to care :-p

##### Share on other sites
I hope this is no missunderstanding, but I still think you're doing the wrong thing.

float *foo = NULL;float *bar = NULL;float pi = 3.14159f;foo = &#960; // foo points to the address of pibar = foo; // bar points to the address of pi (the literal value of foo is assigned to bar)float e = 2.71f;foo = &e; // foo points to the address of ebar; // bar <b>still</b> points to the address of pi

It does matter. You jave to clarify whether you change the object, your pointer points to (eg assign the pointer another address) or just change some value inside the target class.

##### Share on other sites
that is the problem I'm having. I'm not sure how to achieve what I want (as defined in my last post). I could probably shoehorn manual updates (mostly by exposing playertarget to global scope, but it would be greatly preferable not to.

##### Share on other sites
Somewhere in your code, when you change your target (if the old one was destroyed), you could simply loop through all your rockets and replace their old target address with the new one.

##### Share on other sites
I have no need to update the rocket's targets -- they don't have the "fuel" for it. But as things stand, I have to make the launchers themselves poll to check for updated targets, and I'd prefer not to. And I can't directly pass them *playertarget because of scope (which can easily be changed) and more importantly because the weapons system is supposed to be modular. It is designed so that I can install a weapon of any type on any suitable object (any ship or whatnot. The player's host object is derived from ship). If I bound the code to directly read from *playertarget, things would get very weird when I would try to use the missile launchers on enemy ships (they would target the player's enemies... aka themselves. while that would be funny, it would not be correct).

I hope I'm making myself sufficiently clear. Apologies if I am not.

##### Share on other sites
I agree with ThrustGoblin, the "correct" way would be to use a double-pointer. The actual data that matters to missiles and the player is the -pointer- to the target; the pointer is subject to change and everyone needs to know about that change. So they need to "point to" the "pointer" to the target.

Conceptually it's a bit hard to swallow. So I'd design a small helper class, like this:

class Target {Ship *who;};class Ship{...};class Missile{Target *target;};Target player_target; //the word "target" is starting to sound funny at this point......//missiles 1 and 2 will be directed by the player's targetmissile1.target = &player_target;missile2.target = &player_target;//direct them at ship 34player_target.who = &ship34;//now direct them at ship 123player_target.who = &ship123;//the missile can get the ship's position like so:float goto_x = target->who->x;float goto_y = target->who->y;

It's like a double pointer but the double-ness is hidden away from view.

##### Share on other sites
Here's the relevant code... hopefully this will clear up the structure of things...

This is how playertarget is defined
Rotatable *playertarget;list<Ship *>::iterator playertargetiter; // locked to player's target iterator

Here is the entire definition of Guided_Missile_Launcher -- the thing that shoots
class Guided_Missile_Launcher : public Weapon{    public:    Rotatable *target;    Guided_Missile_Launcher(float vel, float rt, float dmg, Rotatable *par, float dispx, float dispy, float dispz, float rx, float ry, int *a, Rotatable **targ)    {        speed = vel;        damage = dmg;        dx = dispx;        dy = dispy;        dz = dispz;        pitch = rx;        yaw = ry;        reloadtime = rt;        timelastfired = 0;        parent = par;        Position = parent->GetPos();        UpVector = parent->GetUp();        RightVector = parent->GetRight();        ViewDir = parent->GetView();        MoveForward(-dz);        StrafeRight(dx);        MoveUpward(dy);        RotateX(pitch);        RotateY(yaw);        ammo = a;        target = *(targ);    }    void Fire()    {        Update();        if(timeGetTime()-timelastfired >= (reloadtime*1000) && (*ammo > 0 || *ammo == -1))        {            allprojectiles.push_back(new Guided_Missile(speed, damage, this, target));            timelastfired = timeGetTime();            if(*ammo > 0)            {                *ammo-=1;            }        }    }    void Update() // Updates position    {        Position = parent->GetPos();        UpVector = parent->GetUp();        RightVector = parent->GetRight();        ViewDir = parent->GetView();        MoveForward(-dz);        StrafeRight(dx);        MoveUpward(dy);        RotateX(pitch);        RotateY(yaw);        /*glPushMatrix();        glTranslated(Position.x, Position.y, Position.z);        rotateTo();        glColor4d(1.0, 0.0, 0.0, 1.0);        glBegin(GL_QUADS);           glVertex3d(0, 0, 0);           glVertex3d(0, 0, 0.5);           glVertex3d(0, 0.1, 0.5);           glVertex3d(0, 0.1, 0);        glEnd();        glPopMatrix();*/    }    /*void ChangeAmmo(int amt)    {        ammo += amt;        if(ammo > ammomax)            ammo = ammomax;        if(ammo < 0)            ammo = 0;    }*/};

Here is the entire definition of Guided_Missile -- the actual thing that gets fired
class Guided_Missile : public Projectile{    public:    Rotatable *target;    Guided_Missile(float vel, float dmg, Rotatable *parent, Rotatable *targ)    {        velocity = vel;        damage = dmg;        Position = parent->GetPos();        ViewDir = parent->GetView();        UpVector = parent->GetUp();        RightVector = parent->GetRight();        RotatedX = parent->GetXrot();        RotatedY = parent->GetYrot();        RotatedZ = parent->GetZrot();        target = targ;        impact = false;        armed = false;        explodetime = 0.0;        travelled = 0.0;        modelnum = 1;        texnum = 1;    }    void Update()    {        MoveForward(velocity/fps); // Take car of actual forward motion        if((velocity/fps) > 0)            travelled += (velocity/fps);        if((velocity/fps) < 0)            travelled -= (velocity/fps);        // This is the fun part -- track target        SF3dVector heretotarget = target->GetPos() - Position;        heretotarget = Normalize3dVector(heretotarget);        SF3dVector normalView = Normalize3dVector(ViewDir);        SF3dVector facingDifference = heretotarget - normalView;        facingDifference = Normalize3dVector(facingDifference);        SF3dVector normalRight = Normalize3dVector(RightVector);        SF3dVector normalUp = Normalize3dVector(UpVector);        float yawdirection = -1 * DotProduct(facingDifference, normalRight);        float pitchdirection = DotProduct(facingDifference, normalUp);        RotateY(yawdirection * (60.0/fps));        RotateX(pitchdirection * (60.0/fps));        if(travelled > 0.5)        {            armed = true;        }    }    void Render()    {        glPushMatrix();        //glTranslatef(displacement_x,displacement_y,displacement_z);        glTranslated(Position.x, Position.y, Position.z);        rotateTo();        glRotated(90, 0, 1.0, 0.0); // TEMPORARY LINE        if(travelled < 0.5)            DrawObj(models[1], 1, 0.0, 0.0, 0.0);        if(travelled >= 0.5)        {            DrawObj(models[1], 10, 0.0, 0.0, 0.0);        }        glRotated(-90, 0, 1.0, 0.0); // TEMPORARY LINE        glPopMatrix();    }};

Here is how I change targets with the 't' key
if(GetAsyncKeyState('T')&0x8000)            {                if(timeGetTime() - lasttimetarget >= 100)                {                    lasttimetarget = timeGetTime(); // Update the last time player targeted a ship                    if(playertargetiter != Allships.end())                    {                        playertarget->targeted = false;                        playertargetiter++;                        playertarget = *playertargetiter;                        playertarget->targeted = true;                    }                    else                    {                        playertarget->targeted = false;                        playertargetiter = Allships.begin();                        playertarget = *playertargetiter;                        playertarget->targeted = true;                    }                }            }

And here is how I instantiate a Guided_Missile_Launcher object in a linked list of all weapons on the ship (Weapons) the player's ship itself being known as pShip.

Weapons.push_back(new Guided_Missile_Launcher(-0.95, 0.5, 10, this, 0.05, 0.05, 0.1, -1.0, 1.0, &pammo, &playertarget));

The weapons stuff is in a file called weapons.h, the definition of *playertarget is in ships.h, the target changing is in my core source file, and the instantiation is in a file called player.h. Sorry for the mess.

##### Share on other sites
Unfortunately, the iterator being an iterator through a linked list of pointers doesn't simplify things much, sorry if it gets a little confusing.

##### Share on other sites
Quote:
 Original post by medevilenemyI have no need to update the rocket's targets -- they don't have the "fuel" for it.

Well, your rockets need to be aware of the entities around them. Otherwise they cannot change targets.
Your code block shows me that you want to change the target by hitting t. If you're afraid that you will change all your rocket's targets, if you loop through them, then you really need to consider another (better) approach to do all this stuff (or simply filter enemy & player targets).

-Rocket: Contains some sort of awareness, checks if the current target is destroyed, looks for the next enemy and try to reach that one.
That approach would require some sort of state management, so that entities can be aware of entities around them.

Consider some class that contains all entities in a scenegraph or some other graph. If a rocket noticies it's target is dead, it will start a query and get another target from that class, if there is one.

##### Share on other sites
Such a structure would be a good idea as far as efficiency is concerned, but as for the designed function of the rockets now necessary. The rockets do not need to know if their target has died (at least, not directly). The program already senses when the current dies and resets targets on its own. So, the missile launcher needs to know of this change passively and maybe the missiles can then learn of the change a similar way -- but that is not absolutely necessary. The important part is that the launcher be passively aware of any change in target. The current inability to be so is a result of my own failure in passing the pointers properly. What I seek is direction as to how to properly pass the reference from *playertarget (as defined in the code I posted) through a constructor argument, to a local variable in the launcher (*target), and then maybe to the individual missile objects through a constructor argument such that at all stages the pointers all point at the same place (the target of *playertarget) and a change in one changes all of them (since they are all supposed to point to the same place).

Thanks for the suggestions, thus far, at least. I'm definitely planning on going through the code in the not-too-distant future to speed things up, but I'll get to that after more pressing concerns of functionality.

• 11
• 26
• 10
• 11
• 12
• ### Similar Content

• So I am building a turn based rogue-like (think CDDA). The game is going to have a very large map (up to 1000's x 1000's) however to alleviate most of that I obviously can't render everything so there will just be render a certain radius around the player and just load in and out data as the player moves.
The next major system I am prototyping is making interactive tiles destructible and pretty much everything will be destructible besides basic landscape (cars, doors, windows, structures, etc. will be destructible)
While I am only rendering a certain amount of tiles around the player, I want to keep the amount of colliders active at one time to be as small as possible for performance and currently the tilemap tool I use automatically merges colliders together.
So instead of creating a separate colliders for each of these tiles and having the destructible behavior tied to that object (which my tilemap tool would allow me to do) I was thinking that I would store an array of all the X and Y locations for the interactive tilemap layer and let the tilemap manage the colliders.
Then when I hit a collider on the interactive tilemap layer, instead of of getting the behavior for how to deal with the destruction for that tile from that game object, I would pull it from the array I mentioned earlier based on the tile I attempt to interact with which I already have.
Does this sound like a good approach? Any other recommendations would be welcomed.

• Hey guys,
I have a really weird problem. I'm trying to get some data from a REST service. I'm using the following code:

private void GetTheScores() { UnityWebRequest GetCommand = UnityWebRequest.Get(url); UnityWebRequestAsyncOperation operation = GetCommand.SendWebRequest(); if (!operation.webRequest.isNetworkError) { ResultsContainer rez = JsonUtility.FromJson<ResultsContainer>(operation.webRequest.downloadHandler.text); Debug.Log("Text: " + operation.webRequest.downloadHandler.text); } } The problem is that when I'm in Unity's editor, the request doesn't return anything (operation.webRequest.downloadHandler.text is empty, the Debug.Log command just prints "Text: "), but when I enter the debug mode and insert a breakpoint on that line, then it returns the text properly. Does anyone have an idea why is this happening?
The real problem I'm trying to solve is that when I receive the text, I can't get the data from the JSON. The markup is really simple:
[{"id":1,"name":"Player1"},{"id":2,"name":"Player2"}] and I have an object that should accept that data:
[System.Serializable] public class ResultScript { public int id; public string name; } There is also a class that should accept the array of these objects (which the JSON is returning):
[System.Serializable] public class ResultsContainer { public ResultScript[] results; } But when I run the code (in the debug mode, to get any result) I get an error: ArgumentException: JSON must represent an object type. I've googled it but none of the proposed solutions work for me.
Also (regardless if I'm in the debug mode or not) when I try to do some string operations like removing or adding characters to the GET result, the functions return an empty string as a result
Can you help me with any of these problems?
Thank you
• By nihitori
The Emotional Music Vol. I pack focuses on beautiful and esoteric orchestral music, capable of creating truly emotive and intimate moods. It features detailed chamber strings, cello and piano as the main instruments, resulting in a subtle and elegant sound never before heard in video game royalty-free music assets.

The pack includes 5 original tracks, as well as a total of 47 loops based on these tracks (long loops for simple use and short loops for custom / complex music layering).