#Collider.SetCollisionFilter problem

1 messages · Page 1 of 1 (latest)

spice ruin
#

I just realized Collider.SetCollisionFilter works in a shared manner (the collision filter changes for every object using that exact collider). How can I achieve this on per object basis?

bleak heath
#

you have to make a unique copy of the blob

#

in 1.1 they added an easier way to do this with PhysicsCollider.MakeUnique()

#

Users can now verify if a collider blob is unique, and make it unique easily if required. The newly introduced PhysicsCollider.IsUnique property lets users check if a PhysicsCollider is unique and turn it into a unique collider if desired via the function PhysicsCollider.MakeUnique(). Making a collider unique with this function also takes care of the collider blob lifetime management and will automatically dispose it if it is no longer needed.

spice ruin
#

Would it be bad for performance if I MakeUniqued and then changed the collision filter to the same one many times? I only have two possible filters so if I understand correctly it would be good to just MakeUnique once and reuse it?

#

What I mean is should I cache the Unique colliders if I make multiple same ones or does that somehow already happens

bleak heath
#

you can toggle it as freely as you want once it's unique

#

it will only be used on that entity

spice ruin
#

So it's just a complete clone but disposed automatically?

#

Also this is available in com.unity.entities@1.1.0-exp.1, right?

bleak heath
#

well com.unity.physics

#

but yes

spice ruin
#

thanks!

thorny delta
#

Alternative approach without structural changes and allocations - you can prebake a bunch of clones and in runtime just swap reference

bleak heath
#

^ what I actually do

#

but there are kind of limits to this if you need layer freedom

weary condor
thorny delta
#

and literally swap field value with other

#

to create another one you need to World.GetExistingSystemManaged<BakingSystem>() get this

#

and get BlobAssetStore from it

#

then

#

get your baked PhysicsCollider

#

and call .Clone() on it

#

add it to asset store

#

and save on some other component

#

that's it

weary condor
#

currently I have no idea about creating/manipulating BakingSystem and BlobAssetStore

#

i will create 2 prefabs, 1 for collision and 1 for non collision for now

thorny delta
#

because it's very easy

weary condor
#

any starting point for those that I can learn? i only found old docs and old baking system

thorny delta
#

that's how they work

weary condor
# thorny delta then better start figuring it out
// get the blob reference
var currentCollider = SystemAPI.GetComponentRW<PhysicsCollider>(spawnedEnemy);

// create copy of the asset blob reference
var clonedCollider = currentCollider.ValueRO.Value.Value.Clone();
                
// manipulate the blob reference
clonedCollider.Value.SetCollisionResponse(CollisionResponsePolicy.RaiseTriggerEvents);
                
// set it to current collider
currentCollider.ValueRW.Value = clonedCollider;

well yess. This method works, thank you issue!

thorny delta
#

you also forgot to add blob to asset store

weary condor
#

yes, I still need more research, just a simple one step first. I've tried to add

var store = World.GetExistingSystemManaged<BakingSystem>().BlobAssetStore;
store.TryAdd(ref clonedCollider);

but get nullReferenceException

weary condor
# thorny delta just use `SystemAPI.GetComponent` instead of lookup

how to set the value to current entity? when i use SystemAPI.GetComponent it doesnt change the current entity physics

equivalent of this line of code

// set it to current collider
currentCollider.Value = clonedCollider;
ColliderLookup[spawnedEnemy] = currentCollider;
thorny delta
#

or SystemAPI.GetComponentRW

thorny delta
#

you probably forgot to add attribute

#

or maybe you tried to run it in runtime?

weary condor
#

I'm currently on SystemBase, yes in runtime

thorny delta
#

just add attribute

#

like in manual

#

and then this system will only run once in baking

weary condor
# thorny delta you probably forgot to add attribute
[UpdateInGroup(typeof(PostBakingSystemGroup))] // added post, to avoid script race
[WorldSystemFilter(WorldSystemFilterFlags.BakingSystem)] // added the filter
public partial struct NonInterCollisionBakingSystem : ISystem
{
    public void OnUpdate(ref SystemState state)
    {
        var enemyPrefabQuery = SystemAPI.QueryBuilder().WithAll<EnemyTagComponent>().Build();

        var store = state.World.GetExistingSystemManaged<BakingSystem>().BlobAssetStore;
        var enemyPrefabArray = enemyPrefabQuery.ToEntityArray(Allocator.Temp);
        foreach (var item in enemyPrefabArray)
        {
            var currentCollider = SystemAPI.GetComponent<PhysicsCollider>(item).Value;

            var clonedCollider = currentCollider.Value.Clone();
            clonedCollider.Value.SetCollisionResponse(CollisionResponsePolicy.RaiseTriggerEvents);
            
            var added = store.BlobAssetStore.TryAdd(ref clonedCollider);
            
            if (added)
            {
                Debug.Log($"{item} collider added");
            }
        }
    }
}

is this baking system executed before the PhysicsBaking? so It got null ref on getting the currentCollider?

thorny delta
#

take a look at manual

#

It has a page about baking system group order

#

Try updating in latest one

#

Or just use, order last on default one

weary condor
thorny delta
#

Why are you using static world

#

Use system's one

weary condor
# thorny delta Why are you using static world

now I'm sucessfully added the BlobAssetRef to the BlobAssetStore using TryAdd, how to swap it on runtime? the TryGet needs Hash128

// on SystemBase

var store = World.GetExistingSystemManaged<BakingSystem>().BlobAssetStore;
Debug.Log(store);  // printed log NULL
var currentCollider = SystemAPI.GetComponentRW<PhysicsCollider>(spawnedEnemy);
store.BlobAssetStore.TryGet(new Unity.Entities.Hash128(), out BlobAssetReference<PhysicsCollider> cloned);
currentCollider.ValueRW.Value = cloned.Value.Value;
thorny delta
#

you need TryAdd

#

You add clones to blob store

#

To make sure they will exist in runtime

#

make clone

#

Try add it

#

Write it to some component

#

Profit

#

In runtime just use blom reference you wrote it some component into PhysicsCollider

weary condor
thorny delta
#

Why do you need it

#

It's only for baking

weary condor
#

whats the purpose adding the cloned to the BlobAssetStore if I write the cloned to some component or save on some other component?

thorny delta
#

It becomes dead if it's not saved anywhere

weary condor
#

now I'm saving it to Singleton DynamicBuffer<EnemyPrefabBufferData> but It I didn't get the reference. Is there any wrong codes that doesn't pass the reference?

var item = enemyPrefabArray[i];
var currentCollider = SystemAPI.GetComponentRO<PhysicsCollider>(item);

var clonedCollider = currentCollider.ValueRO.Value.Value.Clone();
clonedCollider.Value.SetCollisionResponse(CollisionResponsePolicy.RaiseTriggerEvents);

var added = store.TryAdd(ref clonedCollider);

if (added)
{
    Debug.Log($"{state.EntityManager.GetName(item)} collider added");
    
    var currentBuffer = enemyPrefabBufferData[i];
    currentBuffer.nonInterCollisionCollider = clonedCollider;
}
#

so, I manipulate/edit the CollisionResponese but it doesnt work. Seems it have blank/default value struct of PhysicsCollider

thorny delta
#

remove if added condition

#

you need to write to your buffer regardless of whether collider was added or not

#

because it won't be added for cases, when it's already in store

#

it auto deduplicates them

#

also

#
    var currentBuffer = enemyPrefabBufferData[i];
    currentBuffer.nonInterCollisionCollider = clonedCollider;
#

this writes to a copy of struct

#

buffer is unnaffected