Search Unity

Defining Layers in Raycast

Discussion in 'Scripting' started by x10z, Dec 6, 2009.

  1. x10z

    x10z

    Joined:
    Aug 18, 2009
    Posts:
    54
    Ok guys I'm about to get crazy about this right here...

    After 4months of unity I still dont understand how do I script:

    Physics.Raycast(initialPosition,RayVector,Distance,AND ONLY DETECT THIS LAYER);

    How do I do that ?! I see this bit shifting operations with 1<<20 and stuff , but does 1<<20 mean "only 20" or "nothing below 20" ?

    How can I , by script define a Raycast that detects only 2 layers ... for example 20 and 25 ?

    Thanks in advance for the help guys!
     
    AdmiralThrawn likes this.
  2. SixTimesNothing

    SixTimesNothing

    Joined:
    Dec 26, 2007
    Posts:
    167
    Yeah it took me a while to figure this out too. The docs don't really explain the bitshifting stuff in any real amount of detail. You should look up bitwise operators to get a better understanding of how they work.

    Remember that the << operator is a bitwise left shift operation, it has nothing to do with anything being less than anything. i.e. Don't confuse it with the numerical < (less than) operator.

    This casts a ray that ignores all layers except for layer 2:

    Code (csharp):
    1. var hit : RaycastHit;
    2. var layerMask : int = 1 << 2;
    3. if (Physics.Raycast(transform.position, transform.TransformDirection (Vector3.forward), hit, 100, layerMask)) {
    4.     // some code if the ray hits
    5. }
    This casts a ray that ignores only layer 2:

    Note that the ~ operator is used to invert the bitmask.

    Code (csharp):
    1. var hit : RaycastHit;
    2. var layerMask : int = 1 << 2;
    3. layerMask = ~layerMask;
    4. if (Physics.Raycast(transform.position, transform.TransformDirection (Vector3.forward), hit, 100, layerMask)) {
    5.     // some code if the ray hits
    6. }
    This casts a ray that ignores both layers 2 and 8:

    Note that the | operator (bitwise OR) is used to check if the ray hits an object in layer 2 OR layer 8.

    Code (csharp):
    1. var hit : RaycastHit;
    2. var layerMask : int = (1 << 2) | (1 << 8);
    3. layerMask = ~layerMask;
    4. if (Physics.Raycast(transform.position, transform.TransformDirection (Vector3.forward), hit, 100, layerMask)) {
    5.     // some code if the ray hits
    6. }
    Hope that helps! :)
     
  3. jcurrie33

    jcurrie33

    Joined:
    Dec 9, 2009
    Posts:
    49
    Just wanted to say a quick thanks for this. I didn't realize Layer masks could be combined with bit operations. I used that to make a Line Of Sight function variated from the FPS tutorial:

    Code (csharp):
    1.  
    2. function CanSeeTarget () : boolean {
    3.     if (Vector3.Distance(transform.position, target.position) > attackRange) {
    4.         currentState = "Target out-of-range";
    5.         return false;          
    6.     }
    7.        
    8.     var hit : RaycastHit;
    9.     if (Physics.Raycast (transform.position, target.position-transform.position, hit,attackRange,~layersToIgnoreInLineOfSight.value)) {
    10.         if (hit.transform.position == target.position) {
    11.             currentState = "Target Acquired";
    12.         } else {
    13.             currentState = "Lost line-of-sight";
    14.         }
    15.         return hit.transform.position == target.position;
    16.     }
    17.     return false;
    18. }
    19.  
    Thanks again!
     
  4. rocket5tim

    rocket5tim

    Joined:
    May 19, 2009
    Posts:
    242
    There's also a great layermasks thread on UnityAnswers.
     
  5. u3dclt

    u3dclt

    Joined:
    Aug 10, 2009
    Posts:
    30
    GUI buttons and Raycast

    Trying to find out if my situation pertains to this thread or not:

    When you have multiple GUI buttons and you're using Raycast for detection, and you only want the particular button that is touched (that button's script) to run . . . is the Layermask and Layers the best way to handle this?

    Would each button be on its own layer or have its own layermask designation?

    If so, what's the best reference for understanding this?

    Thanks guys!
     
  6. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    If you're talking about a 3D GUI, where objects in the scene act as buttons, then you needn't bother with layers - the RaycastHit contains enough information to identify the hit object.

    For a 2D GUI, you can use the GUI system and not worry about raycasts at all.
     
  7. u3dclt

    u3dclt

    Joined:
    Aug 10, 2009
    Posts:
    30
    Thanks for getting back to me.

    My buttons are SpriteManager2 animated buttons with colliders on them.

    When I press one button, it does what I want it to. When I press another, it does the same thing the first button did even though it has a different script attached.

    I'm not that familiar with Raycast so I'm not sure where the problem lies.
     
  8. Gaba

    Gaba

    Joined:
    May 29, 2009
    Posts:
    41
    I always declared a public Layermask and changed it in the editor, i find it much easier
     
  9. u3dclt

    u3dclt

    Joined:
    Aug 10, 2009
    Posts:
    30
    @andeeee

    I wanted to keep the draw calls down so that's one of the reason's I chose to use SpriteManager over GUI system.

    @Gaba

    I'm not familiar with LayerMask at all and I'm not sure how to set that up.

    Gaba wrote:

    I always declared a public Layermask and changed it in the editor, i find it much easier

    Find what much easier?

    Anyone have any specifics on Raycast and why multiple animations play when one button is touched?

    Thanks!
     
  10. u3dclt

    u3dclt

    Joined:
    Aug 10, 2009
    Posts:
    30
    Finally getting back to this.

    Gaba, I did see how it can be declared in the editor. That is convenient!

    I tried to take one of the sample codes from this thread and see if I could get it to work but but no success.


    I tried this but it didn't work. Not sure what's wrong with it.

    var hit : RaycastHit;
    var dance : GameObject;
    var layerMask : int = 1 << 10;

    if (Physics.Raycast(transform.position, transform.TransformDirection (Vector3.forward), hit, 100, layerMask)) {
    // some code if the ray hits
    dance.animation.Play("dance");
    }

    Dance is an imported 3D animated object.