diff options
author | chai <chaifix@163.com> | 2020-11-03 19:05:55 +0800 |
---|---|---|
committer | chai <chaifix@163.com> | 2020-11-03 19:05:55 +0800 |
commit | ef739e3c4d66007fb9c2ced195edb539eb92f3a4 (patch) | |
tree | db0605625fe907db4179687a18b36453a15f1a75 /Assets/Scripts/Physics/PhysicsWorld.cs | |
parent | 7afdc099b52be6dbf6f9f8c9e607b3c6cf2b51f7 (diff) |
*misc
Diffstat (limited to 'Assets/Scripts/Physics/PhysicsWorld.cs')
-rw-r--r-- | Assets/Scripts/Physics/PhysicsWorld.cs | 183 |
1 files changed, 111 insertions, 72 deletions
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<PhysicsWorld> };
private List<Animator> m_Animators = new List<Animator>();
+#if UNITY_EDITOR
+ private List<Vector3> m_Contacts = new List<Vector3>();
+#endif
- private List<Vector3> m_Contacts = new List<Vector3>();
-
- private List<PhysicsCollisionInfo> m_CollisionInfo = new List<PhysicsCollisionInfo>();
+ private List<PhysicsCollisionInfo> m_CollisionInfo = new List<PhysicsCollisionInfo>();
public const float Ground = 0.1f;
@@ -113,13 +114,13 @@ public class PhysicsWorld : Singleton<PhysicsWorld> 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<PhysicsWorld> 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<PhysicsWorld> Vector3 center = m_Contacts[i];
Gizmos.DrawSphere(center, 0.05f);
}
- }
+#endif
+ }
void Tick()
@@ -171,35 +174,39 @@ public class PhysicsWorld : Singleton<PhysicsWorld> // 更新物理系统
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<PhysicsWorld> 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);
+ }
+
+ }
+
+ /// <summary>
+ /// 处理有物体的动力学运动
+ /// </summary>
+ /// <param name="prim"></param>
+ /// <param name="deltaTime"></param>
+ 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)
+
+ /// <summary>
+ /// 处理物体的环境(地面、墙体)约束
+ /// </summary>
+ /// <param name="prim"></param>
+ /// <param name="deltaTime"></param>
+ 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在当前帧是否有碰撞
|