Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
12 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
  • Help Room /
avatar image
0
Question by zckhyt · Jan 17, 2016 at 05:28 PM · collisionphysicscolliderlayerslayermask

How to Ignore Collisions Between a Layer and a LayerMask?

This was a question I had, and couldn't find an answer for it. However, after some thought, I finally came up with a solution. I decided to post the question, and an answer to my question, for anyone else who ever has my same problem, as the answer was not apparent. Though, simultaneously, I am also looking for an improvement upon my answer.

I'm trying to ignore collision between a single layer, and a set of layers that I've defined in a LayerMask.

I have a LayerMask variable with whom I've marked a set of layers as being inapplicable for use. Like one might when making a mask for a raycast, to filter out results.

There is a Physics.IgnoreLayerCollision(int, int), but not really a Physics.IgnoreLayerCollision(int, LayerMask), or anything similar. Actually, the latter is syntactically acceptable as a LayerMask is an unsigned integer (it's just a just a 32-bit string), but does not actually do anything useful. It will actually throw an error if you have more than the 4th index of the LayerMasked marked true (b/c 2^5 = 32 and it only allows for input from 0-31, I believe).

So I'm looking for a suggestion on how to either decode the bit string and get an array of numbers representing the layers I want to ignore, or an alternative means of ignoring collision from one layer to a set of layers.

So hopefully I didn't miss a really obvious solution, but if anyone had anything better than this, then please share! Otherwise, hopefully at least one person finds this useful (see my answer below, in the answer section).

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
2
Best Answer

Answer by zckhyt · Jan 22, 2016 at 02:50 PM

My Solution

As mentioned, a LayerMask is a 32-bit string. Each bit stores a 1 if that layer is selected, or a 0 if it is not. Each Layer (index n) increases the value of the string by 2^n. E.g., if you mark the first layer as true, it increases the value of the LayerMask by 2^0 = 1.

So if we look at the value of the string, we can tell if it has a layer n marked as true if that n bit is 1. This is done by bit-shifting. As we shift the string n-bits to the right, if the value is still greater-than-zero, that means our current index is a 1. E.g., if the 31st index of a layermask (the highest index of a layermask) is true, that means to 32nd bit of the string is a 1 (the string goes from 1-32, whereas our layers go from 0-31). So our string is shifted 31-times to the right, which leaves us 1, which is greater-than-zero.

Whenever we do this, we need to subtract 1 << n from our bitstring, so we don't the bits from a previous layer in the continuing process.

So here is what I did for my player, who was in the "Player" layer, when I wanted to blacklist some layers with objects I didn't want my player to collide with:

     LayerMask someLayerMask;
     int playerLayer = LayerMask.NameToLayer("Player");
     uint bitstring = (uint)someLayerMask.value;
     for (int i = 31; bitstring > 0; i--)
         if ((bitstring >> i) > 0)
         {
             bitstring = ((bitstring << 32 - i) >> 32 - i);
             Physics.IgnoreLayerCollision(playerLayer, i);
         }

We can break if the bitstring ever is equal to 0, because then there can obviously be nothing left.

A uint data type is used to represent the bitstring as a normal integer's leading-bit signifies if the number is positive or negative. This would mean that if you mark the last layer (and the last layer only), your bitstring value would be -2^31. Which the loop ignores, and would result in it missing the other marked layers. uint is C#'s version of the unsigned integer, which uses the entire 32-bits to represent a positive integer up to 2^32 - 1.

If the LayerMask is a public variable, you can edit it in the Unity Editor. Otherwise, you can set a bit to true by: someLayerMask = ~((1 << n1) | (1 << n2) | ... ); where n1, n2, ... are indices you want to mark true.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image rayant77 · Jul 14, 2018 at 07:35 PM 0
Share

Old post I know, but this was very helpful! In the off chance anyone's still here... this solution works perfectly called from Awake() or Start() but if I put it in a method and call from Update() it completely locks up Unity while running a test. Same exact code. Any ideas?

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

3 People are following this question.

avatar image avatar image avatar image

Related Questions

Realistic Soccer VR 2 Answers

Not using GetComponent during OnCollisionEnter or OnTriggerEnter 1 Answer

How can I make my script recognize my player is in some layer(Thats not solid)? 0 Answers

How to move an object on a terrain that will always stay on top of the terrain? 2 Answers

Ignored colliders still interfere with physics simulation. 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges