From 65ed53a40f990e895305ff17a5e48e3cd6b8785b Mon Sep 17 00:00:00 2001 From: chai Date: Sat, 24 Oct 2020 17:30:07 +0800 Subject: =?UTF-8?q?*=E7=89=A9=E7=90=86=E7=B3=BB=E7=BB=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/Scripts/Physics/PhysicsWorld.cs | 134 +++++++++++++++++++++++++++++---- 1 file changed, 120 insertions(+), 14 deletions(-) (limited to 'Assets/Scripts/Physics/PhysicsWorld.cs') diff --git a/Assets/Scripts/Physics/PhysicsWorld.cs b/Assets/Scripts/Physics/PhysicsWorld.cs index c2397909..7994e14b 100644 --- a/Assets/Scripts/Physics/PhysicsWorld.cs +++ b/Assets/Scripts/Physics/PhysicsWorld.cs @@ -12,6 +12,9 @@ public enum PhysicsGroup Ground, // 地面 Wall, // 墙面 + HitBox, // hitbox + HurtBox, // hurtbox + GroupCount, } @@ -20,6 +23,7 @@ public enum PhysicsGroup /// public enum PhysicsTag { + Null = 0, Player = 1, // 从属于玩家 Oponent = 1 << 1, // 从属于对手 } @@ -28,21 +32,28 @@ public class PhysicsWorld : Singleton { private int m_UpdateRate = 60; // 重力加速度 - private readonly Vector3 m_Gravity = new Vector3(0, -9.8f, 0); + private readonly Vector3 m_Gravity = new Vector3(0, -12f, 0); // 当前管理的碰撞体 private List m_Primitives = new List(); private float m_TimeCount; + private const int _ = 0; private readonly int[] m_CollisionTable = { - // wall ground prop character -/*character*/ 1, 1, 1, 1, -/*prop */ 1, 1, 0, 0, -/*ground */ 0, 0, 0, 0, -/*wall */ 0, 0, 0, 0, + // hurtbox hitBox wall ground prop character +/*character*/ 0, 0, 1, 1, 1, 1, +/*prop */ 0, 0, 1, 1, 0, _, +/*ground */ 0, 0, 0, 0, _, _, +/*wall */ 0, 0, 0, _, _, _, +/*hitbox */ 1, 0, _, _, _, _, +/*hurtbox */ 0, _, _, _, _, _, }; private List m_Animators = new List(); + private List m_Contacts = new List(); + + private List m_CollisionInfo = new List(); + public void Init() { m_TimeCount = Time.time; @@ -85,6 +96,7 @@ public class PhysicsWorld : Singleton /// public void Update() { + BeforeUpdate(); float preTime = m_TimeCount; m_TimeCount = Time.time; float dt = m_TimeCount - preTime; @@ -94,9 +106,35 @@ public class PhysicsWorld : Singleton dt -= 1f / m_UpdateRate; } m_TimeCount -= dt; + AfterUpdate(); } - void Tick() + // 更新之前 + private void BeforeUpdate() + { + m_CollisionInfo.Clear(); + } + + // 更新之后 + private void AfterUpdate() + { + + } + + public void DrawGizmos() + { + if (m_Contacts.Count == 0) + return; + + for(int i = 0; i < m_Contacts.Count; ++i) + { + Vector3 center = m_Contacts[i]; + Gizmos.DrawSphere(center, 0.05f); + } + } + + + void Tick() { float deltaTime = 1f / m_UpdateRate; // animator -> OnAnimatorMove() -> physics @@ -119,32 +157,100 @@ public class PhysicsWorld : Singleton // 更新物理系统 void UpdatePrimitives(float deltaTime) { + m_Contacts.Clear(); + + PhysicsCollisionInfo info = new PhysicsCollisionInfo(); + + // 处理动力学 + for(int i = 0; i < m_Primitives.Count; ++i) + { + PhysicsPrimitive prim = m_Primitives[i]; + HandleDynamics(prim, deltaTime); + } + + // 处理碰撞 int groupCount = (int)PhysicsGroup.GroupCount; 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]; // check collision by group - int minType = Mathf.Min((int)prim1.Type, (int)prim2.Type); - int maxType = Mathf.Max((int)prim1.Type, (int)prim2.Type); - if (m_CollisionTable[minType * groupCount + groupCount - maxType - 1] == 0) + 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) continue; // check collision by label if (prim1.Label == prim2.Label) continue; - PhysicsCollisionInfo info; - if (PhysicsHelper.PrimvsPrim(prim1, prim2, out info)) + if (PhysicsHelper.PrimvsPrim(prim1, prim2, ref info)) { - //没有physics body的primitive将不会被移动,只有那些绑定了physics body的会被施加物理效果,比如角色身体、物品 - + SolveCollision(prim1, info, deltaTime); + SolveCollision(prim2, info, deltaTime); + m_CollisionInfo.Add(info); + m_Contacts.Add(info.contact); } } } } + //没有physics body的primitive将不会被移动,只有那些绑定了physics body的会被施加物理效果,比如角色身体、物品 + void HandleDynamics(PhysicsPrimitive prim, float dt) + { + 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; + + position += velocity * dt; + + body.transform.position = position; + } + + void SolveCollision(PhysicsPrimitive prim, PhysicsCollisionInfo collision, float dt) + { + 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在当前帧是否有碰撞 + public bool HasCollision(PhysicsPrimitive prim) + { + for(int i = 0; i < m_CollisionInfo.Count; ++i) + { + PhysicsCollisionInfo info = m_CollisionInfo[i]; + if(info.prim1 == prim || info.prim2 == prim) + { + return true; + } + } + return false; + } + } \ No newline at end of file -- cgit v1.1-26-g67d0