Search Unity

RaycastHit2D does not detect Children of GameObject

Discussion in 'Scripting' started by Sliske, May 25, 2015.

  1. Sliske

    Sliske

    Joined:
    Apr 9, 2015
    Posts:
    5
    Hello,

    I'm still new to Unity and I am trying to replicate Space Invaders.

    I am trying to use Raycast to make sure only the bottom row of aliens shoot lasers instead of all aliens being able to.

    I have put all the aliens as children of an empty game object so I can easily translate movements.

    This is the code I'm having troubles with:
    Code (CSharp):
    1.  
    2.     void MakeLaser ()
    3.     {
    4.         RaycastHit2D hit = Physics2D.Raycast (this.transform.position, -Vector2.up, Mathf.Infinity);
    5.         Debug.DrawRay (this.transform.position, -Vector2.up);
    6.         Debug.Log (hit.collider.name);
    7.         if (hit.collider.name == "alien" && hit.collider.CompareTag ("Laser")) {
    8.             isBottomRow = false;
    9.         } else {
    10.             isBottomRow = true;
    11.         }
    12.         float randNumber = Random.Range (0, 360);
    13.         if (isBottomRow = true && randNumber < 1 && gs.laserCount < 3 && GameObject.FindWithTag ("Player") != null) {
    14.             Instantiate (laserPrefab, this.transform.position, Quaternion.identity);
    15.         }
    16.     }
    17.  
    It does not set "isBottomRow = false" for aliens that are not in the bottom row and they can shoot lasers out.
    All aliens have box collider 2D (trigger) and rigidbody 2D attached.

    I also get this error:
    warning CS0414: The private field `InvaderController.isBottomRow' is assigned but its value is never used.

    I would greatly appreciate your help.
     
  2. tonemcbride

    tonemcbride

    Joined:
    Sep 7, 2010
    Posts:
    1,089
    It looks like your 'if' condition is assigning the variable 'isBottomRow' instead of testing against it.

    e.g.if (isBottomRow = true
    should be
    if (isBottomRow == true

    I'm probably a bit old fashioned but I think it makes it more readable/safer to put parenthesis around multiple conditions like this:

    Code (CSharp):
    1. if( ( isBottomRow == true ) &&
    2.      ( randNumber < 1 ) &&
    3.      ( gs.laserCount < 3 ) &&
    4.      ( GameObject.FindWithTag ("Player") != null ) )
    5. {
    6.    Instantiate (laserPrefab, this.transform.position, Quaternion.identity);
    7. }
    8.  
     
  3. Sliske

    Sliske

    Joined:
    Apr 9, 2015
    Posts:
    5
    Thanks for pointing this out, it stopped the warning error. However, the raycast still won't recognise the 2D box collider attached to the aliens. I have tried hit.rigidbody.name but it doesn't work either. Do the aliens being children of a GameObject affects the detection?
     
  4. tonemcbride

    tonemcbride

    Joined:
    Sep 7, 2010
    Posts:
    1,089
    I'd probably need to see the scene to see why but it could be that the ray is just hitting the alien that you're firing the ray from. If you're firing a ray you need to start it from a position that's outside the collider of the alien otherwise it'll just hit the same thing each time.
     
  5. Sliske

    Sliske

    Joined:
    Apr 9, 2015
    Posts:
    5
    If the ray is hitting the alien itself, the alien won't fire any lasers since "isBottomRow = false" and thus won't instantiate any laser i think?
     
  6. tonemcbride

    tonemcbride

    Joined:
    Sep 7, 2010
    Posts:
    1,089
    I'm a bit confused as to where you're firing the raycast from. If your layout of aliens is like this:

    A1 A2 A3 A4
    A5 A6 A7 A8
    A9 A10 A11 A12

    If you fire a raycast from A1 downwards it might just be hitting the collider for A1 since you're firing the ray from the centre of A1.
     
  7. Sliske

    Sliske

    Joined:
    Apr 9, 2015
    Posts:
    5
    Capture.JPG
    This is the Debug.DrawRay. If the raycast is hitting the alien's own collider then no laser should be instantiated since "isBottomRow = false". I'm assuming that the raycast is not detecting the alien box colliders as all aliens are able to fire lasers regardless of what position they're in.
     
  8. tonemcbride

    tonemcbride

    Joined:
    Sep 7, 2010
    Posts:
    1,089
    Ah, ok - what about this line:

    if (hit.collider.name == "alien" && hit.collider.CompareTag ("Laser"))

    That seems to indicate that if you fire a ray from the top left alien and it hits the one below then the 'hit.collider.name' would be 'alien'. Is that showing up in the debug.log for hit.collider.name?

    It also checks that the hit.collider has the 'laser' tag which doesn't make sense to me - why would the alien have a laser tag set on it? The 'isBottomRow' will never be set to false unless the ray hits an alien with a 'laser' tag - is that right?
     
  9. Sliske

    Sliske

    Joined:
    Apr 9, 2015
    Posts:
    5
    Oh cool, I made some changes to that line and it's working a bit better.
    Code (CSharp):
    1.            
    2. if (!hit.collider.transform.CompareTag ("Invader") && !hit.collider.transform.CompareTag ("Laser")) {
    3.                 isBottomRow = true;
    4.             }
    EDITED: Should be && instead of ||

    I also moved the raycast position a bit lower so it will be outside the collider.
    Code (CSharp):
    1.        
    2. RaycastHit2D hit = Physics2D.Raycast (new Vector2 (this.transform.position.x, this.transform.position.y - 0.2f), -Vector3.up, Mathf.Infinity);
    3.         Debug.DrawRay (new Vector2 (this.transform.position.x, this.transform.position.y - 0.2f), -Vector3.up);
    Capture.JPG

    The detection is still a bit weird as some of the upper aliens might still be able to fire lasers, but generally only the bottom row aliens are able to shoot lasers.

    Thanks for the tips, really appreciated it. Thank you! :D
     
  10. tonemcbride

    tonemcbride

    Joined:
    Sep 7, 2010
    Posts:
    1,089
    No probs, glad it's working better now