Search Unity

Cannot get 2d raycasting to work (got 3d working)

Discussion in 'Scripting' started by Joevonfo, Nov 14, 2017.

  1. Joevonfo

    Joevonfo

    Joined:
    Mar 31, 2015
    Posts:
    95
    Hi there

    I'm trying to make a top-down shooter, but realized that had made some messy combinations between 2d and 3d, so I decided to start over using only 2d.

    I watched a tutorial on top-down shooting and ended up with a script working as intended - using 3d raycasting.

    This is the script below:

    Code (CSharp):
    1. public class Weapons : MonoBehaviour
    2. {
    3.  
    4.     public enum WeaponType {Semi, Burst, Auto};
    5.     public WeaponType weaponType;
    6.     public float rpm;
    7.     public float damage;
    8.     public AudioSource shotSound;
    9.  
    10.     public Transform hitscan_Spawn;
    11.     private LineRenderer tracer;
    12.  
    13.     public ProjectileController projectile_Shot;
    14.     public Transform projectile_FirePoint;
    15.     public float projectile_Speed;
    16.  
    17.  
    18.  
    19.  
    20.  
    21.     private float secondsBetweenShots;
    22.     private float nextPossibleShootTime;
    23.  
    24.     public void Start()
    25.     {
    26.         secondsBetweenShots = 60 / rpm;
    27.         if (GetComponent<LineRenderer>())
    28.         {
    29.             tracer = GetComponent<LineRenderer>();
    30.         }
    31.     }
    32.  
    33.  
    34.     public void Shoot()
    35.     {
    36.         if (CanShoot())
    37.         {
    38.             {
    39.                 Ray ray = new Ray(hitscan_Spawn.position, hitscan_Spawn.forward);
    40.                 RaycastHit hit;
    41.                 float shotDistance = 20;
    42.  
    43.  
    44.                 if (Physics.Raycast(ray, out hit, shotDistance))
    45.                 {
    46.                     shotDistance = hit.distance;
    47.  
    48.                     if (hit.collider.GetComponent<Health>())
    49.                     {
    50.                         hit.collider.GetComponent<Health>().TakeDamage(damage);
    51.                     }
    52.                 }
    53.  
    54.                 if (tracer)
    55.                 {
    56.                     StartCoroutine("RenderTracer", ray.direction * shotDistance);
    57.                 }
    58.             }
    59.  
    60.             nextPossibleShootTime = Time.time + secondsBetweenShots;
    61.  
    62.             shotSound.Play();    
    63.         }
    64.     }
    65.  
    66.     public void ShootContinuous()
    67.     {
    68.         if (weaponType == WeaponType.Auto)
    69.         {
    70.             Shoot();
    71.         }
    72.     }
    73.  
    74.     public bool CanShoot()
    75.     {
    76.         bool canShoot = true;
    77.  
    78.         if (Time.time < nextPossibleShootTime)
    79.         {
    80.             canShoot = false;
    81.         }
    82.  
    83.         return canShoot;
    84.     }
    85.  
    86.     IEnumerator RenderTracer(Vector3 hitPoint)
    87.     {
    88.         tracer.enabled = true;
    89.         tracer.SetPosition(0, hitscan_Spawn.position);
    90.         tracer.SetPosition(1, hitscan_Spawn.position + hitPoint);
    91.         yield return null;
    92.         tracer.enabled = false;
    93.     }
    94.  
    95. }
    96.  

    That worked, but now that I am trying to "rebuilt" it with 2d raycasting I cannot for the life of me, figure out how to do so.
    I've been trying to work with the Physics2D.Raycast and looking up the API but I'm not sure I actually understand the concept of it well enough to figure it out on my own, and I cannot find any tutorials on top-down 2d shooting.

    Can anyone help or give some advice?

    Thank you
     
  2. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    The physics2d raycast returns either: raycasthit2d or an int , depending on which one you use.
    If you only want the information for the first hit you detect (if any), using the one that returns 1 RaycastHit2D is enough, I'd say.
    Just use the position of your player or weapon, the direction you want and a distance, for example.
    Then, check the RaycastHit2D variable to see what you hit (if anything).
    Quoted from the manual:
    Though the quote says RaycastHit, I'm sure it's RaycastHit2D heh.
     
  3. Joevonfo

    Joevonfo

    Joined:
    Mar 31, 2015
    Posts:
    95

    Thanks :)

    But how do I chose the direction I want?
    In 3d I can say Raycast.forward, but that is unavailable in 2d.
    Should I use Raycast2D.up instead for 2d, if I want a gun to shoot and the raycast do detect trajectory?
     
  4. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
    Generally transform.right is the forward vector in 2D.
     
  5. Joevonfo

    Joevonfo

    Joined:
    Mar 31, 2015
    Posts:
    95
    Trying to "Update" the old script to raycasting in 2D i get a "Use of unassigned variable "hit"" in the "shotDistance = hit.Distance"..
    But as far as I can see I'm doing the exact same thing in the 3d script, but there it's not "unassigned"

    Code (CSharp):
    1.  
    2.     public void Shoot()
    3.     {
    4.         if (CanShoot())
    5.         {
    6.             {
    7.                 Ray2D ray2D = new Ray2D(firePos.position, firePos.right);
    8.                 RaycastHit2D hit;
    9.                 float shotDistance = 20;
    10.  
    11.  
    12.                 if (Physics2D.Raycast(firePos.position, transform.right, shotDistance))
    13.                 {
    14.                     shotDistance = hit.distance;
    15.                     if (hit.collider.GetComponent<Health>())
    16.                     {
    17.                         hit.collider.GetComponent<Health>().TakeDamage(damage);
    18.                     }
    19.                 }
    20.  
    What am I misunderstanding here?
     
  6. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    It doesn't return a bool like the 3d version. So, you want to modify your code a little. You'll always get a hit, as I tried to mention before, so you want to check the collider of the hit (or some other property I suppose should work, too). :)
    Code (csharp):
    1. hit = Physics2D.Raycast(firePos.position, transform.right, shotDistance));
    2. if(hit.collider != NULL) {
    3.  // rest of your code..
    4.   }
    5.  
     
  7. Joevonfo

    Joevonfo

    Joined:
    Mar 31, 2015
    Posts:
    95
    I still can't get it to work.
    I'm going crazy over this :p

    You can see my current code below:


    Code (CSharp):
    1.     public void Shoot()
    2.     {
    3.         if (CanShoot())
    4.         {
    5.             {
    6.                 Ray2D ray2D = new Ray2D(firePos.position, firePos.up);
    7.                 RaycastHit2D hit;
    8.                 float shotDistance = 20;
    9.  
    10.                 hit = Physics2D.Raycast(firePos.position, firePos.up, shotDistance);
    11.                 if (hit.collider != null)
    12.                 {
    13.                     shotDistance = hit.distance;
    14.                     if (hit.collider.GetComponent<Health>())
    15.                     {
    16.                         hit.collider.GetComponent<Health>().TakeDamage(damage);
    17.                     }
    18.                 }
    19.  
    20.                 Debug.DrawRay(firePos.position, firePos.up, Color.red);
    21.  
    22.                 if (tracer)
    23.                 {
    24.                     StartCoroutine("RenderTracer", ray2D.direction * shotDistance);
    25.                 }
    26.             }
    27.  
    28.             nextPossibleShootTime = Time.time + secondsBetweenShots;
    29.  
    30.             shotSound.Play();
    31.         }
    32.     }
    33.  
    34.     public void ShootContinuous()
    35.     {
    36.         if (weaponType == WeaponType.Auto)
    37.         {
    38.             Shoot();
    39.         }
    40.     }
    41.  
    42.     public bool CanShoot()
    43.     {
    44.         bool canShoot = true;
    45.  
    46.         if (Time.time < nextPossibleShootTime)
    47.         {
    48.             canShoot = false;
    49.         }
    50.  
    51.         return canShoot;
    52.     }
    53.  
    54.     IEnumerator RenderTracer(Vector2 hitPoint)
    55.     {
    56.         tracer.enabled = true;
    57.         tracer.SetPosition(0, firePos.position);
    58.         tracer.SetPosition(1, new Vector3(firePos.position.x + hitPoint.x, firePos.position.y + hitPoint.y));
    59.         yield return null;
    60.         tracer.enabled = false;
    61.     }
    My Debug.DrawRay seem to work normally, but I can't get that damn linerenderer to work.
    It seems to me that it's the "SetPosition(1.... .....) that's wrong, although I get no Errors, but I cannot figure out what to do.