1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
|
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// primitive分类
/// </summary>
public enum PhysicsGroup
{
Character, // 角色
Prop, // 物体
Ground, // 地面
Wall, // 墙面
GroupCount,
}
/// <summary>
/// primitive标记
/// </summary>
public enum PhysicsTag
{
Player = 1, // 从属于玩家
Oponent = 1 << 1, // 从属于对手
}
public class PhysicsWorld : Singleton<PhysicsWorld>
{
private int m_UpdateRate = 60;
// 重力加速度
private readonly Vector3 m_Gravity = new Vector3(0, -9.8f, 0);
// 当前管理的碰撞体
private List<PhysicsPrimitive> m_Primitives = new List<PhysicsPrimitive>();
private float m_TimeCount;
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,
};
private List<Animator> m_Animators = new List<Animator>();
public void Init()
{
m_TimeCount = Time.time;
}
public void AddPrimitive(PhysicsPrimitive prim)
{
if (prim == null)
return;
if(m_Primitives.Contains(prim))
{
Debug.LogError("PhysicsWorld已经存在此碰撞体,ID=" + prim.ID + ", 类型=" + prim.Tag);
return;
}
m_Primitives.Add(prim);
}
public void RemovePrimitive(PhysicsPrimitive prim)
{
if (prim == null)
return;
m_Primitives.Remove(prim);
}
public void AddAnimator(Animator animator)
{
if (m_Animators.Contains(animator))
return;
m_Animators.Add(animator);
}
public void RemoveAnimator(Animator animator)
{
if (m_Animators.Contains(animator))
m_Animators.Remove(animator);
}
/// <summary>
/// 物理系统已稳定的逻辑帧率执行
/// </summary>
public void Update()
{
float preTime = m_TimeCount;
m_TimeCount = Time.time;
float dt = m_TimeCount - preTime;
while (dt > 1f / m_UpdateRate)
{
Tick();
dt -= 1f / m_UpdateRate;
}
m_TimeCount -= dt;
}
void Tick()
{
float deltaTime = 1f / m_UpdateRate;
// animator -> OnAnimatorMove() -> physics
//UpdateAnimator(deltaTime);
UpdatePrimitives(deltaTime);
}
// 更新动画,并处理OnAnimatorMove()
void UpdateAnimator(float deltaTime)
{
for (int i = 0; i < m_Animators.Count; ++i)
{
Animator animator = m_Animators[i];
animator.speed = 1;
animator.Update(deltaTime);
animator.speed = 0;
}
}
// 更新物理系统
void UpdatePrimitives(float deltaTime)
{
int groupCount = (int)PhysicsGroup.GroupCount;
for (int i = 0; i < m_Primitives.Count; ++i)
{
PhysicsPrimitive prim1 = m_Primitives[i];
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)
continue;
// check collision by label
if (prim1.Label == prim2.Label)
continue;
PhysicsCollisionInfo info;
if (PhysicsHelper.PrimvsPrim(prim1, prim2, out info))
{
//没有physics body的primitive将不会被移动,只有那些绑定了physics body的会被施加物理效果,比如角色身体、物品
}
}
}
}
}
|