Search Unity

control individual transforms in array from tag finds

Discussion in 'Scripting' started by San_Holo, Mar 18, 2015.

  1. San_Holo

    San_Holo

    Joined:
    Sep 26, 2014
    Posts:
    152
    Hi...

    In my shooter game my missiles have a lock-on target icon, it finds the enemy then re-tags them then I instantiate the icon on top of their position and that is fine, but I have some moving objects and so I need to keep the target-icon with the moving transform of my target and I can do that, but for some reason say if I find five enemy targets my icons then instantiate then group upon the last one found in the array... so I have five icons all on top of one another, now my code works fine but I'm a little lost on how to correct this, perhaps if I show you, you may help me a bit, thanks

    So my seeking missile does this:

    Code (csharp):
    1. foreach (GameObject obj in GameObject.FindGameObjectsWithTag("Enemies")) {
    2.                         if (Vector3.Distance (transform.forward, transform.position - obj.transform.position) < missileSeekRange) {
    3.                                 nearestEnemy = obj;
    4.                                 if (TargetIcon != null && obj.transform.position.y > player.transform.position.y) {
    5.                                         nearestEnemy.tag = "EnemyTagged";
    6.                                         Instantiate (TargetIcon, obj.transform.position, TargetIcon.transform.rotation);
    7.                                        
    8.                                 }
    9.                         }
    10.                 }
    Then my instantiated 'TargetIcon' does this simple code:

    Code (csharp):
    1. public class SeekIcon : MonoBehaviour
    2. {
    3.         private GameObject[] enemy;
    4.  
    5.         void FindTarget ()
    6.         {
    7.                 enemy = GameObject.FindGameObjectsWithTag ("EnemyTagged");
    8.                 if (enemy != null)
    9.                         for (int i = 0; i < enemy.Length; i++) {
    10.                                 transform.position = enemy [i].transform.position;
    11.                         }
    12.                 else {
    13.                         Destroy (gameObject);
    14.                 }
    15.         }
    16.  
    17.         void FixedUpdate ()
    18.         {
    19.                 FindTarget ();
    20.         }
    21. }
    .. and that's it.

    The 'TargetIcon' once instantiated and working via Update() just bundles anything it finds on top of one another... not sure if I'm doing things right, but I could use some help, cheers
     
  2. Brominion

    Brominion

    Joined:
    Sep 30, 2012
    Posts:
    48
    Hi!
    Vector3.Distance use looks strange to me. normally it is Vector3.Distance(point A as vector3, point B as vector3) returns distance as float from point a to b.
    But you have parameters which seem to indicate you are trying to measure along a certain axis, maybe.

    It doesn't explain why your icons end up on the same target, but it should mean that your targets are not correctly selected.

    You could try to just parent the instantiated Icon transform to the enemy transform directly, perhaps reference and track the missile (for distances etc) in a script on each icon instead. This way the icon should follow the enemy around well enough to show which enemy was actually targeted. And you may get a better idea what is going wrong.
     
  3. Brominion

    Brominion

    Joined:
    Sep 30, 2012
    Posts:
    48
    in addition your For loop on line 9-10 seems to assign all the enemy positions one after the other to the same transform, rather the than assign the each enemy position to a different icon transform.
     
  4. San_Holo

    San_Holo

    Joined:
    Sep 26, 2014
    Posts:
    152
    Code (csharp):
    1. List<Transform> taggedAliens;
    Added to start off with, then

    Code (csharp):
    1. taggedAliens = new List<Transform> ();
    in Start() of my missile script

    Code (csharp):
    1. foreach (GameObject obj in GameObject.FindGameObjectsWithTag("Enemies")) {
    2.                         if (Vector3.Distance (transform.forward, transform.position - obj.transform.position) < missileSeekRange) {
    3.                                 nearestEnemy = obj;
    4.                                 if (TargetIcon != null && obj.transform.position.y > player.transform.position.y) {
    5.                                         nearestEnemy.tag = "EnemyTagged";
    6.                                         taggedAliens.Add (Instantiate (TargetIcon, obj.transform.position, TargetIcon.transform.rotation) as Transform);
    7.                                 }
    8.                         }
    9.                 }
    and in FixedUpdate() I have:

    Code (csharp):
    1. if (nearestEnemy != null) {
    2.                                 transform.rotation = Quaternion.LookRotation (nearestEnemy.transform.position - transform.position, Vector3.back);
    3.                                 for (int i = 0; i < taggedAliens.Count; i++) {
    4.                                         taggedAliens.ForEach (taggedAlien => Debug.Log (taggedAliens [i].localPosition));
    5.                                 }
    6.                         }
    shows the target-icons, but in update I have an error
    Code (csharp):
    1. NullReferenceException: Object reference not set to an instance of an object
    Need to sleep on it perhaps, cheers
     
  5. San_Holo

    San_Holo

    Joined:
    Sep 26, 2014
    Posts:
    152
    well I've just arisen and in my cognitive dreams I thought surely just parenting to the alien-object should work right off the bat without the need to update it's transform via Update()... perhaps, I'll try it a bit later
     
  6. San_Holo

    San_Holo

    Joined:
    Sep 26, 2014
    Posts:
    152
    I can't read the array...

    Code (csharp):
    1. taggedAliens.Add (Instantiate (TargetIcon, obj.transform.position, TargetIcon.transform.rotation) as Transform);
    2.                                         print ("tagged :" + taggedAliens [0].name);
    returns 'Object reference not set to an instance of an object'

    I can count the amount in the array 'taggedAliens' but can't really act upon it, for example...

    Code (csharp):
    1. for (int i = 0; i < taggedAliens.Count; i++) {
    2.                                     TargetIcon.transform.ForEach (taggedAlien => taggedAliens[i].transform.parent = TargetIcon.transform);
    3. }
    I'm missing something obvious, don't know what it is... more experimentation
     
  7. San_Holo

    San_Holo

    Joined:
    Sep 26, 2014
    Posts:
    152
    I may just add the target-icon to each spawning alien but disabled at start then the missile simple enables the hidden target-sprite and will naturally follow it about till destroyed, I'll try that.

    nope, the target icon will take on the objects rotation and i don't want that
     
    Last edited: Mar 19, 2015
  8. Brominion

    Brominion

    Joined:
    Sep 30, 2012
    Posts:
    48
    Well yes, your icons will follow the position and rotation of the parent object unless you adjust them to face the camera (I for get if there are camera facing billboard templates to use for this already) . A Similar situation will also happen if your camera moves but your icon does not adjust its rotation.

    for the parenting or position assignment, I think you want something like this;
    Code (CSharp):
    1.  
    2. for(int i = 0; i < number_of_enemies; i++)
    3. {
    4.     Icon[i].tansform.parent = Enemy[i].transform;
    5. }
    you could also assign the transform.position directly instead of the parent,i suppose, no doubt you will find it is not enough and your will want to do more with the icon position before you are done though ;)
     
    San_Holo likes this.
  9. San_Holo

    San_Holo

    Joined:
    Sep 26, 2014
    Posts:
    152
    Thanks for your help and insights, I'll try the suggestion above in a moment, I'll cogitate on it for a bit while I watch another episode of the world at war... I'll post back with my results, cheers
     
  10. San_Holo

    San_Holo

    Joined:
    Sep 26, 2014
    Posts:
    152
    I was using transform.parent but couldn't stop the rotation of the seek-icon even with a rigidbody attached with freeze-rotation, so I tried this and it does the job, thanks for your for your help and advice.
     
    Last edited: Mar 23, 2015
  11. Brominion

    Brominion

    Joined:
    Sep 30, 2012
    Posts:
    48
    I either fail to explain, or I fail to understand. =)
    Line 13 will result in a lot of excessive assignments that are immediately over-written by the next iteration of the loop. All to the same object due to assignement to transform.localposition.
    • If you do this from the missile class, you need to put your icons in an array as well so that you assign the different enemy positions to different icons.
    • If you do this from the icon class (as it looks like) you need to change the enemy tag when icon has been assigned, so that the next icon to execute does not find an enemy that already has a tag. You can just pick the first gameobject in the list of enemies and do the assignment once, skipping the for loop. The Icon can then store areference (instead of an array) to to the enemy the icon should follow so you do not have to findGameObjectsWithTag every frame
     
  12. San_Holo

    San_Holo

    Joined:
    Sep 26, 2014
    Posts:
    152
    After a bit of thought, I thought to myself I was over egging the pudding, I've got one missile, I just need to find one target preferably the closest and pin a little badge on the bugger... so I did:

    Code (csharp):
    1.                 // seeking missile section
    2.                 Enemies = GameObject.FindGameObjectsWithTag ("Enemies");
    3.                 float missileSeekRange = Mathf.Infinity;
    4.                 foreach (GameObject alien in Enemies) {
    5.                         Vector3 difference = alien.transform.position - transform.position;
    6.                         float Distance = difference.sqrMagnitude;
    7.                         if (Distance < missileSeekRange) {
    8.                                 nearestEnemy = alien.gameObject;
    9.                                 missileSeekRange = Distance;
    10.                         }
    11.                 }
    12.                 if (nearestEnemy)
    13.                         Instantiate (TargetIcon, nearestEnemy.transform.position, TargetIcon.transform.rotation);
    14.         }
    So then my little badge of impending doom would have no where to go after that so a quick search again for the closest nasty and bingo... hold on to that sucker a missiles comin...

    Code (csharp):
    1. public class SeekIcon : MonoBehaviour
    2. {
    3.         private GameObject[] Enemies;
    4.         private GameObject nearestEnemy;
    5.  
    6.         void FindTarget ()
    7.         {
    8.                 Enemies = GameObject.FindGameObjectsWithTag ("Enemies");
    9.                 float missileSeekRange = Mathf.Infinity;
    10.                 foreach (GameObject alien in Enemies) {
    11.                         Vector3 difference = alien.transform.position - transform.position;
    12.                         float Distance = difference.sqrMagnitude;
    13.                         if (Distance < missileSeekRange) {
    14.                                 nearestEnemy = alien.gameObject;
    15.                                 missileSeekRange = Distance;
    16.                         }
    17.                 }
    18.         }
    19.  
    20.         void FixedUpdate ()
    21.         {
    22.                 FindTarget ();
    23.                 if (nearestEnemy) {
    24.                         transform.position = nearestEnemy.transform.position;
    25.                 } else {
    26.                         Destroy (gameObject);
    27.                 }
    28.         }
    29. }
    Sorted, I double up my missile weapons and it's fine, with a bit of squiggling the timings here & there, the icons self destruct after a short delay and bobs your uncle.
     
    Last edited: Mar 20, 2015