Posts: 70
Threads: 23
Joined: Dec 2021
Reputation:
0
30-04-2024, 10:00 AM
Hi, I'm looking for a way to setup Ignore Collisions between my Character all body colliders and its Motor (a separated capsule who control the character movement)
I can setup this just fine with Unity's Physics.IgnoreCollision(a, b, ignore); for Unity Colliders.
The reason I can't use Obi layer to do this is I want all characters no matter friends or foes can consider moving on top of any other characters, so Motor can interact with other character's body colliders, but not interact with its owner's body colliders. Do Obi have this method? I've looked into the Collision page and does not see any mention.
Posts: 6,313
Threads: 24
Joined: Jun 2017
Reputation:
399
Obi Owner:
30-04-2024, 10:26 AM
(This post was last modified: 30-04-2024, 10:30 AM by josemendez.)
(30-04-2024, 10:00 AM)spikebor Wrote: The reason I can't use Obi layer to do this
Hi,
Not sure what you mean by Obi "layer"?
(30-04-2024, 10:00 AM)spikebor Wrote: I want all characters no matter friends or foes can consider moving on top of any other characters, so Motor can interact with other character's body colliders, but not interact with its owner's body colliders. Do Obi have this method? I've looked into the Collision page and does not see any mention.
For controlling collisions, Obi uses a filter-based system that allows you to assign a specific category to both colliders and particles, and a mask that determines which categories it is allowed to collide against. You can find this explained in the Collisions page:
http://obi.virtualmethodstudio.com/manua...#filtering
So for your use case you can set up a character's body colliders on a specific category, and set the character's softbody to collide with all categories except its own. This will allow you to have up to 16 characters per solver (as there's 16 available categories). In case you need more than 16 categories, you can dynamically reassign them based on distance between their transforms.
Note there's no equivalent to Physics.IgnoreCollision in Obi, as this information would need to be stored per-particle and the amount of memory required would skyrocket. The advantage of a category/mask based system is that it can be efficiently stored using only 4 bytes per particle (2 for the category, 2 for the mask) and it's also really fast to test (just a bitwise "and").
kind regards,
Posts: 70
Threads: 23
Joined: Dec 2021
Reputation:
0
(30-04-2024, 10:26 AM)josemendez Wrote: Hi,
Not sure what you mean by Obi "layer"?
For controlling collisions, Obi uses a filter-based system that allows you to assign a specific category to both colliders and particles, and a mask that determines which categories it is allowed to collide against. You can find this explained in the Collisions page:
http://obi.virtualmethodstudio.com/manua...#filtering
So for your use case you can set up a character's body colliders on a specific category, and set the character's softbody to collide with all categories except its own. This will allow you to have up to 16 characters per solver (as there's 16 available categories). In case you need more than 16 categories, you can dynamically reassign them based on distance between their transforms.
Note there's no equivalent to Physics.IgnoreCollision in Obi, as this information would need to be stored per-particle and the amount of memory required would skyrocket. The advantage of a category/mask based system is that it can be efficiently stored using only 4 bytes per particle (2 for the category, 2 for the mask) and it's also really fast to test (just a bitwise "and").
kind regards,
Yes, I mean Obi "layer" is this mask filtering system.
So dynamically setting filter and mask? I still not wrap my head around this fully.
For example:
character A: the soft bodies must be setup dynamically so that it will Not contact with its own motor (set to category 2).
character B becomes the nearest character to A: it also set Not contact with its motor, for example set to category 3, just a random number from 2-15 so that it is different than 2 (motor of A) because it wants to contact with character A.
This dynamically set "contact with" and motor category logic will execute every time character A detect another character that become the new nearest character? This sound very complicated haha.
Posts: 6,313
Threads: 24
Joined: Jun 2017
Reputation:
399
Obi Owner:
30-04-2024, 12:40 PM
(This post was last modified: 30-04-2024, 12:41 PM by josemendez.)
(30-04-2024, 11:55 AM)spikebor Wrote: Yes, I mean Obi "layer" is this mask filtering system.
So dynamically setting filter and mask? I still not wrap my head around this fully.
It depends on how many characters you need to simulate simultaneously. You'll only ever need to dynamically change the filtering system at runtime if you have more than 16 characters on screen, since that's the maximum amount of categories you can have. Otherwise you can just give a different category to each character (doesn't matter which one), and set its mask to "everything except its own category".
If you really must have more than 16 characters simultaneously (which is probably too many if they all have to be simulated) you can just group them by proximity using a regular grid, for example. Assuming each character has a maximum size/radius of X meters:
- Take the position of the character, divide it by X and take its integer part. This gives you coordinates of a cell the character is in. Characters in cells not adjacent to it are guaranteed to be more than X meters apart, so you know a character can only ever collide with characters in its same cell or cells adjacent to it.
- Whenever a character moves to a new cell (that is, its integer coordinates change), take the categories of all characters found in adjacent cells and assign the first free one to it.
This method allows you to have up to 16 characters per cell neighborhood and is fairly straightforward to implement.
Posts: 70
Threads: 23
Joined: Dec 2021
Reputation:
0
(30-04-2024, 12:40 PM)josemendez Wrote: It depends on how many characters you need to simulate simultaneously. You'll only ever need to dynamically change the filtering system at runtime if you have more than 16 characters on screen, since that's the maximum amount of categories you can have. Otherwise you can just give a different category to each character (doesn't matter which one), and set its mask to "everything except its own category".
If you really must have more than 16 characters simultaneously (which is probably too many if they all have to be simulated) you can just group them by proximity using a regular grid, for example. Assuming each character has a maximum size/radius of X meters:
- Take the position of the character, divide it by X and take its integer part. This gives you coordinates of a cell the character is in. Characters in cells not adjacent to it are guaranteed to be more than X meters apart, so you know a character can only ever collide with characters in its same cell or cells adjacent to it.
- Whenever a character moves to a new cell (that is, its integer coordinates change), take the categories of all characters found in adjacent cells and assign the first free one to it.
This method allows you to have up to 16 characters per cell neighborhood and is fairly straightforward to implement.
Wonderful, thank you!
I use this code to do CollideWithEverythingExcept(int excludedFlag) and the logic works fine now.
Yes I shouldn't worry too much about the character count since not much characters having simulation on at the same time around the Player.
Code: int CollideWithEverythingExcept(int excludedFlag)
{
// Ensure the excluded flag is within the valid range (0-15)
if (excludedFlag < 0 || excludedFlag > 15)
{
return -1;
}
int allFlags = ObiUtils.CollideWithEverything;
// Clear the bit corresponding to the excluded flag
int result = allFlags & ~(1 << excludedFlag);
return result;
}
public void ChangeMotorCategory(int id) {
if (id == motorCategory) return;
Debug.Log($"change motor category of {character.name.ColorMe(Color.green)} to {id.ColorMe(Color.yellow)}");
motorCategory = id;
var mask = CollideWithEverythingExcept(id);
motorObiCollider.Filter = ObiUtils.MakeFilter(mask, id);
//bodies and motor will collide with everything except its own
if (hasSoftbodies) {
foreach (var b in softbodieDatas) {
//Debug.Log($"set softbody {b.softbody} mask to {mask}");
b.softbody.SetFilterCategory(id);
b.softbody.SetFilterMask(mask);
}
}
}
|