// Compound & Other private void CalculateCollisionData(CompoundCollider a, ICollidable b) { a.colliders.ForEach(collider => { ResolveCollision(collider, b); }); }
public static PhysicsCollider GetEnviromentPhysicsCollider(string name, float scale = 1f) { PhysicsCollider pc = new PhysicsCollider { }; switch (name) { case "Kanto|Tree": NativeArray <CompoundCollider.ColliderBlobInstance> cs = new NativeArray <CompoundCollider.ColliderBlobInstance>(2, Allocator.TempJob); cs[0] = new CompoundCollider.ColliderBlobInstance { Collider = CylinderCollider.Create(new CylinderGeometry { Orientation = Quaternion.Euler(new float3(270f, 270f, 0)), Height = 1f * scale, Radius = .25f * scale, SideCount = 20, Center = new float3(0, .5f, 0) * scale }, new CollisionFilter { BelongsTo = TriggerEventClass.Collidable, CollidesWith = TriggerEventClass.Collidable, GroupIndex = 1 }), CompoundFromChild = new RigidTransform { rot = quaternion.identity } }; cs[1] = new CompoundCollider.ColliderBlobInstance { Collider = CylinderCollider.Create(new CylinderGeometry { Center = new float3(0, 1.7f, 0) * scale, Orientation = Quaternion.Euler(new float3(90f, 0, 0)), Height = 1.5f * scale, Radius = 1f * scale, SideCount = 20 }, new CollisionFilter { BelongsTo = TriggerEventClass.Collidable, CollidesWith = TriggerEventClass.Collidable, GroupIndex = 1 }), CompoundFromChild = new RigidTransform { rot = quaternion.identity } }; pc = new PhysicsCollider { Value = CompoundCollider.Create(cs) }; cs.Dispose(); break; default: Debug.LogWarning("Failed to get collider for \"" + name + "\""); break; } return(pc); }
public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) { var rigComponent = GetComponent <RigComponent>(); if (rigComponent != null) { var buffer = dstManager.AddBuffer <PhysicsColliderFollowEntityData>(entity); GetData(rigComponent, out Transform[] children, out var shapes); // children = new Transform[0]; if (children.Length > 1) { int numberOfValidShapes = GetNumberOfValidShapes(shapes); NativeList <CompoundCollider.ColliderBlobInstance> blobs = new NativeList <CompoundCollider.ColliderBlobInstance>(Allocator.TempJob); for (int i = 0; i < children.Length; i++) { if (shapes[i] != null && shapes[i].enabled) { var shapeExt = children[i].gameObject.GetComponent <PhysicsMaterialsExtensionComponent>(); BlobAssetReference <Unity.Physics.Collider> collider = GenerateCollider(shapes[i], shapeExt, out float3 offsetPosition, out quaternion offsetRotation); blobs.Add(new CompoundCollider.ColliderBlobInstance { CompoundFromChild = new RigidTransform(children[i].rotation, children[i].position - this.transform.position), Collider = collider }); var ltw = new LocalToWorld { Value = new float4x4(children[i].rotation, children[i].position - this.transform.position) }; buffer.Add(new PhysicsColliderFollowEntityData { AnimationDataIndex = i, CompoundColliderChildIndex = blobs.Length - 1, RootTransform = new RigidTransform(InitialRootRotation, InitialRootPosition), sourceEntity = conversionSystem.GetPrimaryEntity(shapes[i].gameObject), CompoundColliderDataIsSet = false, Old = ltw, Offset = ltw }); Debug.Log("Setting \"" + children[i].name + "\" to " + (blobs.Length - 1) + " animation index =" + i + ", valid shapes = " + numberOfValidShapes + ", belongs to " + shapes[i].BelongsTo.Value + ", collides with = " + shapes[i].CollidesWith.Value); // shapes[i].enabled = false; } } if (blobs.Length > 0) { dstManager.AddComponentData(entity, new PhysicsCollider { Value = CompoundCollider.Create(blobs) }); } blobs.Dispose(); } else if (children.Length == 1) { dstManager.AddComponentData(entity, new PhysicsCollider { Value = GenerateCollider(shapes[0], null, out var a, out var b) });
protected override void OnUpdate() { // A map from entities to arrays of colliders that were not applied to the body during the first pass. m_ExtraColliders = new NativeMultiHashMap <ComparableEntity, LeafShapeData>(64, Allocator.Temp); // TODO - add custom data to Physics.Collider? // First pass. // Convert all editor shape components into colliders, and either apply them to their parent rigid body // or store them for building compound colliders in the second pass. Entities.ForEach <T>(ConvertShape); // Second pass. // Merge any leftover colliders into their parent rigid bodies, as compound colliders. if (m_ExtraColliders.Length > 0) { var keys = m_ExtraColliders.GetUniqueKeyArray(Allocator.Temp); using (keys.Item1) { for (var k = 0; k < keys.Item2; ++k) { ComparableEntity entity = keys.Item1[k]; var collider = DstEntityManager.GetComponentData <PhysicsCollider>(entity.Entity); var children = new NativeList <CompoundCollider.ColliderBlobInstance>(16, Allocator.Temp); if (collider.IsValid) { // Include the already assigned collider as a child children.Add(new CompoundCollider.ColliderBlobInstance { Collider = collider.Value, CompoundFromChild = RigidTransform.identity }); } byte customData = 0; if (m_ExtraColliders.TryGetFirstValue(entity, out var child, out var iterator)) { do { children.Add(child.ColliderBlobInstance); customData &= child.CustomFlags; // TODO: Should be |= ?? } while (m_ExtraColliders.TryGetNextValue(out child, ref iterator)); } collider.Value = CompoundCollider.Create(children); children.Dispose(); DstEntityManager.SetComponentData(entity.Entity, collider); if (customData != 0) { DstEntityManager.AddOrSetComponent(entity.Entity, new PhysicsCustomData { Value = customData }); } } } } m_ExtraColliders.Dispose(); }
public void MassProperties_BuiltFromChildren_MatchesExpected() { void TestCompoundBox(RigidTransform transform) { // Create a unit box var box = BoxCollider.Create(transform.pos, transform.rot, new float3(1, 1, 1), 0.0f); // Create a compound of mini boxes, matching the volume of the single box var miniBox = BoxCollider.Create(float3.zero, quaternion.identity, new float3(0.5f, 0.5f, 0.5f), 0.0f); var children = new NativeArray <CompoundCollider.ColliderBlobInstance>(8, Allocator.Temp) { [0] = new CompoundCollider.ColliderBlobInstance { Collider = miniBox, CompoundFromChild = math.mul(transform, new RigidTransform(quaternion.identity, new float3(+0.25f, +0.25f, +0.25f))) }, [1] = new CompoundCollider.ColliderBlobInstance { Collider = miniBox, CompoundFromChild = math.mul(transform, new RigidTransform(quaternion.identity, new float3(-0.25f, +0.25f, +0.25f))) }, [2] = new CompoundCollider.ColliderBlobInstance { Collider = miniBox, CompoundFromChild = math.mul(transform, new RigidTransform(quaternion.identity, new float3(+0.25f, -0.25f, +0.25f))) }, [3] = new CompoundCollider.ColliderBlobInstance { Collider = miniBox, CompoundFromChild = math.mul(transform, new RigidTransform(quaternion.identity, new float3(+0.25f, +0.25f, -0.25f))) }, [4] = new CompoundCollider.ColliderBlobInstance { Collider = miniBox, CompoundFromChild = math.mul(transform, new RigidTransform(quaternion.identity, new float3(-0.25f, -0.25f, +0.25f))) }, [5] = new CompoundCollider.ColliderBlobInstance { Collider = miniBox, CompoundFromChild = math.mul(transform, new RigidTransform(quaternion.identity, new float3(+0.25f, -0.25f, -0.25f))) }, [6] = new CompoundCollider.ColliderBlobInstance { Collider = miniBox, CompoundFromChild = math.mul(transform, new RigidTransform(quaternion.identity, new float3(-0.25f, +0.25f, -0.25f))) }, [7] = new CompoundCollider.ColliderBlobInstance { Collider = miniBox, CompoundFromChild = math.mul(transform, new RigidTransform(quaternion.identity, new float3(-0.25f, -0.25f, -0.25f))) } }; var compound = CompoundCollider.Create(children); children.Dispose(); var boxMassProperties = box.Value.MassProperties; var compoundMassProperties = compound.Value.MassProperties; TestUtils.AreEqual(compoundMassProperties.Volume, boxMassProperties.Volume, 1e-3f); TestUtils.AreEqual(compoundMassProperties.AngularExpansionFactor, boxMassProperties.AngularExpansionFactor, 1e-3f); TestUtils.AreEqual(compoundMassProperties.MassDistribution.Transform.pos, boxMassProperties.MassDistribution.Transform.pos, 1e-3f); //TestUtils.AreEqual(compoundMassProperties.MassDistribution.Orientation, boxMassProperties.MassDistribution.Orientation, 1e-3f); // TODO: Figure out why this differs, and if that is a problem TestUtils.AreEqual(compoundMassProperties.MassDistribution.InertiaTensor, boxMassProperties.MassDistribution.InertiaTensor, 1e-3f); } // Compare box with compound at various transforms TestCompoundBox(RigidTransform.identity); TestCompoundBox(new RigidTransform(quaternion.identity, new float3(1.0f, 2.0f, 3.0f))); TestCompoundBox(new RigidTransform(quaternion.EulerXYZ(0.5f, 1.0f, 1.5f), float3.zero)); TestCompoundBox(new RigidTransform(quaternion.EulerXYZ(0.5f, 1.0f, 1.5f), new float3(1.0f, 2.0f, 3.0f))); }
public override void CreateScene(CompoundDemoScene sceneSettings) { // // Floor // { // BlobAssetReference<Unity.Physics.Collider> collider = Unity.Physics.BoxCollider.Create(new float3(0, -0.1f, 0), Quaternion.identity, new float3(10.0f, 0.1f, 10.0f), 0.05f); // CreatedColliders.Add(collider); // CreateStaticBody(float3.zero, quaternion.identity, collider); // } // Dynamic compound { var box = new BoxGeometry { Center = float3.zero, Orientation = quaternion.identity, Size = new float3(1), BevelRadius = 0.05f }; var sphere = new SphereGeometry { Center = float3.zero, Radius = 0.5f }; var children = new NativeArray <CompoundCollider.ColliderBlobInstance>(3, Allocator.Temp) { [0] = new CompoundCollider.ColliderBlobInstance { CompoundFromChild = new RigidTransform(quaternion.identity, new float3(-1, 0, 0)), Collider = Unity.Physics.BoxCollider.Create(box) }, [1] = new CompoundCollider.ColliderBlobInstance { CompoundFromChild = RigidTransform.identity, Collider = Unity.Physics.SphereCollider.Create(sphere) }, [2] = new CompoundCollider.ColliderBlobInstance { CompoundFromChild = new RigidTransform(quaternion.identity, new float3(1, 0, 0)), Collider = Unity.Physics.BoxCollider.Create(box) } }; foreach (var child in children) { CreatedColliders.Add(child.Collider); } BlobAssetReference <Unity.Physics.Collider> collider = CompoundCollider.Create(children); CreatedColliders.Add(collider); children.Dispose(); CreateDynamicBody(new float3(0, 1, 0), quaternion.identity, collider, float3.zero, float3.zero, 1.0f); } }
protected unsafe override void Start() { //float3 gravity = new float3(0, -9.81f, 0); float3 gravity = float3.zero; base.init(gravity); // // Floor // { // BlobAssetReference<Unity.Physics.Collider> collider = Unity.Physics.BoxCollider.Create(new float3(0, -0.1f, 0), Quaternion.identity, new float3(10.0f, 0.1f, 10.0f), 0.05f); // CreateStaticBody(float3.zero, quaternion.identity, collider); // } // Dynamic compound { var box = new BoxGeometry { Center = float3.zero, Orientation = quaternion.identity, Size = new float3(1), BevelRadius = 0.05f }; var sphere = new SphereGeometry { Center = float3.zero, Radius = 0.5f }; var children = new NativeArray <CompoundCollider.ColliderBlobInstance>(3, Allocator.Temp) { [0] = new CompoundCollider.ColliderBlobInstance { CompoundFromChild = new RigidTransform(quaternion.identity, new float3(-1, 0, 0)), Collider = Unity.Physics.BoxCollider.Create(box) }, [1] = new CompoundCollider.ColliderBlobInstance { CompoundFromChild = RigidTransform.identity, Collider = Unity.Physics.SphereCollider.Create(sphere) }, [2] = new CompoundCollider.ColliderBlobInstance { CompoundFromChild = new RigidTransform(quaternion.identity, new float3(1, 0, 0)), Collider = Unity.Physics.BoxCollider.Create(box) } }; BlobAssetReference <Unity.Physics.Collider> collider = CompoundCollider.Create(children); children.Dispose(); CreateDynamicBody(new float3(0, 1, 0), quaternion.identity, collider, float3.zero, float3.zero, 1.0f); } }
private void UpdateBoundsCompound(CompoundCollider collider) { boundsMin = new Vector2(Mathf.Infinity, Mathf.Infinity); boundsMax = new Vector2(Mathf.NegativeInfinity, Mathf.NegativeInfinity); collider.colliders.ForEach(col => { col.boundingBox.Update(); SetBoundsMinMaxValues(col.boundingBox.boundsMin, col.boundingBox.boundsMax); }); }
private static PhysicsCollider CreateCompoundCollider(PhysicsCollider c1, PhysicsCollider c2) { CompoundCollider.ColliderBlobInstance[] colliderArray = new CompoundCollider.ColliderBlobInstance[2]; colliderArray[0] = new CompoundCollider.ColliderBlobInstance { Collider = c1.Value }; colliderArray[1] = new CompoundCollider.ColliderBlobInstance { Collider = c2.Value }; NativeArray <CompoundCollider.ColliderBlobInstance> colliderNativeArray = new NativeArray <CompoundCollider.ColliderBlobInstance>(colliderArray, Allocator.TempJob); PhysicsCollider compoundCollider = new PhysicsCollider { Value = CompoundCollider.Create(colliderNativeArray) }; colliderNativeArray.Dispose(); return(compoundCollider); }
protected virtual void OnDrawGizmos() { collidables.ForEach(collidable => { if (collidable.boundingBox == null) { return; } if (collidable is CompoundCollider) { CompoundCollider cc = collidable as CompoundCollider; cc.colliders.ForEach(col => { DrawBoundingBox(col.boundingBox); }); } DrawBoundingBox(collidable.boundingBox); }); }
public static unsafe BlobAssetReference <Collider> GenerateRandomCompound(ref Random rnd) { int numChildren = rnd.NextInt(1, 10); var children = new NativeArray <CompoundCollider.ColliderBlobInstance>(numChildren, Allocator.Temp); for (int i = 0; i < numChildren; i++) { children[i] = new CompoundCollider.ColliderBlobInstance { CompoundFromChild = new RigidTransform { pos = (rnd.NextInt(10) > 0) ? rnd.NextFloat3(-5.0f, 5.0f) : float3.zero, rot = (rnd.NextInt(10) > 0) ? rnd.NextQuaternionRotation() : quaternion.identity }, Collider = GenerateRandomCollider(ref rnd) }; } return(CompoundCollider.Create(children)); }
private BlobAssetReference <Collider> CreateGroundCompoundWith2Children(float3 groundSize) { var groundCollider1 = BoxCollider.Create(new BoxGeometry { Orientation = quaternion.identity, Size = groundSize }); var groundCollider2 = BoxCollider.Create(new BoxGeometry { Orientation = quaternion.identity, Size = groundSize }); var instances = new NativeArray <CompoundCollider.ColliderBlobInstance>(2, Allocator.Temp); instances[0] = new CompoundCollider.ColliderBlobInstance { Collider = groundCollider1, CompoundFromChild = RigidTransform.identity }; instances[1] = new CompoundCollider.ColliderBlobInstance { Collider = groundCollider2, CompoundFromChild = RigidTransform.identity }; return(CompoundCollider.Create(instances)); }
private void SetCollider() { colliders = GetComponents <ICollidable>().ToList(); if (colliders.Count <= 0) { return; } if (colliders.Count == 1) { collider = colliders[0]; } else { collider = new CompoundCollider(colliders); } // Calculate Static Parameters for every collider colliders.ForEach(collider => SetUpCollider(collider)); if (collider is CompoundCollider) { SetUpCollider(collider); } // Set Static Parameters for the physics body mass = isKinematic ? Mathf.Infinity : collider.mass; momentOfInertia = isKinematic ? Mathf.Infinity : collider.momentOfInertia; // OnCollision Events Setup collider.onCollision += ICollidable_OnCollision; collider.onTrigger += ICollidable_OnTrigger; }
/// <summary> /// creates and returns the pokemoon's PhysicsCollider /// </summary> /// <param name="pokemonName">Name of the pokemon</param> /// <returns>PhysicsCollider</returns> public static PhysicsCollider getPokemonPhysicsCollider(string pokemonName, PokemonEntityData ped, CollisionFilter collisionFilter = new CollisionFilter(), float scale = 1f, Unity.Physics.Material material = new Unity.Physics.Material(), int groupIndex = 1) { ///FUTURE UPDATE ///allow specific colliders to recieve specific filters and materials! //needs collision groups PhysicsCollider physicsCollider = new PhysicsCollider { }; Quaternion rotation = new quaternion(); //if default collision filter is detected then create one realted to the pokemon if (collisionFilter.Equals(new CollisionFilter())) { Debug.Log("Creating new Collision Filter"); collisionFilter = new CollisionFilter { BelongsTo = TriggerEventClass.Pokemon | TriggerEventClass.Collidable, CollidesWith = TriggerEventClass.Collidable, GroupIndex = groupIndex }; } if (material.Equals(new Unity.Physics.Material())) { material = GetPokemonColliderMaterial(StringToPokedexEntry(pokemonName)); } switch (pokemonName) { case "Cubone": var colliders = new NativeArray <CompoundCollider.ColliderBlobInstance>(5, Allocator.Temp); colliders[0] = new CompoundCollider.ColliderBlobInstance { Collider = Unity.Physics.SphereCollider.Create(new SphereGeometry { Center = new float3(0, 0.27f, 0.03f), Radius = 0.225f }, collisionFilter, material), CompoundFromChild = new RigidTransform { pos = new float3 { x = 0, y = 0, z = 0 }, rot = quaternion.identity } }; var a = GenerateCapsuleData(float3.zero, Vector3.right, 0.1f, 0.3f); rotation.SetFromToRotation(Vector3.right, new Vector3(0, 90f, 0)); colliders[1] = new CompoundCollider.ColliderBlobInstance { Collider = Unity.Physics.CapsuleCollider.Create(new CapsuleGeometry { Vertex0 = a.pointA, Vertex1 = a.pointB, Radius = 0.1f }, collisionFilter, material), CompoundFromChild = new RigidTransform { pos = new float3(-0.17f, 0.19f, 0), rot = rotation } }; colliders[2] = new CompoundCollider.ColliderBlobInstance { Collider = Unity.Physics.CapsuleCollider.Create(new CapsuleGeometry { Vertex0 = a.pointA, Vertex1 = a.pointB, Radius = 0.1f }, collisionFilter, material), CompoundFromChild = new RigidTransform { pos = new float3(0.17f, 0.19f, 0), rot = rotation } }; colliders[3] = new CompoundCollider.ColliderBlobInstance { Collider = Unity.Physics.SphereCollider.Create(new SphereGeometry { Center = float3.zero, Radius = 0.23f }, collisionFilter, material), CompoundFromChild = new RigidTransform { pos = new float3(0, 0.75f, 0.03f), rot = rotation } }; a = GenerateCapsuleData(float3.zero, Vector3.right, 0.1f, 0.3f); rotation = Quaternion.Euler(0, 90f, 26f); colliders[4] = new CompoundCollider.ColliderBlobInstance { Collider = Unity.Physics.CapsuleCollider.Create(new CapsuleGeometry { Vertex0 = a.pointA, Vertex1 = a.pointB, Radius = 0.1f }, collisionFilter, material), CompoundFromChild = new RigidTransform { pos = new float3(0, 0.63f, 0.33f), rot = rotation } }; physicsCollider = new PhysicsCollider { Value = CompoundCollider.Create(colliders) }; if (scale > 1f) { Debug.LogWarning("Cannot scale Cubone"); } colliders.Dispose(); break; case "Electrode": Debug.Log("Creating PHysicwsCollider for Electrode"); physicsCollider = new PhysicsCollider { Value = Unity.Physics.SphereCollider.Create(new SphereGeometry { Center = float3.zero, Radius = ped.Height / 2 * scale }, collisionFilter, material ) }; break; default: Debug.LogError("Failed to find collider for pokemon \"" + pokemonName + "\""); physicsCollider = new PhysicsCollider { Value = Unity.Physics.SphereCollider.Create(new SphereGeometry { Center = float3.zero, Radius = ped.Height / 2 * scale }, collisionFilter, material ) }; break; } // Debug.Log("Returning Physics Collide for \""+pokemonName+"\""); return(physicsCollider); }
private void ConvertCompoundColliders() { Profiler.BeginSample("ConvertCompoundColliders"); m_nativeColliders = new NativeList <Collider>(128, Allocator.TempJob); m_nativeTransforms = new NativeList <RigidTransform>(128, Allocator.TempJob); m_compoundRanges = new NativeList <int2>(128, Allocator.TempJob); //Step 1: Find all colliders and construct parallel arrays m_authorings.Clear(); Entities.WithNone <DontConvertColliderTag>().ForEach((LatiosColliderAuthoring colliderAuthoring) => { //Do stuff if (colliderAuthoring.colliderType == AuthoringColliderTypes.None) { return; } if (colliderAuthoring.generateFromChildren) { m_unityColliders.Clear(); colliderAuthoring.GetComponentsInChildren(m_unityColliders); try { CreateChildrenColliders(colliderAuthoring, m_unityColliders, m_nativeColliders, m_nativeTransforms, m_compoundRanges); } catch (Exception e) { DisposeAndThrow(e); } } else { try { CreateChildrenColliders(colliderAuthoring, colliderAuthoring.colliders, m_nativeColliders, m_nativeTransforms, m_compoundRanges); } catch (Exception e) { DisposeAndThrow(e); } } m_authorings.Add(colliderAuthoring); }); if (m_authorings.Count > 0) { using (var computationContext = new BlobAssetComputationContext <CompoundColliderComputationData, CompoundColliderBlob>(BlobAssetStore, 128, Allocator.Temp)) { //Step 2: Compute hashes var hashes = new NativeArray <ColliderTransformHashPair>(m_compoundRanges.Length, Allocator.TempJob); new ComputeCompoundHashesJob { colliders = m_nativeColliders, transforms = m_nativeTransforms, ranges = m_compoundRanges, hashes = hashes }.ScheduleParallel(m_compoundRanges.Length, 1, default).Complete(); //Step 3: Check hashes against computationContext to see if blobs need to be built for (int i = 0; i < m_authorings.Count; i++) { var hash = hashes.ReinterpretLoad <Hash128>(i); computationContext.AssociateBlobAssetWithUnityObject(hash, m_authorings[i].gameObject); if (computationContext.NeedToComputeBlobAsset(hash)) { computationContext.AddBlobAssetToCompute(hash, new CompoundColliderComputationData { hash = hash, index = i }); } } //Step 4: Dispatch builder job using (var computationData = computationContext.GetSettings(Allocator.TempJob)) { new ComputeCompoundBlobs { colliders = m_nativeColliders, transforms = m_nativeTransforms, ranges = m_compoundRanges, computationData = computationData }.ScheduleParallel(computationData.Length, 1, default).Complete(); foreach (var data in computationData) { computationContext.AddComputedBlobAsset(data.hash, data.blob); } } //Step 5: Build Collider component var index = 0; Entities.ForEach((LatiosColliderAuthoring colliderAuthoring) => { computationContext.GetBlobAsset(hashes.ReinterpretLoad <Hash128>(index++), out var blob); var targetEntity = GetPrimaryEntity(colliderAuthoring); float3 scale = colliderAuthoring.transform.lossyScale; if (scale.x != scale.y || scale.x != scale.z) { throw new InvalidOperationException( $"GameObject Conversion Error: Failed to convert {colliderAuthoring}. Only uniform scale is permitted on Compound colliders."); } Collider icdCompound = new CompoundCollider { compoundColliderBlob = blob, scale = scale.x }; DstEntityManager.AddComponentData(targetEntity, icdCompound); }); hashes.Dispose(); } } m_nativeColliders.Dispose(); m_nativeTransforms.Dispose(); m_compoundRanges.Dispose(); Profiler.EndSample(); }
private BlobAssetReference <Collider> CreateCollider(ColliderType type) { int numMeshes = type == ColliderType.Compound ? 2 : 1; ColliderMeshes = new Mesh[numMeshes]; BlobAssetReference <Collider> collider = default; switch (type) { case ColliderType.Sphere: collider = SphereCollider.Create(new SphereGeometry { Center = float3.zero, Radius = 0.5f }); break; case ColliderType.Triangle: collider = PolygonCollider.CreateTriangle(k_TriangleVertices[0], k_TriangleVertices[1], k_TriangleVertices[2]); break; case ColliderType.Quad: collider = PolygonCollider.CreateQuad(k_QuadVertices[0], k_QuadVertices[1], k_QuadVertices[2], k_QuadVertices[3]); break; case ColliderType.Box: collider = BoxCollider.Create(new BoxGeometry { Center = float3.zero, Orientation = quaternion.identity, Size = new float3(1.0f), BevelRadius = 0.0f }); break; case ColliderType.Capsule: collider = CapsuleCollider.Create(new CapsuleGeometry { Vertex0 = new float3(0, -0.5f, 0), Vertex1 = new float3(0, 0.5f, 0), Radius = 0.5f }); break; case ColliderType.Cylinder: // TODO: need someone to add throw new NotImplementedException(); case ColliderType.Convex: // Tetrahedron NativeArray <float3> points = new NativeArray <float3>(k_TetraherdonVertices, Allocator.TempJob); collider = ConvexCollider.Create(points, ConvexHullGenerationParameters.Default, CollisionFilter.Default); points.Dispose(); break; case ColliderType.Compound: var child1 = SphereCollider.Create(new SphereGeometry { Center = float3.zero, Radius = 0.5f }); ChildrenColliders.Add(child1); var child2 = BoxCollider.Create(new BoxGeometry { Center = float3.zero, Orientation = quaternion.identity, Size = new float3(1.0f), BevelRadius = 0.0f }); ChildrenColliders.Add(child2); NativeArray <ColliderBlobInstance> childrenBlobs = new NativeArray <ColliderBlobInstance>(2, Allocator.TempJob); childrenBlobs[0] = new ColliderBlobInstance { Collider = child1, CompoundFromChild = new RigidTransform { pos = new float3(0.5f, 0, 0), rot = quaternion.identity } }; childrenBlobs[1] = new ColliderBlobInstance { Collider = child2, CompoundFromChild = new RigidTransform { pos = new float3(-0.5f, 0, 0), rot = quaternion.identity } }; ColliderMeshes[0] = SceneCreationUtilities.CreateMeshFromCollider(child1); ColliderMeshes[1] = SceneCreationUtilities.CreateMeshFromCollider(child2); collider = CompoundCollider.Create(childrenBlobs); childrenBlobs.Dispose(); break; case ColliderType.Mesh: // Tetrahedron mesh NativeArray <float3> meshVertices = new NativeArray <float3>(k_TetraherdonVertices, Allocator.TempJob); NativeArray <int3> meshTriangles = new NativeArray <int3>(k_TetrahedronMeshTriangles, Allocator.TempJob); collider = MeshCollider.Create(meshVertices, meshTriangles); meshVertices.Dispose(); meshTriangles.Dispose(); break; case ColliderType.Terrain: int2 size = 2; float3 scale = 1; Random rand = new Random(0x9739); int numSamples = size.x * size.y; var heights = new NativeArray <float>(numSamples, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); for (int i = 0; i < numSamples; i++) { heights[i] = rand.NextFloat(0, 1); } collider = TerrainCollider.Create(heights, size, scale, TerrainCollider.CollisionMethod.VertexSamples); heights.Dispose(); break; default: throw new System.NotImplementedException(); } if (ColliderType != ColliderType.Compound) { ColliderMeshes[0] = SceneCreationUtilities.CreateMeshFromCollider(collider); } return(collider); }
// 生成されたジョイントエンティティを返す。 public NativeArray <Entity> Convert (EntityManager em, Entity posturePrefab, NameAndEntity[] bonePrefabs) { //var motionClip = this.GetComponent<MotionAuthoring>().MotionClip;// var rbTop = this.GetComponentInChildren <Rigidbody>();// if (rbTop == null) { return(new NativeArray <Entity>()); // } var srcColliders = this.GetComponentsInChildren <UnityEngine.Collider>(); // 名前とボーンエンティティの組を配列化 //var qNameAndBone = motionClip.StreamPaths // .Select( x => System.IO.Path.GetFileName( x ) ) // .Select( ( name, i ) => (name, i: motionClip.IndexMapFbxToMotion[ i ]) ) // .Where( x => x.i != -1 ) // .Select( x => (Name:x.name, Entity:bonePrefabs[ x.i ].Entity) ) // .Append( (Name:rbTop.name, Entity:posturePrefab) ); //var namesAndBones = qNameAndBone.ToArray(); var namesAndBones = bonePrefabs .Append(new NameAndEntity(rbTop.name, posturePrefab)); // クエリ用コライダの生成 // ・マテリアルが "xxx overlap collider" という名前になっているものを抽出 // ・対応するボーンエンティティに専用のコンポーネントデータを付加 var qQueryableCollider = from x in srcColliders where x.sharedMaterial != null where x.sharedMaterial.name.StartsWith("overlap ") join bone in namesAndBones on x.name equals bone.Name select(bone.Entity, c : x) ; foreach (var(ent, c) in qQueryableCollider) { addQuearyableColliderBlobs_(ent, c, 0); } // コライダとそれが付くべき剛体の組を配列化(同じ剛体に複数のコライダもあり) // ・有効でないコライダは除外する var qColliderWithParent = from collider in srcColliders where collider.enabled let parent = collider.gameObject .AncestorsAndSelf() .Where(anc => anc.GetComponent <Rigidbody>() != null) .First() select(collider, parent) ; var collidersWithParent = qColliderWithParent.ToArray(); // 同じ剛体を親とするコライダをグループ化するクエリ var qColliderGroup = from x in collidersWithParent group x.collider by x.parent ; // 剛体を持たない子コライダを合成して、コライダコンポーネントデータを生成するクエリ var qCompounds = from g in qColliderGroup select new PhysicsCollider { Value = createBlobCollider_(srcColliders_: g, parent: g.Key, groupIndex: 0), }; // コライダがついているオブジェクトに相当するボーンのエンティティに、コライダコンポーネントデータを付加 // ・コライダ不要なら、質量プロパティだけ生成してコライダはつけないようにしたい(未実装) var qEntAndComponent = from c in (qColliderGroup, qCompounds).Zip() join b in namesAndBones on c.x.Key.name equals b.Name select(b.Entity, c : c.y) ; foreach (var(ent, c) in qEntAndComponent) { em.AddComponentData(ent, c); } // 剛体がついているオブジェクトに相当するボーンのエンティティに、各種コンポーネントデータを付加 // ・キネマティックは質量ゼロにするが、速度や質量プロパティは付加する。 // ・コライダがない場合は、球の質量プロパティになる。 var qRbAndBone = from x in this.GetComponentsInChildren <Rigidbody>() join b in namesAndBones on x.name equals b.Name select(rb : x, b.Entity) ; foreach (var(rb, ent) in qRbAndBone) { addDynamicComponentData_ByRigidbody_(ent, rb, posturePrefab); } //return new NativeArray<Entity>(0,Allocator.Temp); // ジョイントの生成。両端のオブジェクトに相当するエンティティを特定する。 // ・ジョイントはエンティティとして生成する。 // (コライダと同じエンティティに着けても動作したが、サンプルではこうしている) // (また、ラグドールジョイントはなぜか2つジョイントを返してくるので、同じエンティティには付けられない) var qJoint = from j in this.GetComponentsInChildren <UnityEngine.Joint>() //.Do( x=>Debug.Log(x.name)) join a in namesAndBones on j.name equals a.Name join b in namesAndBones on j.connectedBody.name equals b.Name let jointData = createJointBlob_(j) //select (a, b, j, jointData) select addJointComponentData_(a.Entity, jointData, a.Entity, b.Entity, j.enableCollision) ; return(qJoint.SelectMany().ToNativeArray(Allocator.Temp)); // 物理材質に着けられた名前から、特定のコライダを持つコンポーネントデータを生成する。 void addQuearyableColliderBlobs_ (Entity ent, UnityEngine.Collider srcCollider, int groupIndex) { switch (srcCollider.sharedMaterial.name) { //case "overlap cast":汎用だと1つしかもてない、用途ごとにコンポーネントデータを定義しないといけない //{ // var blob = createBlobCollider_( new[] { srcCollider }, srcCollider.gameObject, groupIndex ); // em.AddComponentData( ent, new GroundHitColliderData { Collider = blob } ); // break; //} case "overlap ground ray": { if (srcCollider is UnityEngine.SphereCollider srcSphere) { em.AddComponentData(ent, new GroundHitRayData { Start = srcSphere.center, Ray = new DirectionAndLength { value = new float4(math.up() * -1, srcSphere.radius) }, // 向きは暫定 Filter = LegacyColliderProducer.GetFilter(srcSphere, groupIndex), }); } break; } case "overlap ground sphere": { if (srcCollider is UnityEngine.SphereCollider srcSphere) { em.AddComponentData(ent, new GroundHitSphereData { Center = srcSphere.center, Distance = srcSphere.radius, Filter = LegacyColliderProducer.GetFilter(srcSphere, groupIndex), }); } break; } } } BlobAssetReference <Collider> compoundColliderBlobsFromEnumerable_ (IEnumerable <CompoundCollider.ColliderBlobInstance> src) { using (var arr = src.ToNativeArray(Allocator.Temp)) return(CompoundCollider.Create(arr)); } BlobAssetReference <Collider> createBlobCollider_ (IEnumerable <UnityEngine.Collider> srcColliders_, GameObject parent, int groupIndex) { return((srcColliders_.Count() > 1 || srcColliders_.First().gameObject != parent) ? queryBlobInstances_(srcColliders_, parent.transform, groupIndex) .To(compoundColliderBlobsFromEnumerable_) : createColliderBlob_(srcColliders_.First(), groupIndex) ); IEnumerable <CompoundCollider.ColliderBlobInstance> queryBlobInstances_ (IEnumerable <UnityEngine.Collider> srcColliders__, Transform tfParent, int groupIndex_) { return (from x in srcColliders__ let tfCollider = x.transform let rtf = new RigidTransform { pos = tfCollider.position - tfParent.position, rot = tfCollider.rotation * Quaternion.Inverse(tfParent.rotation), } select new CompoundCollider.ColliderBlobInstance { Collider = createColliderBlob_(x, groupIndex_), CompoundFromChild = rtf, }); } } BlobAssetReference <Collider> createColliderBlob_(UnityEngine.Collider srcCollider, int groupIndex) { switch (srcCollider) { case UnityEngine.SphereCollider srcSphere: return(srcSphere.ProduceColliderBlob(groupIndex)); case UnityEngine.CapsuleCollider srcCapsule: return(srcCapsule.ProduceColliderBlob(groupIndex)); case UnityEngine.BoxCollider srcBox: return(srcBox.ProduceColliderBlob(groupIndex)); } return(BlobAssetReference <Collider> .Null); } void addDynamicComponentData_ByRigidbody_(Entity ent, Rigidbody rb, Entity postureEnt) { var massProp = em.HasComponent <PhysicsCollider>(ent) ? em.GetComponentData <PhysicsCollider>(ent).MassProperties : MassProperties.UnitSphere; var physicsMass = rb.isKinematic ? PhysicsMass.CreateKinematic(massProp) : PhysicsMass.CreateDynamic(massProp, rb.mass); // XY回転拘束だけ特例で設定する var freez_xy = RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationZ; if (rb.constraints == freez_xy) { physicsMass.InverseInertia = new float3(0, 1, 0); } //if( !rb.isKinematic ) em.AddComponentData(ent, physicsMass); // キネマティックの場合は、つけなくても大丈夫みたい(主にジョイントにとって) // が、いちおうつけておく //if( !rb.isKinematic ) em.AddComponentData(ent, new PhysicsVelocity()); // ジョイント付けると、質量ゼロにしても速度が必要みたい(ないと荒ぶる) // もしくは、コライダがあると安定したように見えた if (rb.isKinematic || !rb.useGravity) { em.AddComponentData(ent, new PhysicsGravityFactor { Value = 0.0f }); } // 質量ゼロにしても、なぜか重力の影響を受け続けるのでオフる //if( !rb.isKinematic ) { em.AddComponentData(ent, new Bone.InitializeData { PostureEntity = postureEnt }); em.SetComponentData(ent, new Translation { Value = rb.position }); em.SetComponentData(ent, new Rotation { Value = rb.rotation }); } } BlobAssetReference <JointData>[] createJointBlob_(UnityEngine.Joint srcJoint) { switch (srcJoint) { //case UnityEngine.CharacterJoint srcChJoint when srcChJoint.GetComponent<RagdollJointAuthoring>() != null: //{ // var srcRagdollJoint = srcChJoint.GetComponent<RagdollJointAuthoring>(); // JointData.CreateRagdoll // ( // srcRagdollJoint.positionAinA, // srcRagdollJoint.positionBinB, // srcRagdollJoint.twistAxisInA, // srcRagdollJoint.twistAxisInB, // srcRagdollJoint.perpendicularAxisInA, // srcRagdollJoint.perpendicularAxisInB, // math.radians( srcRagdollJoint.maxConeAngle ), // math.radians( srcRagdollJoint.minPerpendicularAngle ), // math.radians( srcRagdollJoint.maxPerpendicularAngle ), // math.radians( srcRagdollJoint.minTwistAngle ), // math.radians( srcRagdollJoint.maxTwistAngle ), // out var jointData0, // out var jointData1 // ); // return new[] { jointData0, jointData1 }; //} case UnityEngine.CharacterJoint srcChJoint2: { var blob = JointData.CreateBallAndSocket(srcChJoint2.anchor, srcChJoint2.connectedAnchor); return(new[] { blob }); } } return(new BlobAssetReference <JointData>[] {}); } //unsafe Entity createJoint_ unsafe Entity[] addJointComponentData_( Entity jointEntity, BlobAssetReference <JointData>[] jointDataArray, Entity entityA, Entity entityB, bool isEnableCollision = false ) { return((from x in jointDataArray select createJointEntity_(x)).ToArray()); Entity createJointEntity_(BlobAssetReference <JointData> jd) { var ent = em.CreateEntity(typeof(Prefab), typeof(PhysicsJoint)); em.SetComponentData(ent, new PhysicsJoint { //JointData = jd, //EntityA = entityA, //EntityB = entityB, //EnableCollision = ( isEnableCollision ? 1 : 0 ) } ); return(ent); } } } }
public void Execute() => Output[0] = CompoundCollider.Create(Children);
public unsafe void CreateCompound_WithRepeatedInputs_ChildrenAreInstances() { BlobAssetReference <Collider> boxBlob = default; BlobAssetReference <Collider> capsuleBlob = default; BlobAssetReference <Collider> sphereBlob = default; BlobAssetReference <Collider> compoundBlob = default; try { // 3 unique instance inputs boxBlob = BoxCollider.Create(new BoxGeometry { Orientation = quaternion.identity, Size = new float3(1) }); capsuleBlob = CapsuleCollider.Create(new CapsuleGeometry { Radius = 0.5f, Vertex0 = new float3(1f), Vertex1 = new float3(-1f) }); sphereBlob = SphereCollider.Create(new SphereGeometry { Radius = 0.5f }); var children = new NativeArray <CompoundCollider.ColliderBlobInstance>(8, Allocator.Temp) { [0] = new CompoundCollider.ColliderBlobInstance { Collider = boxBlob, CompoundFromChild = new RigidTransform(quaternion.identity, new float3(0f)) }, [1] = new CompoundCollider.ColliderBlobInstance { Collider = capsuleBlob, CompoundFromChild = new RigidTransform(quaternion.identity, new float3(1f)) }, [2] = new CompoundCollider.ColliderBlobInstance { Collider = boxBlob, CompoundFromChild = new RigidTransform(quaternion.identity, new float3(2f)) }, [3] = new CompoundCollider.ColliderBlobInstance { Collider = sphereBlob, CompoundFromChild = new RigidTransform(quaternion.identity, new float3(3f)) }, [4] = new CompoundCollider.ColliderBlobInstance { Collider = boxBlob, CompoundFromChild = new RigidTransform(quaternion.identity, new float3(4f)) }, [5] = new CompoundCollider.ColliderBlobInstance { Collider = capsuleBlob, CompoundFromChild = new RigidTransform(quaternion.identity, new float3(5f)) }, [6] = new CompoundCollider.ColliderBlobInstance { Collider = boxBlob, CompoundFromChild = new RigidTransform(quaternion.identity, new float3(6f)) }, [7] = new CompoundCollider.ColliderBlobInstance { Collider = sphereBlob, CompoundFromChild = new RigidTransform(quaternion.identity, new float3(7f)) } }; compoundBlob = CompoundCollider.Create(children); var compound = (CompoundCollider *)compoundBlob.GetUnsafePtr(); var uniqueChildren = new HashSet <long>(); for (var i = 0; i < compound->Children.Length; i++) { uniqueChildren.Add((long)compound->Children[i].Collider); } Assert.That(uniqueChildren.Count, Is.EqualTo(3)); } finally { boxBlob.Dispose(); capsuleBlob.Dispose(); sphereBlob.Dispose(); if (compoundBlob.IsCreated) { compoundBlob.Dispose(); } } }
protected override void OnUpdate() { var shapeQuery = EntityManager.CreateEntityQuery(ComponentType.ReadOnly <T>()); var shapeCount = shapeQuery.CalculateEntityCount(); // A map from entities to arrays of colliders m_ExtraColliders = new NativeMultiHashMap <ComparableEntity, LeafShapeData>(shapeCount, Allocator.Temp); // Lists to store input data for deferred convex and mesh jobs const int defaultPointsPerShape = 1024; m_ConvexColliderJobs = new NativeList <ConvertConvexColliderInput>(shapeCount, Allocator.TempJob); m_ConvexColliderPoints = new NativeList <float3>(shapeCount * defaultPointsPerShape, Allocator.TempJob); m_MeshColliderJobs = new NativeList <ConvertMeshColliderInput>(shapeCount, Allocator.TempJob); m_MeshColliderVertices = new NativeList <float3>(shapeCount * defaultPointsPerShape, Allocator.TempJob); m_MeshColliderIndices = new NativeList <int>(shapeCount * defaultPointsPerShape / 2, Allocator.TempJob); // First pass. // Convert all shape authoring components into colliders, and collect them for each primary body Entities.ForEach <T>(ConvertShape); // Second pass. // Produce all convex and mesh collider blobs in parallel const int arrayLength = 5; var convexColliders = new NativeArray <KeyValuePair <Entity, LeafShapeData> >(m_ConvexColliderJobs.Length, Allocator.TempJob); var convexJob = new ProduceConvexCollidersJob { InputParameters = m_ConvexColliderJobs, AllPoints = m_ConvexColliderPoints, Output = convexColliders }.Schedule(m_ConvexColliderJobs.Length, arrayLength); var meshColliders = new NativeArray <KeyValuePair <Entity, LeafShapeData> >(m_MeshColliderJobs.Length, Allocator.TempJob); var meshJob = new ProduceMeshCollidersJob { InputParameters = m_MeshColliderJobs, AllVertices = m_MeshColliderVertices, AllIndices = m_MeshColliderIndices, Output = meshColliders }.Schedule(m_MeshColliderJobs.Length, arrayLength); JobHandle.CombineDependencies(convexJob, meshJob).Complete(); AppendLeafShapeDataToShapeMap(convexColliders, m_ExtraColliders, m_ConvexShapes); convexColliders.Dispose(); AppendLeafShapeDataToShapeMap(meshColliders, m_ExtraColliders, m_MeshShapes); meshColliders.Dispose(); // Final pass. // Assign PhysicsCollider components to rigid bodies, merging multiples into compounds as needed var keys = m_ExtraColliders.GetUniqueKeyArray(Allocator.Temp); using (keys.Item1) { for (var k = 0; k < keys.Item2; ++k) { ComparableEntity body = keys.Item1[k]; var collider = DstEntityManager.HasComponent <PhysicsCollider>(body.Entity) ? DstEntityManager.GetComponentData <PhysicsCollider>(body.Entity) : new PhysicsCollider(); var children = new NativeList <CompoundCollider.ColliderBlobInstance>(16, Allocator.Temp); // collect any existing valid shapes if (collider.IsValid) { ColliderType colliderType; unsafe { colliderType = collider.ColliderPtr->Type; } // if there is already a compound, add its leaves to the list of children if (colliderType == ColliderType.Compound) { unsafe { var existingChildren = ((CompoundCollider *)collider.ColliderPtr)->Children; for (int i = 0, count = existingChildren.Length; i < count; ++i) { children.Add(new CompoundCollider.ColliderBlobInstance { Collider = BlobAssetReference <Collider> .Create( existingChildren[i].Collider, existingChildren[i].Collider->MemorySize ), CompoundFromChild = existingChildren[i].CompoundFromChild }); } } } // otherwise add the single collider to the list of children else { children.Add( new CompoundCollider.ColliderBlobInstance { Collider = collider.Value, CompoundFromChild = RigidTransform.identity } ); } } // if collider is already valid, a shape already existed from another system var isSingleShapeOnPrimaryBody = !collider.IsValid; // collect all children found by this system if (m_ExtraColliders.TryGetFirstValue(body, out var child, out var iterator)) { do { children.Add(child.ColliderBlobInstance); isSingleShapeOnPrimaryBody &= child.LeafEntity.Equals(body.Entity); } while (m_ExtraColliders.TryGetNextValue(out child, ref iterator)); } // if there is a single shape on the primary body, use it as-is, otherwise create a compound // (assume a single leaf should still be a compound so that local offset values in authoring representation are retained) collider.Value = isSingleShapeOnPrimaryBody ? children[0].Collider : CompoundCollider.Create(children); children.Dispose(); DstEntityManager.AddOrSetComponent(body.Entity, collider); } } m_ConvexShapes.Clear(); m_ConvexColliderJobs.Dispose(); m_ConvexColliderPoints.Dispose(); m_MeshShapes.Clear(); m_MeshColliderJobs.Dispose(); m_MeshColliderVertices.Dispose(); m_MeshColliderIndices.Dispose(); }
public void RebuildCollision() { List <ChunkComponent> chunkList = new List <ChunkComponent>(); int colliderCount = 0; for (int x = 0; x < sizeX; x++) { for (int z = 0; z < sizeZ; z++) { for (int y = 0; y < sizeY; y++) { if (chunkComponents[x, y, z] != null || chunkComponents[x, y, z].chunk.getCollisionData() != null) { chunkList.Add(chunkComponents[x, y, z]); colliderCount += chunkComponents[x, y, z].chunk.getCollisionData().Count; } } } } BoxGeometry box = new BoxGeometry { Center = float3.zero, Orientation = quaternion.identity, Size = new float3(0.9f), BevelRadius = 0.0f }; Vector3 position = Vector3.zero; quaternion rotation = quaternion.identity; Chunk chunk = null; int colliderIndex = 0; NativeArray <CompoundCollider.ColliderBlobInstance> colliders = new NativeArray <CompoundCollider.ColliderBlobInstance>(colliderCount, Allocator.Temp); for (int i = 0; i < chunkList.Count; i++) { chunk = chunkList[i].chunk; for (int n = 0; n < chunk.getCollisionData().Count; n++) { float3 center = chunk.getCollisionData().centers[n] + (new Vector3(chunk.getX(), chunk.getY(), chunk.getZ()) * Constants.CHUNK_SIZE) + pivotPoint; box.Size = chunk.getCollisionData().sizes[n]; colliders[colliderIndex] = new CompoundCollider.ColliderBlobInstance { CompoundFromChild = new RigidTransform(quaternion.identity, center), Collider = Unity.Physics.BoxCollider.Create(box) }; colliderIndex++; } } BlobAssetReference <Unity.Physics.Collider> collider = CompoundCollider.Create(colliders); GameMaster.Instance.entityManager.SetComponentData(entity, new PhysicsCollider { Value = collider }); if (isStatic == false) { GameMaster.Instance.SetEntityMass(entity, collider, colliders.Length); } colliders.Dispose(); }