protected override unsafe void Start() { init(); // no gravity Entity *entities = stackalloc Entity[2]; entities[1] = Entity.Null; for (int i = 0; i < 1; i++) { CollisionFilter filter = new CollisionFilter { CollidesWith = (uint)(1 << i), BelongsTo = (uint)~(1 << (1 - i)) }; BlobAssetReference <Collider> collider = BoxCollider.Create( new BoxGeometry { Center = float3.zero, Orientation = quaternion.identity, Size = new float3(1.0f, 0.2f, 0.2f), BevelRadius = 0.0f }, filter, Material.Default); entities[i] = CreateDynamicBody(float3.zero, quaternion.identity, collider, float3.zero, new float3(0, 1 - i, 0), 1.0f); } var jointFrame = new BodyFrame { Axis = new float3(0, 1, 0), PerpendicularAxis = new float3(0, 0, 1) }; PhysicsJoint hingeData = PhysicsJoint.CreateLimitedHinge(jointFrame, jointFrame, new FloatRange(-math.PI, -0.2f)); CreateJoint(hingeData, entities[0], entities[1]); }
public static PhysicsJoint CreateKnee(GameObject upperLeg, GameObject lowerLeg) { float upperLegHeight = 2.0f * upperLeg.transform.localScale.y; float3 pivotUpperLeg = new float3(0, -upperLegHeight / 2.0f, 0); var lowerLegTransform = new RigidTransform(lowerLeg.transform.rotation, lowerLeg.transform.position); var upperLegTransform = new RigidTransform(upperLeg.transform.rotation, upperLeg.transform.position); float3 pivotLowerLeg = math.transform(math.inverse(lowerLegTransform), math.transform(upperLegTransform, pivotUpperLeg)); float3 axis = new float3(1, 0, 0); float3 perpendicular = new float3(0, 0, 1); var jointFrameUpperLeg = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotUpperLeg }; var jointFrameLowerLeg = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotLowerLeg }; return(PhysicsJoint.CreateLimitedHinge(jointFrameUpperLeg, jointFrameLowerLeg, new FloatRange { Min = -1.2f })); }
public static PhysicsJoint CreateElbow(GameObject upperArm, GameObject lowerArm) { float upperArmLength = 2 * upperArm.transform.localScale.y; float lowerArmLength = 2 * lowerArm.transform.localScale.y; float sign = math.sign(-1.0f * upperArm.transform.position.x); float3 pivotUpper = new float3(-1.0f * sign * upperArmLength / 2.0f, 0, 0); float3 pivotLower = new float3(sign * lowerArmLength / 2.0f, 0, 0); pivotUpper = math.rotate(math.inverse(upperArm.transform.rotation), pivotUpper); pivotLower = math.rotate(math.inverse(lowerArm.transform.rotation), pivotLower); float3 axis = new float3(0, 0, 1); float3 perpendicular = new float3(0, 1, 0); var jointFrameUpperArm = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotUpper }; var jointFrameLowerArm = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotLower }; return(PhysicsJoint.CreateLimitedHinge(jointFrameUpperArm, jointFrameLowerArm, new FloatRange { Max = 3f })); }
public static PhysicsJoint CreateWrist(GameObject lowerArm, GameObject hand) { float armLength = 2.0f * lowerArm.transform.localScale.y; float handLength = 2.0f * hand.transform.localScale.y; float sign = math.sign(-1.0f * lowerArm.transform.position.x); float3 pivotFore = new float3(0, -1.0f * sign * armLength / 2.0f, 0); float3 pivotHand = new float3(0, sign * handLength / 2.0f, 0); float3 axis = new float3(0, 0, 1); float3 perpendicular = new float3(0, 1, 0); var jointFrameForearm = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotFore }; var jointFrameHand = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotHand }; return(PhysicsJoint.CreateLimitedHinge(jointFrameForearm, jointFrameHand, new FloatRange(-0.3f, 0.6f))); }
public static PhysicsJoint CreateAnkle(GameObject lowerLeg, GameObject foot) { float lowerLegLength = 2.0f * lowerLeg.transform.localScale.y; var lowerLegTransform = new RigidTransform(lowerLeg.transform.rotation, lowerLeg.transform.position); var footTransform = new RigidTransform(foot.transform.rotation, foot.transform.position); float3 pivotLowerLeg = new float3(0, -lowerLegLength / 2.0f, 0); float3 pivotFoot = math.transform(math.inverse(footTransform), math.transform(lowerLegTransform, pivotLowerLeg)); float3 axis = new float3(1, 0, 0); float3 perpendicular = new float3(0, 0, 1); var jointFrameLowerLeg = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotLowerLeg }; var jointFrameFoot = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotFoot }; return(PhysicsJoint.CreateLimitedHinge(jointFrameLowerLeg, jointFrameFoot, new FloatRange(-0.4f, 0.1f))); }
public override void Create(EntityManager entityManager, GameObjectConversionSystem conversionSystem) { UpdateAuto(); conversionSystem.World.GetOrCreateSystem <EndJointConversionSystem>().CreateJointEntity( this, GetConstrainedBodyPair(conversionSystem), PhysicsJoint.CreateLimitedHinge( new BodyFrame { Axis = math.normalize(HingeAxisLocal), PerpendicularAxis = math.normalize(PerpendicularAxisLocal), Position = PositionLocal }, new BodyFrame { Axis = math.normalize(HingeAxisInConnectedEntity), PerpendicularAxis = math.normalize(PerpendicularAxisInConnectedEntity), Position = PositionInConnectedEntity }, math.radians(new FloatRange(MinAngle, MaxAngle)) ) ); }
void ConvertHingeJoint(LegacyHinge joint) { RigidTransform worldFromBodyA = Math.DecomposeRigidBodyTransform(joint.transform.localToWorldMatrix); RigidTransform worldFromBodyB = joint.connectedBody == null ? RigidTransform.identity : Math.DecomposeRigidBodyTransform(joint.connectedBody.transform.localToWorldMatrix); Math.CalculatePerpendicularNormalized(joint.axis, out float3 perpendicularA, out _); var bodyAFromJoint = new BodyFrame { Axis = joint.axis, PerpendicularAxis = perpendicularA, Position = joint.anchor }; var connectedEntity = GetPrimaryEntity(joint.connectedBody); var isConnectedBodyConverted = joint.connectedBody == null || connectedEntity != Entity.Null; RigidTransform bFromA = isConnectedBodyConverted ? math.mul(math.inverse(worldFromBodyB), worldFromBodyA) : worldFromBodyA; RigidTransform bFromBSource = isConnectedBodyConverted ? RigidTransform.identity : worldFromBodyB; var bodyBFromJoint = new BodyFrame { Axis = math.mul(bFromA.rot, joint.axis), PerpendicularAxis = math.mul(bFromA.rot, perpendicularA), Position = math.mul(bFromBSource, new float4(joint.connectedAnchor, 1f)).xyz }; var limits = math.radians(new FloatRange(joint.limits.min, joint.limits.max).Sorted()); var jointData = joint.useLimits ? PhysicsJoint.CreateLimitedHinge(bodyAFromJoint, bodyBFromJoint, limits) : PhysicsJoint.CreateHinge(bodyAFromJoint, bodyBFromJoint); m_EndJointConversionSystem.CreateJointEntity(joint, GetConstrainedBodyPair(joint), jointData); }
public static PhysicsJoint CreateJoint(GameObject parentBody, GameObject childBody, BasicJointInfo.BasicJointType jointType) { var bodyPBounds = parentBody.GetComponent <MeshRenderer>().bounds; var bodyCBounds = childBody.GetComponent <MeshRenderer>().bounds; var pointConPWorld = bodyPBounds.ClosestPoint(bodyCBounds.center); var pointPonCWorld = bodyCBounds.ClosestPoint(bodyPBounds.center); var bodyPTransform = new RigidTransform(parentBody.transform.rotation, parentBody.transform.position); // was torso var bodyCTransform = new RigidTransform(childBody.transform.rotation, childBody.transform.position); // was head PhysicsJoint jointData = default; switch (jointType) { case BasicJointInfo.BasicJointType.BallAndSocket: { var pivotP = math.transform(math.inverse(bodyPTransform), pointConPWorld); var pivotC = math.transform(math.inverse(bodyCTransform), pointConPWorld); jointData = PhysicsJoint.CreateBallAndSocket(pivotP, pivotC); } break; case BasicJointInfo.BasicJointType.Distance: { var pivotP = math.transform(math.inverse(bodyPTransform), pointConPWorld); var pivotC = math.transform(math.inverse(bodyCTransform), pointPonCWorld); var range = new FloatRange(0, math.distance(pointConPWorld, pointPonCWorld)); jointData = PhysicsJoint.CreateLimitedDistance(pivotP, pivotC, range); } break; case BasicJointInfo.BasicJointType.Hinge: { var commonPivotPointWorld = math.lerp(pointConPWorld, pointPonCWorld, 0.5f); // assume a vertical hinge joint var axisP = math.rotate(math.inverse(bodyPTransform.rot), math.up()); var axisC = math.rotate(math.inverse(bodyCTransform.rot), math.up()); float3 perpendicularAxisA, perpendicularAxisB; Math.CalculatePerpendicularNormalized(axisP, out perpendicularAxisA, out _); Math.CalculatePerpendicularNormalized(axisC, out perpendicularAxisB, out _); var pivotP = math.transform(math.inverse(bodyPTransform), commonPivotPointWorld); var pivotC = math.transform(math.inverse(bodyCTransform), commonPivotPointWorld); var jointFrameP = new BodyFrame { Axis = axisP, PerpendicularAxis = perpendicularAxisA, Position = pivotP }; var jointFrameC = new BodyFrame { Axis = axisC, PerpendicularAxis = perpendicularAxisB, Position = pivotC }; var range = new FloatRange(math.radians(-90), math.radians(90.0f)); jointData = PhysicsJoint.CreateLimitedHinge(jointFrameP, jointFrameC, range); } break; default: break; } return(jointData); }
private void CreateRagdoll(Mesh torsoMesh, Mesh renderMesh, float3 positionOffset, quaternion rotationOffset, float3 initialVelocity, int ragdollIndex = 1, bool internalCollisions = false, float rangeGain = 1.0f) { var entities = new NativeList <Entity>(Allocator.Temp); var rangeModifier = new float2(math.max(0, math.min(rangeGain, 1))); // Head float headRadius = 0.1f; float3 headPosition = new float3(0, 1.8f, headRadius); Entity head; { CollisionFilter filter = internalCollisions ? layerFilter(layer.Head, layer.Torso) : groupFilter(-ragdollIndex); BlobAssetReference <Collider> headCollider = Unity.Physics.CapsuleCollider.Create(new CapsuleGeometry { Vertex0 = new float3(0, 0, 0), Vertex1 = new float3(0, 0, headRadius / 4), Radius = headRadius }, filter); CreatedColliders.Add(headCollider); head = CreateDynamicBody(headPosition, quaternion.identity, headCollider, float3.zero, float3.zero, 5.0f); } entities.Add(head); // Torso float3 torsoSize; float3 torsoPosition; Entity torso; { //UnityEngine.Mesh torsoMesh = (UnityEngine.Mesh)Resources.Load("torso", typeof(UnityEngine.Mesh)); torsoSize = torsoMesh.bounds.size; torsoPosition = headPosition - new float3(0, headRadius * 3.0f / 4.0f + torsoSize.y, 0); CollisionFilter filter = internalCollisions ? layerFilter(layer.Torso, layer.Thigh | layer.Head | layer.UpperArm | layer.Pelvis) : groupFilter(-ragdollIndex); NativeArray <float3> points = new NativeArray <float3>(torsoMesh.vertices.Length, Allocator.TempJob); for (int i = 0; i < torsoMesh.vertices.Length; i++) { points[i] = torsoMesh.vertices[i]; } BlobAssetReference <Collider> collider = ConvexCollider.Create( points, ConvexHullGenerationParameters.Default, CollisionFilter.Default ); CreatedColliders.Add(collider); points.Dispose(); collider.Value.Filter = filter; torso = CreateDynamicBody(torsoPosition, quaternion.identity, collider, float3.zero, float3.zero, 20.0f); } entities.Add(torso); // Neck { float3 pivotHead = new float3(0, -headRadius, 0); float3 pivotTorso = math.transform(math.inverse(GetBodyTransform(torso)), math.transform(GetBodyTransform(head), pivotHead)); float3 axisHead = new float3(0, 0, 1); float3 perpendicular = new float3(1, 0, 0); FloatRange coneAngle = new FloatRange(math.radians(0), math.radians(45)) * rangeModifier; FloatRange perpendicularAngle = new FloatRange(math.radians(-30), math.radians(+30)) * rangeModifier; FloatRange twistAngle = new FloatRange(math.radians(-5), math.radians(5)) * rangeModifier; var axisTorso = math.rotate(math.inverse(GetBodyTransform(torso).rot), math.rotate(GetBodyTransform(head).rot, axisHead)); axisTorso = math.rotate(quaternion.AxisAngle(perpendicular, math.radians(10)), axisTorso); var headFrame = new BodyFrame { Axis = axisHead, PerpendicularAxis = perpendicular, Position = pivotHead }; var torsoFrame = new BodyFrame { Axis = axisTorso, PerpendicularAxis = perpendicular, Position = pivotTorso }; PhysicsJoint.CreateRagdoll(headFrame, torsoFrame, coneAngle.Max, perpendicularAngle, twistAngle, out var ragdoll0, out var ragdoll1); CreateJoint(ragdoll0, head, torso); CreateJoint(ragdoll1, head, torso); } // Arms { float armLength = 0.25f; float armRadius = 0.05f; CollisionFilter armUpperFilter = internalCollisions ? layerFilter(layer.UpperArm, layer.Torso | layer.Forearm) : groupFilter(-ragdollIndex); CollisionFilter armLowerFilter = internalCollisions ? layerFilter(layer.Forearm, layer.UpperArm | layer.Hand) : groupFilter(-ragdollIndex); BlobAssetReference <Collider> upperArmCollider = Unity.Physics.CapsuleCollider.Create(new CapsuleGeometry { Vertex0 = new float3(-armLength / 2, 0, 0), Vertex1 = new float3(armLength / 2, 0, 0), Radius = armRadius }, armUpperFilter); BlobAssetReference <Collider> foreArmCollider = Unity.Physics.CapsuleCollider.Create(new CapsuleGeometry { Vertex0 = new float3(-armLength / 2, 0, 0), Vertex1 = new float3(armLength / 2, 0, 0), Radius = armRadius }, armLowerFilter); float handLength = 0.025f; float handRadius = 0.055f; CollisionFilter handFilter = internalCollisions ? layerFilter(layer.Hand, layer.Forearm) : groupFilter(-ragdollIndex); BlobAssetReference <Collider> handCollider = Unity.Physics.CapsuleCollider.Create(new CapsuleGeometry { Vertex0 = new float3(-handLength / 2, 0, 0), Vertex1 = new float3(handLength / 2, 0, 0), Radius = handRadius }, handFilter); CreatedColliders.Add(upperArmCollider); CreatedColliders.Add(foreArmCollider); CreatedColliders.Add(handCollider); for (int i = 0; i < 2; i++) { float s = i * 2 - 1.0f; float3 upperArmPosition = torsoPosition + new float3(s * (torsoSize.x + armLength) / 2.0f, 0.9f * torsoSize.y - armRadius, 0.0f); Entity upperArm = CreateDynamicBody(upperArmPosition, quaternion.identity, upperArmCollider, float3.zero, float3.zero, 10.0f); float3 foreArmPosition = upperArmPosition + new float3(armLength * s, 0, 0); Entity foreArm = CreateDynamicBody(foreArmPosition, quaternion.identity, foreArmCollider, float3.zero, float3.zero, 5.0f); float3 handPosition = foreArmPosition + new float3((armLength + handLength) / 2.0f * s, 0, 0); Entity hand = CreateDynamicBody(handPosition, quaternion.identity, handCollider, float3.zero, float3.zero, 2.0f); entities.Add(upperArm); entities.Add(foreArm); entities.Add(hand); // shoulder { float3 pivotArm = new float3(-s * armLength / 2.0f, 0, 0); float3 pivotTorso = math.transform(math.inverse(GetBodyTransform(torso)), math.transform(GetBodyTransform(upperArm), pivotArm)); float3 axisArm = new float3(-s, 0, 0); float3 perpendicularArm = new float3(0, 1, 0); FloatRange coneAngle = new FloatRange(math.radians(0), math.radians(80)) * rangeModifier; FloatRange perpendicularAngle = new FloatRange(math.radians(-70), math.radians(20)) * rangeModifier; FloatRange twistAngle = new FloatRange(math.radians(-5), math.radians(5)) * rangeModifier; var axisTorso = math.rotate(math.inverse(GetBodyTransform(torso).rot), math.rotate(GetBodyTransform(upperArm).rot, axisArm)); axisTorso = math.rotate(quaternion.AxisAngle(perpendicularArm, math.radians(-s * 45.0f)), axisTorso); var armFrame = new BodyFrame { Axis = axisArm, PerpendicularAxis = perpendicularArm, Position = pivotArm }; var bodyFrame = new BodyFrame { Axis = axisTorso, PerpendicularAxis = perpendicularArm, Position = pivotTorso }; PhysicsJoint.CreateRagdoll(armFrame, bodyFrame, coneAngle.Max, perpendicularAngle, twistAngle, out var ragdoll0, out var ragdoll1); CreateJoint(ragdoll0, upperArm, torso); CreateJoint(ragdoll1, upperArm, torso); } // elbow { float3 pivotUpper = new float3(s * armLength / 2.0f, 0, 0); float3 pivotFore = -pivotUpper; float3 axis = new float3(0, -s, 0); float3 perpendicular = new float3(-s, 0, 0); var lowerArmFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotFore }; var upperArmFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotUpper }; var hingeRange = new FloatRange(math.radians(0), math.radians(100)); hingeRange = (hingeRange - new float2(hingeRange.Mid)) * rangeModifier + hingeRange.Mid; PhysicsJoint hinge = PhysicsJoint.CreateLimitedHinge(lowerArmFrame, upperArmFrame, hingeRange); CreateJoint(hinge, foreArm, upperArm); } // wrist { float3 pivotFore = new float3(s * armLength / 2.0f, 0, 0); float3 pivotHand = new float3(-s * handLength / 2.0f, 0, 0); float3 axis = new float3(0, 0, -s); float3 perpendicular = new float3(0, 0, 1); var handFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotHand }; var forearmFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotFore }; var hingeRange = new FloatRange(math.radians(0), math.radians(135)) * rangeModifier; PhysicsJoint hinge = PhysicsJoint.CreateLimitedHinge(handFrame, forearmFrame, hingeRange); CreateJoint(hinge, hand, foreArm); } } } // Pelvis float pelvisRadius = 0.08f; float pelvisLength = 0.22f; float3 pelvisPosition = torsoPosition - new float3(0, pelvisRadius * 0.75f, 0.0f); Entity pelvis; { CollisionFilter filter = internalCollisions ? layerFilter(layer.Pelvis, layer.Torso | layer.Thigh) : groupFilter(-ragdollIndex); BlobAssetReference <Collider> collider = Unity.Physics.CapsuleCollider.Create(new CapsuleGeometry { Vertex0 = new float3(-pelvisLength / 2, 0, 0), Vertex1 = new float3(pelvisLength / 2, 0, 0), Radius = pelvisRadius }, filter); pelvis = CreateDynamicBody(pelvisPosition, quaternion.identity, collider, float3.zero, float3.zero, 15.0f); CreatedColliders.Add(collider); } entities.Add(pelvis); // Waist { float3 pivotTorso = float3.zero; float3 pivotPelvis = math.transform(math.inverse(GetBodyTransform(pelvis)), math.transform(GetBodyTransform(torso), pivotTorso)); float3 axis = new float3(0, 1, 0); float3 perpendicular = new float3(0, 0, 1); FloatRange coneAngle = new FloatRange(math.radians(0), math.radians(5)) * rangeModifier; FloatRange perpendicularAngle = new FloatRange(math.radians(-5), math.radians(90)) * rangeModifier; FloatRange twistAngle = new FloatRange(-math.radians(-5), math.radians(5)) * rangeModifier; var pelvisFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotPelvis }; var torsoFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotTorso }; PhysicsJoint.CreateRagdoll(pelvisFrame, torsoFrame, coneAngle.Max, perpendicularAngle, twistAngle, out var ragdoll0, out var ragdoll1); CreateJoint(ragdoll0, pelvis, torso); CreateJoint(ragdoll1, pelvis, torso); } // Legs { float thighLength = 0.32f; float thighRadius = 0.08f; CollisionFilter thighFilter = internalCollisions ? layerFilter(layer.Thigh, layer.Pelvis | layer.Calf) : groupFilter(-ragdollIndex); BlobAssetReference <Collider> thighCollider = Unity.Physics.CapsuleCollider.Create(new CapsuleGeometry { Vertex0 = new float3(0, -thighLength / 2, 0), Vertex1 = new float3(0, thighLength / 2, 0), Radius = thighRadius }, thighFilter); float calfLength = 0.32f; float calfRadius = 0.06f; CollisionFilter calfFilter = internalCollisions ? layerFilter(layer.Calf, layer.Thigh | layer.Foot) : groupFilter(-ragdollIndex); BlobAssetReference <Collider> calfCollider = Unity.Physics.CapsuleCollider.Create(new CapsuleGeometry { Vertex0 = new float3(0, -calfLength / 2, 0), Vertex1 = new float3(0, calfLength / 2, 0), Radius = calfRadius }, calfFilter); float footLength = 0.08f; float footRadius = 0.06f; CollisionFilter footFilter = internalCollisions ? layerFilter(layer.Foot, layer.Calf) : groupFilter(-ragdollIndex); BlobAssetReference <Collider> footCollider = Unity.Physics.CapsuleCollider.Create(new CapsuleGeometry { Vertex0 = new float3(0), Vertex1 = new float3(0, 0, footLength), Radius = footRadius }, footFilter); CreatedColliders.Add(thighCollider); CreatedColliders.Add(calfCollider); CreatedColliders.Add(footCollider); for (int i = 0; i < 2; i++) { float s = i * 2 - 1.0f; float3 thighPosition = pelvisPosition + new float3(s * pelvisLength / 2.0f, -thighLength / 2.0f, 0.0f); Entity thigh = CreateDynamicBody(thighPosition, quaternion.identity, thighCollider, float3.zero, float3.zero, 10.0f); float3 calfPosition = thighPosition + new float3(0, -(thighLength + calfLength) / 2.0f, 0); Entity calf = CreateDynamicBody(calfPosition, quaternion.identity, calfCollider, float3.zero, float3.zero, 5.0f); float3 footPosition = calfPosition + new float3(0, -calfLength / 2.0f, 0); Entity foot = CreateDynamicBody(footPosition, quaternion.identity, footCollider, float3.zero, float3.zero, 2.0f); entities.Add(thigh); entities.Add(calf); entities.Add(foot); // hip { float3 pivotThigh = new float3(0, thighLength / 2.0f, 0); float3 pivotPelvis = math.transform(math.inverse(GetBodyTransform(pelvis)), math.transform(GetBodyTransform(thigh), pivotThigh)); float3 axisLeg = new float3(0, -1, 0); float3 perpendicularLeg = new float3(-s, 0, 0); FloatRange coneAngle = new FloatRange(math.radians(0), math.radians(60)) * rangeModifier; FloatRange perpendicularAngle = new FloatRange(math.radians(-10), math.radians(40)) * rangeModifier; FloatRange twistAngle = new FloatRange(-math.radians(5), math.radians(5)) * rangeModifier; var axisPelvis = math.rotate(math.inverse(GetBodyTransform(pelvis).rot), math.rotate(GetBodyTransform(thigh).rot, axisLeg)); axisPelvis = math.rotate(quaternion.AxisAngle(perpendicularLeg, math.radians(s * 45.0f)), axisPelvis); var upperLegFrame = new BodyFrame { Axis = axisLeg, PerpendicularAxis = perpendicularLeg, Position = pivotThigh }; var pelvisFrame = new BodyFrame { Axis = axisPelvis, PerpendicularAxis = perpendicularLeg, Position = pivotPelvis }; PhysicsJoint.CreateRagdoll(upperLegFrame, pelvisFrame, coneAngle.Max, perpendicularAngle, twistAngle, out var ragdoll0, out var ragdoll1); CreateJoint(ragdoll0, thigh, pelvis); CreateJoint(ragdoll1, thigh, pelvis); } // knee { float3 pivotThigh = new float3(0, -thighLength / 2.0f, 0); float3 pivotCalf = math.transform(math.inverse(GetBodyTransform(calf)), math.transform(GetBodyTransform(thigh), pivotThigh)); float3 axis = new float3(-1, 0, 0); float3 perpendicular = new float3(0, 0, 1); var lowerLegFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotCalf }; var upperLegFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotThigh }; var hingeRange = new FloatRange(math.radians(-90), math.radians(0)); hingeRange = (hingeRange - new float2(hingeRange.Mid)) * rangeModifier + hingeRange.Mid; PhysicsJoint hinge = PhysicsJoint.CreateLimitedHinge(lowerLegFrame, upperLegFrame, hingeRange); CreateJoint(hinge, calf, thigh); } // ankle { float3 pivotCalf = new float3(0, -calfLength / 2.0f, 0); float3 pivotFoot = float3.zero; float3 axis = new float3(-1, 0, 0); float3 perpendicular = new float3(0, 0, 1); var footFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotFoot }; var lowerLegFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotCalf }; var hingeRange = new FloatRange(math.radians(-5), math.radians(5)) * rangeModifier; PhysicsJoint hinge = PhysicsJoint.CreateLimitedHinge(footFrame, lowerLegFrame, hingeRange); CreateJoint(hinge, foot, calf); } } } // reposition with offset information if (entities.Length > 0) { for (int i = 0; i < entities.Length; i++) { var e = entities[i]; bool isTorso = (i == 1); SwapRenderMesh(e, isTorso, torsoMesh, renderMesh); Translation positionComponent = EntityManager.GetComponentData <Translation>(e); Rotation rotationComponent = EntityManager.GetComponentData <Rotation>(e); PhysicsVelocity velocityComponent = EntityManager.GetComponentData <PhysicsVelocity>(e); float3 position = positionComponent.Value; quaternion rotation = rotationComponent.Value; float3 localPosition = position - pelvisPosition; localPosition = math.rotate(rotationOffset, localPosition); position = localPosition + pelvisPosition + positionOffset; rotation = math.mul(rotation, rotationOffset); positionComponent.Value = position; rotationComponent.Value = rotation; velocityComponent.Linear = initialVelocity; EntityManager.SetComponentData <PhysicsVelocity>(e, velocityComponent); EntityManager.SetComponentData <Translation>(e, positionComponent); EntityManager.SetComponentData <Rotation>(e, rotationComponent); } } }
private void CreateRagdoll(float3 positionOffset, quaternion rotationOffset, int ragdollIndex = 1, bool internalCollisions = false) { var entities = new NativeList <Entity>(Allocator.Temp); // Head float headRadius = 0.1f; float3 headPosition = new float3(0, 1.8f, 0); Entity head; { CollisionFilter filter = internalCollisions ? layerFilter(layer.Head, layer.Torso) : groupFilter(-ragdollIndex); BlobAssetReference <Unity.Physics.Collider> collider = Unity.Physics.SphereCollider.Create(new SphereGeometry { Center = float3.zero, Radius = headRadius }, filter); head = CreateDynamicBody(headPosition, quaternion.identity, collider, float3.zero, float3.zero, 5.0f); } entities.Add(head); // Torso float3 torsoSize; float3 torsoPosition; Entity torso; { //UnityEngine.Mesh torsoMesh = (UnityEngine.Mesh)Resources.Load("torso", typeof(UnityEngine.Mesh)); torsoSize = torsoMesh.bounds.size; torsoPosition = headPosition - new float3(0, headRadius * 3.0f / 4.0f + torsoSize.y, 0); CollisionFilter filter = internalCollisions ? layerFilter(layer.Torso, layer.Thigh | layer.Head | layer.UpperArm | layer.Pelvis) : groupFilter(-ragdollIndex); NativeArray <float3> points = new NativeArray <float3>(torsoMesh.vertices.Length, Allocator.TempJob); for (int i = 0; i < torsoMesh.vertices.Length; i++) { points[i] = torsoMesh.vertices[i]; } BlobAssetReference <Unity.Physics.Collider> collider = ConvexCollider.Create( points, ConvexHullGenerationParameters.Default, CollisionFilter.Default ); points.Dispose(); collider.Value.Filter = filter; torso = CreateDynamicBody(torsoPosition, quaternion.identity, collider, float3.zero, float3.zero, 20.0f); } entities.Add(torso); // Neck { float3 pivotHead = new float3(0, -headRadius, 0); float3 pivotBody = math.transform(math.inverse(GetBodyTransform(torso)), math.transform(GetBodyTransform(head), pivotHead)); float3 axis = new float3(0, 1, 0); float3 perpendicular = new float3(0, 0, 1); float coneAngle = (float)math.PI / 5.0f; var perpendicularAngle = new FloatRange { Max = math.PI }; // unlimited var twistAngle = new FloatRange(-math.PI / 3f, math.PI / 3f); var headFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotHead }; var bodyFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotBody }; PhysicsJoint.CreateRagdoll(headFrame, bodyFrame, coneAngle, perpendicularAngle, twistAngle, out var ragdoll0, out var ragdoll1); CreateJoint(ragdoll0, head, torso); CreateJoint(ragdoll1, head, torso); } // Arms { float armLength = 0.25f; float armRadius = 0.05f; CollisionFilter armUpperFilter = internalCollisions ? layerFilter(layer.UpperArm, layer.Torso | layer.Forearm) : groupFilter(-ragdollIndex); CollisionFilter armLowerFilter = internalCollisions ? layerFilter(layer.Forearm, layer.UpperArm | layer.Hand) : groupFilter(-ragdollIndex); BlobAssetReference <Unity.Physics.Collider> upperArmCollider = Unity.Physics.CapsuleCollider.Create(new CapsuleGeometry { Vertex0 = new float3(-armLength / 2, 0, 0), Vertex1 = new float3(armLength / 2, 0, 0), Radius = armRadius }, armUpperFilter); BlobAssetReference <Unity.Physics.Collider> foreArmCollider = Unity.Physics.CapsuleCollider.Create(new CapsuleGeometry { Vertex0 = new float3(-armLength / 2, 0, 0), Vertex1 = new float3(armLength / 2, 0, 0), Radius = armRadius }, armLowerFilter); float handLength = 0.025f; float handRadius = 0.055f; CollisionFilter handFilter = internalCollisions ? layerFilter(layer.Hand, layer.Forearm) : groupFilter(-ragdollIndex); BlobAssetReference <Unity.Physics.Collider> handCollider = Unity.Physics.CapsuleCollider.Create(new CapsuleGeometry { Vertex0 = new float3(-handLength / 2, 0, 0), Vertex1 = new float3(handLength / 2, 0, 0), Radius = handRadius }, handFilter); for (int i = 0; i < 2; i++) { float s = i * 2 - 1.0f; float3 upperArmPosition = torsoPosition + new float3(s * (torsoSize.x + armLength) / 2.0f, 0.9f * torsoSize.y - armRadius, 0.0f); Entity upperArm = CreateDynamicBody(upperArmPosition, quaternion.identity, upperArmCollider, float3.zero, float3.zero, 10.0f); float3 foreArmPosition = upperArmPosition + new float3(armLength * s, 0, 0); Entity foreArm = CreateDynamicBody(foreArmPosition, quaternion.identity, foreArmCollider, float3.zero, float3.zero, 5.0f); float3 handPosition = foreArmPosition + new float3((armLength + handLength) / 2.0f * s, 0, 0); Entity hand = CreateDynamicBody(handPosition, quaternion.identity, handCollider, float3.zero, float3.zero, 2.0f); entities.Add(upperArm); entities.Add(foreArm); entities.Add(hand); // shoulder { float3 pivotArm = new float3(-s * armLength / 2.0f, 0, 0); float3 pivotBody = math.transform(math.inverse(GetBodyTransform(torso)), math.transform(GetBodyTransform(upperArm), pivotArm)); float3 axis = new float3(s, 0, 0); float3 perpendicular = new float3(0, 0, 1); float coneAngle = (float)math.PI / 2.0f; var perpendicularAngle = new FloatRange { Max = math.PI / 2f }; var twistAngle = new FloatRange(-math.PI / 4f, math.PI / 4f); var armFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotArm }; var bodyFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotBody }; PhysicsJoint.CreateRagdoll(armFrame, bodyFrame, coneAngle, perpendicularAngle, twistAngle, out var ragdoll0, out var ragdoll1); CreateJoint(ragdoll0, upperArm, torso); CreateJoint(ragdoll1, upperArm, torso); } // elbow { float3 pivotUpper = new float3(s * armLength / 2.0f, 0, 0); float3 pivotFore = -pivotUpper; float3 axis = new float3(0, -s, 0); float3 perpendicular = new float3(s, 0, 0); var lowerArmFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotFore }; var upperArmFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotUpper }; PhysicsJoint hinge = PhysicsJoint.CreateLimitedHinge(lowerArmFrame, upperArmFrame, new FloatRange { Max = 3f }); CreateJoint(hinge, foreArm, upperArm); } // wrist { float3 pivotFore = new float3(s * armLength / 2.0f, 0, 0); float3 pivotHand = new float3(-s * handLength / 2.0f, 0, 0); float3 axis = new float3(0, -s, 0); float3 perpendicular = new float3(s, 0, 0); var handFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotHand }; var forearmFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotFore }; PhysicsJoint hinge = PhysicsJoint.CreateLimitedHinge(handFrame, forearmFrame, new FloatRange(-0.3f, 0.6f)); CreateJoint(hinge, hand, foreArm); } } } // Pelvis float pelvisRadius = 0.08f; float pelvisLength = 0.22f; float3 pelvisPosition = torsoPosition - new float3(0, pelvisRadius * 0.75f, 0.0f); Entity pelvis; { CollisionFilter filter = internalCollisions ? layerFilter(layer.Pelvis, layer.Torso | layer.Thigh) : groupFilter(-ragdollIndex); BlobAssetReference <Unity.Physics.Collider> collider = Unity.Physics.CapsuleCollider.Create(new CapsuleGeometry { Vertex0 = new float3(-pelvisLength / 2, 0, 0), Vertex1 = new float3(pelvisLength / 2, 0, 0), Radius = pelvisRadius }, filter); pelvis = CreateDynamicBody(pelvisPosition, quaternion.identity, collider, float3.zero, float3.zero, 15.0f); } entities.Add(pelvis); // Waist { float3 pivotTorso = float3.zero; float3 pivotPelvis = math.transform(math.inverse(GetBodyTransform(pelvis)), math.transform(GetBodyTransform(torso), pivotTorso)); float3 axis = new float3(0, -1, 0); float3 perpendicular = new float3(0, 0, 1); float coneAngle = 0.1f; var perpendicularAngle = new FloatRange(-0.1f, math.PI); var twistAngle = new FloatRange(-0.1f, 0.1f); var pelvisFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotPelvis }; var torsoFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotTorso }; PhysicsJoint.CreateRagdoll(pelvisFrame, torsoFrame, coneAngle, perpendicularAngle, twistAngle, out var ragdoll0, out var ragdoll1); CreateJoint(ragdoll0, pelvis, torso); CreateJoint(ragdoll1, pelvis, torso); } // Legs { float thighLength = 0.32f; float thighRadius = 0.08f; CollisionFilter thighFilter = internalCollisions ? layerFilter(layer.Thigh, layer.Pelvis | layer.Calf) : groupFilter(-ragdollIndex); BlobAssetReference <Unity.Physics.Collider> thighCollider = Unity.Physics.CapsuleCollider.Create(new CapsuleGeometry { Vertex0 = new float3(0, -thighLength / 2, 0), Vertex1 = new float3(0, thighLength / 2, 0), Radius = thighRadius }, thighFilter); float calfLength = 0.32f; float calfRadius = 0.06f; CollisionFilter calfFilter = internalCollisions ? layerFilter(layer.Calf, layer.Thigh | layer.Foot) : groupFilter(-ragdollIndex); BlobAssetReference <Unity.Physics.Collider> calfCollider = Unity.Physics.CapsuleCollider.Create(new CapsuleGeometry { Vertex0 = new float3(0, -calfLength / 2, 0), Vertex1 = new float3(0, calfLength / 2, 0), Radius = calfRadius }, calfFilter); float footLength = 0.08f; float footRadius = 0.06f; CollisionFilter footFilter = internalCollisions ? layerFilter(layer.Foot, layer.Calf) : groupFilter(-ragdollIndex); BlobAssetReference <Unity.Physics.Collider> footCollider = Unity.Physics.CapsuleCollider.Create(new CapsuleGeometry { Vertex0 = new float3(0), Vertex1 = new float3(0, 0, footLength), Radius = footRadius }, footFilter); for (int i = 0; i < 2; i++) { float s = i * 2 - 1.0f; float3 thighPosition = pelvisPosition + new float3(s * pelvisLength / 2.0f, -thighLength / 2.0f, 0.0f); Entity thigh = CreateDynamicBody(thighPosition, quaternion.identity, thighCollider, float3.zero, float3.zero, 10.0f); float3 calfPosition = thighPosition + new float3(0, -(thighLength + calfLength) / 2.0f, 0); Entity calf = CreateDynamicBody(calfPosition, quaternion.identity, calfCollider, float3.zero, float3.zero, 5.0f); float3 footPosition = calfPosition + new float3(0, -calfLength / 2.0f, 0); Entity foot = CreateDynamicBody(footPosition, quaternion.identity, footCollider, float3.zero, float3.zero, 2.0f); entities.Add(thigh); entities.Add(calf); entities.Add(foot); // hip { float3 pivotThigh = new float3(0, thighLength / 2.0f, 0); float3 pivotBody = math.transform(math.inverse(GetBodyTransform(torso)), math.transform(GetBodyTransform(thigh), pivotThigh)); float3 axis = new float3(0, -1, 0); float3 perpendicular = new float3(s, 0, 0); float coneAngle = (float)math.PI / 4.0f; var perpendicularAngle = new FloatRange { Max = 0.2f + math.PI / 2.0f }; var twistAngle = new FloatRange(-0.2f, 0.2f); var upperLegFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotThigh }; var bodyFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotBody }; PhysicsJoint.CreateRagdoll(upperLegFrame, bodyFrame, coneAngle, perpendicularAngle, twistAngle, out var ragdoll0, out var ragdoll1); CreateJoint(ragdoll0, thigh, torso); CreateJoint(ragdoll1, thigh, torso); } // knee { float3 pivotThigh = new float3(0, -thighLength / 2.0f, 0); float3 pivotCalf = math.transform(math.inverse(GetBodyTransform(calf)), math.transform(GetBodyTransform(thigh), pivotThigh)); float3 axis = new float3(-1, 0, 0); float3 perpendicular = new float3(0, 0, 1); var lowerLegFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotCalf }; var upperLegFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotThigh }; PhysicsJoint hinge = PhysicsJoint.CreateLimitedHinge(lowerLegFrame, upperLegFrame, new FloatRange { Min = -1.2f }); CreateJoint(hinge, calf, thigh); } // ankle { float3 pivotCalf = new float3(0, -calfLength / 2.0f, 0); float3 pivotFoot = float3.zero; float3 axis = new float3(-1, 0, 0); float3 perpendicular = new float3(0, 0, 1); var footFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotFoot }; var lowerLegFrame = new BodyFrame { Axis = axis, PerpendicularAxis = perpendicular, Position = pivotCalf }; PhysicsJoint hinge = PhysicsJoint.CreateLimitedHinge(footFrame, lowerLegFrame, new FloatRange(-0.4f, 0.1f)); CreateJoint(hinge, foot, calf); } } } var entityManager = BasePhysicsDemo.DefaultWorld.EntityManager; // reposition with offset information if (entities.Length > 0) { float3 center = float3.zero; for (int i = 0; i < entities.Length; i++) { var e = entities[i]; center += entityManager.GetComponentData <Translation>(e).Value; } center /= entities.Length; for (int i = 0; i < entities.Length; i++) { var e = entities[i]; Translation positionComponent = entityManager.GetComponentData <Translation>(e); Rotation rotationComponent = entityManager.GetComponentData <Rotation>(e); float3 position = positionComponent.Value; quaternion rotation = rotationComponent.Value; float3 localPosition = position - center; localPosition = math.rotate(rotationOffset, localPosition); position = localPosition + center + positionOffset; rotation = math.mul(rotation, rotationOffset); positionComponent.Value = position; rotationComponent.Value = rotation; entityManager.SetComponentData <Translation>(e, positionComponent); entityManager.SetComponentData <Rotation>(e, rotationComponent); } } }
public override void CreateScene(SoftJointDemoScene sceneSettings) { // Make soft ball and sockets { BlobAssetReference <Unity.Physics.Collider> collider = Unity.Physics.BoxCollider.Create(new BoxGeometry { Center = float3.zero, Orientation = quaternion.identity, Size = new float3(0.2f, 0.2f, 0.2f), BevelRadius = 0.0f }); CreatedColliders.Add(collider); // Make joints with different spring frequency. The leftmost joint should oscillate at 0.5hz, the next at 1hz, the next at 1.5hz, etc. for (int i = 0; i < 10; i++) { // Create a body float3 position = new float3((i - 4.5f) * 1.0f, 0, 0); float3 velocity = new float3(0, -10.0f, 0); Entity body = CreateDynamicBody( position, quaternion.identity, collider, velocity, float3.zero, 1.0f); // Create the ball and socket joint float3 pivotLocal = float3.zero; float3 pivotInWorld = math.transform(GetBodyTransform(body), pivotLocal); var jointData = PhysicsJoint.CreateBallAndSocket(pivotLocal, pivotInWorld); var constraints = jointData.GetConstraints(); var constraint = constraints[0]; // Choose a small damping value instead of 0 to improve stability of the joints constraint.SpringDamping = 0.05f; constraint.SpringFrequency = 0.5f * (float)(i + 1); constraints[0] = constraint; jointData.SetConstraints(constraints); CreateJoint(jointData, body, Entity.Null); } } //Make soft limited hinges { BlobAssetReference <Unity.Physics.Collider> collider = Unity.Physics.BoxCollider.Create(new BoxGeometry { Center = float3.zero, Orientation = quaternion.identity, Size = new float3(0.4f, 0.1f, 0.6f), BevelRadius = 0.0f }); CreatedColliders.Add(collider); // First row has soft limit with hard hinge + pivot, second row has everything soft for (int j = 0; j < 2; j++) { for (int i = 0; i < 10; i++) { // Create a body float3 position = new float3((i - 4.5f) * 1.0f, 0, (j + 1) * 3.0f); float3 velocity = new float3(0, -10.0f, 0); float3 angularVelocity = new float3(0, 0, -10.0f); Entity body = CreateDynamicBody( position, quaternion.identity, collider, velocity, angularVelocity, 1.0f); // Create the limited hinge joint float3 pivotLocal = new float3(0, 0, 0); float3 pivotInWorld = math.transform(GetBodyTransform(body), pivotLocal); float3 axisLocal = new float3(0, 0, 1); float3 axisInWorld = axisLocal; float3 perpendicularLocal = new float3(0, 1, 0); float3 perpendicularInWorld = perpendicularLocal; var frameLocal = new BodyFrame { Axis = axisLocal, PerpendicularAxis = perpendicularLocal, Position = pivotLocal }; var frameWorld = new BodyFrame { Axis = axisInWorld, PerpendicularAxis = perpendicularInWorld, Position = pivotInWorld }; var jointData = PhysicsJoint.CreateLimitedHinge(frameLocal, frameWorld, default); // First constraint is the limit, next two are the hinge and pivot var constraints = jointData.GetConstraints(); for (int k = 0; k < 1 + 2 * j; k++) { var constraint = constraints[k]; // Choose a small damping value instead of 0 to improve stability of the joints constraint.SpringDamping = 0.05f; constraint.SpringFrequency = 0.5f * (i + 1); constraints[k] = constraint; } jointData.SetConstraints(constraints); CreateJoint(jointData, body, Entity.Null); } } } // Make a soft prismatic { BlobAssetReference <Unity.Physics.Collider> collider = Unity.Physics.BoxCollider.Create(new BoxGeometry { Center = float3.zero, Orientation = quaternion.identity, Size = new float3(0.2f, 0.2f, 0.2f), BevelRadius = 0.0f }); CreatedColliders.Add(collider); // Create a body float3 position = new float3(0, 0, 9.0f); float3 velocity = new float3(50.0f, 0, 0); Entity body = CreateDynamicBody( position, quaternion.identity, collider, velocity, float3.zero, 1.0f); // Create the prismatic joint float3 pivotLocal = float3.zero; float3 pivotInWorld = math.transform(GetBodyTransform(body), pivotLocal); float3 axisLocal = new float3(1, 0, 0); float3 axisInWorld = axisLocal; float3 perpendicularLocal = new float3(0, 1, 0); float3 perpendicularInWorld = perpendicularLocal; var localFrame = new BodyFrame { Axis = axisLocal, PerpendicularAxis = perpendicularLocal, Position = pivotLocal }; var worldFrame = new BodyFrame { Axis = axisInWorld, PerpendicularAxis = perpendicularInWorld, Position = pivotInWorld }; var jointData = PhysicsJoint.CreatePrismatic(localFrame, worldFrame, new FloatRange(-2f, 2f)); var constraints = jointData.GetConstraints(); var constraint = constraints[0]; // Choose a small damping value instead of 0 to improve stability of the joints constraint.SpringDamping = 0.05f; constraint.SpringFrequency = 5.0f; constraints[0] = constraint; jointData.SetConstraints(constraints); CreateJoint(jointData, body, Entity.Null); } }