public override unsafe void Create(EntityManager entityManager) { if (AutoSetConnected) { PositionLocal = math.transform(math.inverse(worldFromA), math.transform(worldFromB, PositionInConnectedEntity)); } CreateJointEntity(JointData.CreateBallAndSocket(PositionLocal, PositionInConnectedEntity), entityManager); }
public override unsafe void Create(EntityManager entityManager) { if (autoSetConnected) { RigidTransform bFromA = math.mul(math.inverse(WorldFromB), WorldFromA); positionInConnectedEntity = math.transform(bFromA, positionLocal); } CreateJointEntity(JointData.CreateBallAndSocket(positionLocal, positionInConnectedEntity), entityManager); }
public override void Create(EntityManager entityManager, GameObjectConversionSystem conversionSystem) { if (AutoSetConnected) { RigidTransform bFromA = math.mul(math.inverse(worldFromB), worldFromA); PositionInConnectedEntity = math.transform(bFromA, PositionLocal); } CreateJointEntity(JointData.CreateBallAndSocket(PositionLocal, PositionInConnectedEntity), entityManager, conversionSystem); }
public void JointDataCreateBallAndSocketTest() { var positionAinA = float3.zero; var positionBinB = float3.zero; var jointDataRef = JointData.CreateBallAndSocket(positionAinA, positionBinB); var jointData = jointDataRef.Value; Assert.AreEqual(MTransform.Identity, jointData.AFromJoint); Assert.AreEqual(MTransform.Identity, jointData.BFromJoint); Assert.AreEqual(1, jointData.Version); Assert.AreEqual(1, jointData.NumConstraints); var constraint = jointDataRef.Value.Constraints[0]; Assert.AreEqual(new bool3(true), constraint.ConstrainedAxes); Assert.AreEqual(ConstraintType.Linear, constraint.Type); Assert.AreEqual(0.0f, constraint.Min); Assert.AreEqual(0.0f, constraint.Max); Assert.AreEqual(Constraint.DefaultSpringFrequency, constraint.SpringFrequency); Assert.AreEqual(Constraint.DefaultSpringDamping, constraint.SpringDamping); }
protected override void Start() { float3 gravity = float3.zero; base.init(gravity); // Enable the joint viewer SetDebugDisplay(new Unity.Physics.Authoring.PhysicsDebugDisplayData { DrawJoints = 1 }); // 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 }); // 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); BlobAssetReference <JointData> jointData; jointData = JointData.CreateBallAndSocket(pivotLocal, pivotInWorld); jointData.Value.Constraints[0].SpringDamping = 0.0f; jointData.Value.Constraints[0].SpringFrequency = 0.5f * (float)(i + 1); 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 }); // 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; BlobAssetReference <JointData> jointData; jointData = JointData.CreateLimitedHinge(pivotLocal, pivotInWorld, axisLocal, axisInWorld, perpendicularLocal, perpendicularInWorld, 0.0f, 0.0f); // First constraint is the limit, next two are the hinge and pivot for (int k = 0; k < 1 + 2 * j; k++) { jointData.Value.Constraints[k].SpringDamping = 0.0f; jointData.Value.Constraints[k].SpringFrequency = 0.5f * (float)(i + 1); } 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 }); // 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; BlobAssetReference <JointData> jointData; jointData = JointData.CreatePrismatic(pivotLocal, pivotInWorld, axisLocal, axisInWorld, perpendicularLocal, perpendicularInWorld, -2.0f, 2.0f, 0.0f, 0.0f); jointData.Value.Constraints[0].SpringDamping = 0.0f; jointData.Value.Constraints[0].SpringFrequency = 5.0f; CreateJoint(jointData, body, Entity.Null); } }
protected override void Start() { base.Start(); // Enable the joint viewer SetDebugDisplay(new Unity.Physics.Authoring.PhysicsDebugDisplayData { DrawJoints = 1 }); BlobAssetReference <Unity.Physics.Collider> collider = Unity.Physics.BoxCollider.Create(new BoxGeometry { Center = float3.zero, Orientation = quaternion.identity, Size = new float3(0.25f), BevelRadius = 0.0f }); var manager = DefaultWorld.EntityManager; // Add a dynamic body constrained to the world that will die // Once the dynamic body is destroyed the joint will be invalid { // Create a dynamic body float3 pivotWorld = new float3(-2f, 0, 0); Entity body = CreateDynamicBody(pivotWorld, quaternion.identity, collider, float3.zero, float3.zero, 1.0f); // add timeout on dynamic body after 15 frames. manager.AddComponentData <EntityKiller>(body, new EntityKiller() { TimeToDie = 15 }); // Create the joint float3 pivotLocal = float3.zero; BlobAssetReference <JointData> jointData = JointData.CreateBallAndSocket(pivotLocal, pivotWorld); var jointEntity = CreateJoint(jointData, body, Entity.Null); // add timeout on joint entity after 30 frames. manager.AddComponentData <EntityKiller>(jointEntity, new EntityKiller() { TimeToDie = 30 }); } // Add two static bodies constrained together // The joint is invalid immediately { // Create a body Entity bodyA = CreateStaticBody(new float3(0, 0.0f, 0), quaternion.identity, collider); Entity bodyB = CreateStaticBody(new float3(0, 1.0f, 0), quaternion.identity, collider); // Create the joint float3 pivotLocal = float3.zero; BlobAssetReference <JointData> jointData = JointData.CreateBallAndSocket(pivotLocal, pivotLocal); var jointEntity = CreateJoint(jointData, bodyA, bodyB); // add timeout on joint entity after 15 frames. manager.AddComponentData <EntityKiller>(jointEntity, new EntityKiller() { TimeToDie = 15 }); } }
// 生成されたジョイントエンティティを返す。 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); } } } }