- Home /
[ECS] How to dynamically update body friction
Hello,
I have a problem with updating ECS PhysicsCollider
material.
For now, while I am creating new phycis entity I am simply doing:
Unity.Physics.Material someMaterial = new Unity.Physics.Material {
Friction = 1,
Restitution = 0.5f
};
BlobAssetReference<Unity.Physics.Collider> collider = Unity.Physics.CapsuleCollider.Create(new CapsuleGeometry {
Radius = baseDiameter/2,
Vertex0 = new float3(0, 0.0f, 0),
Vertex1 = new float3(0, height, 0)
}, CollisionFilter.Default, someMaterial);
EntityManager.SetComponentData<PhysicsCollider>(e, new PhysicsCollider { Value = collider });
And this is working perfectly fine. But the problem is when I want to change body collider, but use the same material. Here is some system to update colliders:
protected override void OnUpdate()
{
var ecb = m_EndSimulationEcbSystem.CreateCommandBuffer().AsParallelWriter();
List<RenderMesh> renderes = new List<RenderMesh>();
EntityManager.GetAllUniqueSharedComponentData<RenderMesh>(renderes);
foreach (RenderMesh render in renderes)
{
if (render.mesh == null) continue;
var meshBounds = render.mesh.bounds;
var center = (float3) meshBounds.center;
Entities.WithSharedComponentFilter(render)
.WithAll<UpdateColliderByMesh_TAG>()
.ForEach((Entity e, int entityInQueryIndex, ref PhysicsCollider colliderComponent) => {
var collider = Unity.Physics.BoxCollider.Create(new BoxGeometry {
Center = meshBounds.center,
Size = meshBounds.size,
Orientation = quaternion.Euler(0, 0, 0),
BevelRadius = 0.01f
}); // <--- how to pass material from previous collider here????
colliderComponent.Value = collider;
ecb.RemoveComponent<UpdateColliderByMesh_TAG>(entityInQueryIndex, e);
})
.ScheduleParallel();
}
m_EndSimulationEcbSystem.AddJobHandleForProducer(this.Dependency);
}
And this is also working fine BUT it resets collider material to default one, so it means body has no friction. So the question is how to get previous material and apply it to the new collider?
Any help will be more than welcome ;)
this is sidenote too, but blob assets alloc memory so don't leave a leak there
colliderComponent.Value.Dispose();
colliderComponent.Value = collider;
Answer by NT_Ninetails · Dec 26, 2020 at 07:45 PM
@wiiiteekk the easy way would be to setup "prefabs for the material to be called later
[ReadOnly] static Unity.Physics.Material[] MaterialPrefabs = new Unity.Physics.Material /*continue here*/
But if you're trying to access the data dynamically then you would have to cast the PhysicsCollider pointer to the matching collider you used to create it.
something like...
unsafe{
Unity.Physics.CapsuleColider* capsule_p = (Unity.Physics.CapsuleColider*)colliderComponent.ColliderPtr;
var collider = Unity.Physics.BoxCollider.Create(new BoxGeometry {
Center = meshBounds.center,
Size = meshBounds.size,
Orientation = quaternion.Euler(0, 0, 0),
BevelRadius = 0.01f
},capsule_p->Filter,capsule_p->Material); // <--- add pointer values
colliderComponent.Value = collider;
ecb.RemoveComponent<UpdateColliderByMesh_TAG>(entityInQueryIndex, e);
}
Though i don't recommend this unless you know what your doing.
Your answer
Follow this Question
Related Questions
how to capsule cast from within Entities.ForEach job? ECS 1 Answer
2D 360 degress platformer example needed 0 Answers
Can not add PhysicsCollider at runtime Unity in ECS 1 Answer
(DOTS) How to slowly rotate an object to face a point? 1 Answer
Cannot move anything with pure ECS Physics instantiation 1 Answer