From ef739e3c4d66007fb9c2ced195edb539eb92f3a4 Mon Sep 17 00:00:00 2001 From: chai Date: Tue, 3 Nov 2020 19:05:55 +0800 Subject: *misc --- Assets/Scripts/Physics/PhysicsWorld.cs | 183 ++++++++++++++++++++------------- 1 file changed, 111 insertions(+), 72 deletions(-) (limited to 'Assets/Scripts/Physics/PhysicsWorld.cs') diff --git a/Assets/Scripts/Physics/PhysicsWorld.cs b/Assets/Scripts/Physics/PhysicsWorld.cs index ba9b1bc1..c5fbe046 100644 --- a/Assets/Scripts/Physics/PhysicsWorld.cs +++ b/Assets/Scripts/Physics/PhysicsWorld.cs @@ -52,10 +52,11 @@ public class PhysicsWorld : Singleton }; private List m_Animators = new List(); +#if UNITY_EDITOR + private List m_Contacts = new List(); +#endif - private List m_Contacts = new List(); - - private List m_CollisionInfo = new List(); + private List m_CollisionInfo = new List(); public const float Ground = 0.1f; @@ -113,13 +114,13 @@ public class PhysicsWorld : Singleton BeforeUpdate(); float preTime = m_TimeCount; m_TimeCount = Time.time; - float dt = m_TimeCount - preTime; - while (dt > 1f / m_UpdateRate) + float deltaTime = m_TimeCount - preTime; + while (deltaTime > 1f / m_UpdateRate) { Tick(); - dt -= 1f / m_UpdateRate; + deltaTime -= 1f / m_UpdateRate; } - m_TimeCount -= dt; + m_TimeCount -= deltaTime; AfterUpdate(); } @@ -137,7 +138,8 @@ public class PhysicsWorld : Singleton public void DrawGizmos() { - if (m_Contacts.Count == 0) +#if UNITY_EDITOR + if (m_Contacts.Count == 0) return; for(int i = 0; i < m_Contacts.Count; ++i) @@ -145,7 +147,8 @@ public class PhysicsWorld : Singleton Vector3 center = m_Contacts[i]; Gizmos.DrawSphere(center, 0.05f); } - } +#endif + } void Tick() @@ -171,35 +174,39 @@ public class PhysicsWorld : Singleton // 更新物理系统 void UpdatePrimitives(float deltaTime) { - m_Contacts.Clear(); +#if UNITY_EDITOR + m_Contacts.Clear(); +#endif - PhysicsCollisionInfo info = new PhysicsCollisionInfo(); + PhysicsCollisionInfo info = new PhysicsCollisionInfo(); - // 处理动力学 - for(int i = 0; i < m_Primitives.Count; ++i) - { - PhysicsPrimitive prim = m_Primitives[i]; - HandleDynamics(prim, deltaTime); - } + // 1) 处理刚体的动力学 + for (int i = 0; i < m_Primitives.Count; ++i) + { + PhysicsPrimitive prim = m_Primitives[i]; + PhysicsBody body = prim.Body; + if (body == null) + continue; + HandleDynamics(prim, deltaTime); + } - // 处理碰撞 - int groupCount = (int)PhysicsGroup.GroupCount; - for (int i = 0; i < m_Primitives.Count; ++i) + // 2) 处理碰撞 + for (int i = 0; i < m_Primitives.Count; ++i) { PhysicsPrimitive prim1 = m_Primitives[i]; if (!prim1.IsActive) continue; + for (int j = i + 1; j < m_Primitives.Count; ++j) { PhysicsPrimitive prim2 = m_Primitives[j]; - // group int minGroup = Mathf.Min((int)prim1.Group, (int)prim2.Group); int maxGroup = Mathf.Max((int)prim1.Group, (int)prim2.Group); - if (m_CollisionTable[minGroup * groupCount + groupCount - maxGroup - 1] == 0) + int index = minGroup * (int)PhysicsGroup.GroupCount + (int)PhysicsGroup.GroupCount - maxGroup - 1; + if (m_CollisionTable[index] == 0) continue; - // label if (prim1.Label == prim2.Label) continue; @@ -208,96 +215,128 @@ public class PhysicsWorld : Singleton SolveCollision(prim1, info, deltaTime); SolveCollision(prim2, info, deltaTime); m_CollisionInfo.Add(info); - m_Contacts.Add(info.contact); - } + +#if UNITY_EDITOR + m_Contacts.Add(info.contact); +#endif + } } } - } - //没有physics body的primitive将不会被移动,只有那些绑定了physics body的会被施加物理效果,比如角色身体、物品 - void HandleDynamics(PhysicsPrimitive prim, float dt) + // 3) 处理刚体的约束,必须在最后处理 + for (int i = 0; i < m_Primitives.Count; ++i) + { + PhysicsPrimitive prim = m_Primitives[i]; + PhysicsBody body = prim.Body; + if (body == null) + continue; + HandleConstrain(prim, deltaTime); + } + + } + + /// + /// 处理有物体的动力学运动 + /// + /// + /// + void HandleDynamics(PhysicsPrimitive prim, float deltaTime) { PhysicsBody body = prim.Body; if (body == null) return; - if (!body.UseGravity) - return; Vector3 position = body.transform.position; - Vector3 velocity = body.Velocity; - velocity += m_Gravity * dt; - body.Velocity = velocity; - // impluse = d(mv) = m*dv - Vector3 impluse = body.Force * dt; + // 重力 + if(body.UseGravity) + { + velocity += m_Gravity * deltaTime; + } + + // 受力(冲量) + Vector3 impluse = body.Force * deltaTime; Vector3 deltaV = impluse / body.Weight; velocity += deltaV; - body.Velocity = velocity; - - position += velocity * dt; - - body.transform.position = position; if (prim.IsOnGround) - { - // pos=0, Vy=0 - position.y = 0.1f; - body.transform.position = position; - + { // 地面摩擦力 - if(body.Velocity.x != 0 && body.GroundFriction != 0) + if (body.Velocity.x != 0 && body.GroundFriction != 0) { - float dv = body.GroundFriction * dt; + float dv = body.GroundFriction * deltaTime; dv = Mathf.Min(dv, Mathf.Abs(body.Velocity.x)); dv = body.Velocity.x > 0 ? -dv : dv; velocity.x += dv; } - velocity.y = 0; - body.Velocity = velocity; } - else if(prim.IsInAir) // 空气摩擦力 + + if (prim.IsInAir) { + // 空气阻力 if(body.Velocity.x != 0 && body.AirFriction != 0) { - float dv = body.AirFriction * dt; + float dv = body.AirFriction * deltaTime; dv = Mathf.Min(dv, Mathf.Abs(body.Velocity.x)); dv = body.Velocity.x > 0 ? -dv : dv; velocity.x += dv; - body.Velocity = velocity; } } + position += velocity * deltaTime; + + body.Velocity = velocity; + body.transform.position = position; body.SetForce(Vector3.zero); } - - void SolveCollision(PhysicsPrimitive prim, PhysicsCollisionInfo collision, float dt) + + /// + /// 处理物体的环境(地面、墙体)约束 + /// + /// + /// + void HandleConstrain(PhysicsPrimitive prim, float deltaTime) + { + PhysicsBody body = prim.Body; + if (body == null) + return; + + Vector3 position = body.transform.position; + Vector3 velocity = body.Velocity; + + if (prim.IsOnGround) + { + position.y = PhysicsWorld.Ground; + velocity.y = 0; + } + + body.transform.position = position; + body.Velocity = velocity; + } + + void SolveCollision(PhysicsPrimitive prim, PhysicsCollisionInfo collision, float deltaTime) { PhysicsPrimitive other = collision.prim1 == prim ? collision.prim2 : collision.prim1; - if(prim.Body != null && other.Body != null) + + // 1. 对于刚体,根据碰撞对位置进行约束 + if(prim.Body != null) { Vector3 pos = prim.Body.transform.position; - pos.x += pos.x > collision.contact.x ? collision.size.x / 2f : - collision.size.x / 2f; + if(collision.size.x <= collision.size.y) + { + float offsetX = Mathf.Min(collision.size.x / 2f, 0.8f); + pos.x += prim.Position.x > collision.contact.x ? offsetX : -offsetX; + } + else + { + float offsetY = Mathf.Min(collision.size.y / 2f, 0.1f); + pos.y += prim.Position.y > collision.contact.y ? offsetY : -offsetY; + } prim.Body.transform.position = pos; } return; - - PhysicsBody body = prim.Body; - if (body == null) - return; - if (!body.UseGravity) - return; - Vector3 contact = collision.contact; - Vector3 dir = (prim.Position - contact).normalized; - dir.z = 0; - - float mag = Mathf.Max(0.3f, body.Velocity.magnitude); - - Vector3 position = body.transform.position; - position += mag * dir * dt; - body.Velocity = Vector3.zero; - body.transform.position = position; } // prim在当前帧是否有碰撞 -- cgit v1.1-26-g67d0