#Collider.SetCollisionFilter problem
1 messages · Page 1 of 1 (latest)
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.
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
you can toggle it as freely as you want once it's unique
it will only be used on that entity
So it's just a complete clone but disposed automatically?
Also this is available in com.unity.entities@1.1.0-exp.1, right?
thanks!
Alternative approach without structural changes and allocations - you can prebake a bunch of clones and in runtime just swap reference
Can you elaborate this? how to swap in runtime BlobAssetReference for PhysicsCollider?
just bake other blob asset references
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
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
then better start figuring it out
because it's very easy
any starting point for those that I can learn? i only found old docs and old baking system
it's not old
that's how they work
// 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!
just use SystemAPI.GetComponent instead of lookup
you also forgot to add blob to asset store
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
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;
SystemAPI.SetComponent
or SystemAPI.GetComponentRW
this is only valid in baking systems
you probably forgot to add attribute
or maybe you tried to run it in runtime?
I'm currently on SystemBase, yes in runtime
just add attribute
like in manual
and then this system will only run once in baking
[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?
Could be
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
using [UpdateInGroup(typeof(PostBakingSystemGroup))] solve the issue,
store.BlobAssetStore is now Null, still can't get the BlobAssetStore
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;
It's out param
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
can't get the BlobAssetStore in runtime (systembase)
whats the purpose adding the cloned to the BlobAssetStore if I write the cloned to some component or save on some other component?
You write reference
It becomes dead if it's not saved anywhere
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
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