Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 3
0
        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);
        }
Ejemplo n.º 4
0
        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);
        }
    }
Ejemplo n.º 6
0
    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
            });
        }
    }
Ejemplo n.º 7
0
        // 生成されたジョイントエンティティを返す。
        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);
                }
            }
        }
    }