pafuhana1213 / KawaiiPhysics

KawaiiPhysics : Simple fake Physics for UnrealEngine4 & 5
MIT License
1.92k stars 287 forks source link

PlaneLimitに対し、初期位置でPlaneに潜っていたときや、高速移動で潜ってしまったときは潜りっぱなしになる #29

Closed monguri closed 1 year ago

monguri commented 3 years ago

仕様に関する質問です。 AnimBP_ChainKawaiiPhysicsCollision2を見ると、チェインが何も動いてなければ先の方のチェインはPlaneLimitに潜りっぱなしになります。

これは、FAnimNode_KawaiiPhysics::AdjustByPlanerCollisionにおいて、 FMath::SegmentPlaneIntersection(Bone.Location, Bone.PrevLocation, Planar.Plane, IntersectionPoint) がtrueを返すときのみ押し出し処理をするというところから来ている挙動だと思います。

これは仕様として想定している挙動かどうかを伺いたいです。 ゲーム用途ですと何かのきっかけで潜ってしまっても押し出してほしいケースが多いと思いますし、 もし仮にPlaneを片面押し出しでなく両面に対して隔てる壁と捉えていれば、GetUpVector()の方向だけでなく、 逆方向にも押し出し処理がほしい感じはします。 ただ、現在の挙動の方が、KawaiiPhysicsSampleマップのようにチェインが左右に引っ張られるケースでは、潜っていたチェインがすべていきなり1フレームで飛び出すのでなく、PlaneLimitと交差したもののみ押し出されるので、急激に動くことがないというメリットはあると感じます。 なので、仕様であっても問題はなく、今回は確認させていただきたかっただけとなります。

monguri commented 3 years ago

潜っていたら常に押し出すパッチを書いてみました。 FAnimNode_KawaiiPhysics::AdjustByPlanerCollision()の

        float DistSquared = (Bone.Location - PointOnPlane).SizeSquared();

        FVector IntersectionPoint;
        if (DistSquared < Bone.PhysicsSettings.Radius * Bone.PhysicsSettings.Radius ||
            FMath::SegmentPlaneIntersection(Bone.Location, Bone.PrevLocation, Planar.Plane, IntersectionPoint))
        {
            Bone.Location = PointOnPlane + Planar.Rotation.GetUpVector() * Bone.PhysicsSettings.Radius;
            continue;
        }

の部分を

        float DotProduct = FVector::DotProduct(Bone.Location - PointOnPlane, Planar.Rotation.GetUpVector());
        if (DotProduct < Bone.PhysicsSettings.Radius)
        {
            Bone.Location = PointOnPlane + Planar.Rotation.GetUpVector() * Bone.PhysicsSettings.Radius;
            continue;
        }

で置き換えます