Search Unity

  1. We've closed the job boards. If you're looking for work, or looking to hire check out Unity Connect. You can see more information here.
    Dismiss Notice
  2. We're running great holiday deals on subscriptions, swag and Asset Store packages! Take a peek at this blog for more information!
    Dismiss Notice
  3. Check out our Unite Austin 2017 YouTube playlist to catch up on what you missed. More videos coming soon.
    Dismiss Notice
  4. Unity 2017.2 is now released.
    Dismiss Notice
  5. The Unity Gear Store is here to help you look great at your next meetup, user group or conference. With all new Unity apparel, stickers and more!
    Dismiss Notice
  6. Introducing the Unity Essentials Packs! Find out more.
    Dismiss Notice
  7. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice
  8. Unity 2017.3 beta is now available for download.
    Dismiss Notice

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:
    86
    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:
    3,523
    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:
    86

    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:
    1,107
    Generally transform.right is the forward vector in 2D.
     
  5. Joevonfo

    Joevonfo

    Joined:
    Mar 31, 2015
    Posts:
    86
    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:
    3,523
    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:
    86
    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.