-
-
Save pbhogan/d9170ff611eff23229274bec9207a633 to your computer and use it in GitHub Desktop.
Unity Physics creating collider from mesh
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Runtime.CompilerServices; | |
using Unity.Burst; | |
using Unity.Collections; | |
using Unity.Entities; | |
using Unity.Jobs; | |
using Unity.Mathematics; | |
using Unity.Physics; | |
using UnityEngine; | |
using UnityEngine.Rendering; | |
using Collider = Unity.Physics.Collider; | |
using Material = Unity.Physics.Material; | |
namespace GallantGames | |
{ | |
public struct ConvertMeshToNativeBuffersJob : IJob | |
{ | |
[ReadOnly] public Mesh.MeshData MeshData; | |
[WriteOnly] public NativeArray<float3> MeshVertices; | |
[WriteOnly] public NativeArray<int3> MeshTriangles; | |
public void Execute() | |
{ | |
MeshData.GetVertices( MeshVertices.Reinterpret<Vector3>() ); | |
if (MeshData.indexFormat == IndexFormat.UInt16) | |
{ | |
var indexData16 = MeshData.GetIndexData<ushort>(); | |
var index16 = 0; | |
for (var sm = 0; sm < MeshData.subMeshCount; ++sm) | |
{ | |
var subMesh = MeshData.GetSubMesh( sm ); | |
for (int i = subMesh.indexStart, count = 0; count < subMesh.indexCount; i += 3, count += 3) | |
{ | |
MeshTriangles[index16++] = (int3) new uint3( indexData16[i], indexData16[i + 1], indexData16[i + 2] ); | |
} | |
} | |
} | |
else | |
{ | |
var indexData32 = MeshData.GetIndexData<uint>(); | |
var index32 = 0; | |
for (var sm = 0; sm < MeshData.subMeshCount; ++sm) | |
{ | |
var subMesh = MeshData.GetSubMesh( sm ); | |
for (int i = subMesh.indexStart, count = 0; count < subMesh.indexCount; i += 3, count += 3) | |
{ | |
MeshTriangles[index32++] = (int3) new uint3( indexData32[i], indexData32[i + 1], indexData32[i + 2] ); | |
} | |
} | |
} | |
} | |
} | |
public struct CreatePhysicsMeshColliderJob : IJob | |
{ | |
[ReadOnly] public NativeArray<float3> MeshVertices; | |
[ReadOnly] public NativeArray<int3> MeshTriangles; | |
[ReadOnly] public CollisionFilter CollisionFilter; | |
[ReadOnly] public Material Material; | |
[WriteOnly] public NativeReference<BlobAssetReference<Collider>> Collider; | |
public void Execute() | |
{ | |
Collider.Value = Unity.Physics.MeshCollider.Create( MeshVertices, MeshTriangles, CollisionFilter, Material ); | |
} | |
} | |
public static class PhysicsUtility | |
{ | |
public static BlobAssetReference<Collider> CreateColliderForMesh( Mesh mesh, CollisionFilter collisionFilter ) | |
{ | |
var material = new Material | |
{ | |
FrictionCombinePolicy = Material.CombinePolicy.Maximum, | |
RestitutionCombinePolicy = Material.CombinePolicy.Maximum, | |
Friction = 0.5f, | |
Restitution = 0.5f | |
}; | |
using var meshDataArray = Mesh.AcquireReadOnlyMeshData( mesh ); | |
var meshData = meshDataArray[0]; | |
var vertices = new NativeArray<float3>( meshData.vertexCount, Allocator.TempJob ); | |
var triangles = new NativeArray<int3>( meshData.GetTriangleCount(), Allocator.TempJob ); | |
var convertMeshToNativeBuffersJob = new ConvertMeshToNativeBuffersJob | |
{ | |
MeshData = meshData, | |
MeshVertices = vertices, | |
MeshTriangles = triangles | |
}; | |
convertMeshToNativeBuffersJob.Run(); | |
var createPhysicsMeshColliderJob = new CreatePhysicsMeshColliderJob | |
{ | |
MeshVertices = vertices, | |
MeshTriangles = triangles, | |
CollisionFilter = collisionFilter, | |
Material = material, | |
Collider = new NativeReference<BlobAssetReference<Collider>>( Allocator.TempJob ) | |
}; | |
createPhysicsMeshColliderJob.Run(); | |
var collider = createPhysicsMeshColliderJob.Collider.Value; | |
createPhysicsMeshColliderJob.MeshVertices.Dispose(); | |
createPhysicsMeshColliderJob.MeshTriangles.Dispose(); | |
createPhysicsMeshColliderJob.Collider.Dispose(); | |
return collider; | |
} | |
public static void AddComponentsForMesh( Entity entity, EntityManager entityManager, BlobAssetReference<Collider> collider, PhysicsBodyMotionType bodyMotionType = PhysicsBodyMotionType.Static ) | |
{ | |
entityManager.AddComponentData( entity, new PhysicsCollider { Value = collider } ); | |
switch (bodyMotionType) | |
{ | |
case PhysicsBodyMotionType.Dynamic: | |
entityManager.AddComponentData( entity, new PhysicsVelocity() ); | |
entityManager.AddComponentData( entity, PhysicsMass.CreateDynamic( collider.Value.MassProperties, 1.0f ) ); | |
break; | |
case PhysicsBodyMotionType.Kinematic: | |
entityManager.AddComponentData( entity, new PhysicsVelocity() ); | |
entityManager.AddComponentData( entity, PhysicsMass.CreateKinematic( collider.Value.MassProperties ) ); | |
break; | |
case PhysicsBodyMotionType.Static: | |
break; | |
default: | |
throw new ArgumentOutOfRangeException( nameof(bodyMotionType), bodyMotionType, null ); | |
} | |
entityManager.AddSharedComponentManaged( entity, new PhysicsWorldIndex { Value = 0 } ); | |
} | |
public static void AddComponentsForMesh( Entity entity, EntityManager entityManager, Mesh mesh, CollisionFilter collisionFilter, PhysicsBodyMotionType bodyMotionType = PhysicsBodyMotionType.Static ) | |
{ | |
var collider = CreateColliderForMesh( mesh, collisionFilter ); | |
AddComponentsForMesh( entity, entityManager, collider, bodyMotionType ); | |
} | |
public static void AddComponentsForMesh( Entity entity, EntityCommandBuffer entityCommandBuffer, BlobAssetReference<Collider> collider, PhysicsBodyMotionType bodyMotionType = PhysicsBodyMotionType.Static ) | |
{ | |
entityCommandBuffer.AddComponent( entity, new PhysicsCollider { Value = collider } ); | |
switch (bodyMotionType) | |
{ | |
case PhysicsBodyMotionType.Dynamic: | |
entityCommandBuffer.AddComponent( entity, new PhysicsVelocity() ); | |
entityCommandBuffer.AddComponent( entity, PhysicsMass.CreateDynamic( collider.Value.MassProperties, 1.0f ) ); | |
break; | |
case PhysicsBodyMotionType.Kinematic: | |
entityCommandBuffer.AddComponent( entity, new PhysicsVelocity() ); | |
entityCommandBuffer.AddComponent( entity, PhysicsMass.CreateKinematic( collider.Value.MassProperties ) ); | |
break; | |
case PhysicsBodyMotionType.Static: | |
break; | |
default: | |
throw new ArgumentOutOfRangeException( nameof(bodyMotionType), bodyMotionType, null ); | |
} | |
entityCommandBuffer.AddSharedComponent( entity, new PhysicsWorldIndex { Value = 0 } ); | |
} | |
public static void AddComponentsForMesh( Entity entity, EntityCommandBuffer entityCommandBuffer, Mesh mesh, CollisionFilter collisionFilter, PhysicsBodyMotionType bodyMotionType = PhysicsBodyMotionType.Static ) | |
{ | |
var collider = CreateColliderForMesh( mesh, collisionFilter ); | |
AddComponentsForMesh( entity, entityCommandBuffer, collider, bodyMotionType ); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment