TrueSync
PhysicsWorldManager.cs
1 using UnityEngine;
2 using System.Collections.Generic;
3 using System;
4 
5 namespace TrueSync {
6 
10  public class PhysicsWorldManager : IPhysicsManager {
11 
12  private World world;
13 
14  Dictionary<IBody, GameObject> gameObjectMap;
15 
16  Dictionary<RigidBody, Dictionary<RigidBody, TSCollision>> collisionInfo;
17 
21  public TSVector Gravity {
22  get;
23  set;
24  }
25 
29  public bool SpeculativeContacts {
30  get;
31  set;
32  }
33 
34  public FP LockedTimeStep {
35  get;
36  set;
37  }
38 
39  // Use this for initialization
40  public void Init() {
41  ChecksumExtractor.Init(this);
42 
43  gameObjectMap = new Dictionary<IBody, GameObject>();
44  collisionInfo = new Dictionary<RigidBody, Dictionary<RigidBody, TSCollision>>();
45 
46  CollisionSystemPersistentSAP collisionSystem = new CollisionSystemPersistentSAP();
47  collisionSystem.EnableSpeculativeContacts = SpeculativeContacts;
48 
49  world = new World(collisionSystem);
50  collisionSystem.world = world;
51 
52  world.physicsManager = this;
53  world.Gravity = Gravity;
54 
55  world.Events.BodiesBeginCollide += CollisionEnter;
56  world.Events.BodiesStayCollide += CollisionStay;
57  world.Events.BodiesEndCollide += CollisionExit;
58 
59  world.Events.TriggerBeginCollide += TriggerEnter;
60  world.Events.TriggerStayCollide += TriggerStay;
61  world.Events.TriggerEndCollide += TriggerExit;
62 
63  world.Events.RemovedRigidBody += OnRemovedRigidBody;
64 
65  AddRigidBodies();
66  }
67 
71  public void UpdateStep() {
72  world.Step(LockedTimeStep, false);
73  }
74 
78  public IWorld GetWorld() {
79  return world;
80  }
81 
82  void AddRigidBodies() {
83  TSCollider[] bodies = GameObject.FindObjectsOfType<TSCollider>();
84  List<TSCollider> sortedBodies = new List<TSCollider>(bodies);
85  sortedBodies.Sort(UnityUtils.bodyComparer);
86 
87  for (int i = 0; i < sortedBodies.Count; i++) {
88  AddBody(sortedBodies[i]);
89  }
90  }
91 
97  public void AddBody(ICollider iCollider) {
98  if (!(iCollider is TSCollider)) {
99  Debug.LogError("You have a 2D object but your Physics 2D is disabled.");
100  return;
101  }
102 
103  TSCollider tsCollider = (TSCollider) iCollider;
104 
105  if (tsCollider._body != null) {
106  //already added
107  return;
108  }
109 
110  tsCollider.Initialize();
111  world.AddBody(tsCollider._body);
112  gameObjectMap[tsCollider._body] = tsCollider.gameObject;
113 
114  if (tsCollider.gameObject.transform.parent != null && tsCollider.gameObject.transform.parent.GetComponentInParent<TSCollider>() != null) {
115  TSCollider parentCollider = tsCollider.gameObject.transform.parent.GetComponentInParent<TSCollider>();
116  world.AddConstraint(new ConstraintHierarchy(parentCollider.Body, tsCollider._body, (tsCollider.GetComponent<TSTransform>().position + tsCollider.ScaledCenter) - (parentCollider.GetComponent<TSTransform>().position + parentCollider.ScaledCenter)));
117  }
118  }
119 
120  public void RemoveBody(IBody iBody) {
121  world.RemoveBody((RigidBody) iBody);
122  }
123 
124  public void OnRemoveBody(System.Action<IBody> OnRemoveBody){
125  world.Events.RemovedRigidBody += delegate (RigidBody rb) {
126  OnRemoveBody(rb);
127  };
128  }
129 
130  public bool Raycast(TSVector rayOrigin, TSVector rayDirection, RaycastCallback raycast, out IBody body, out TSVector normal, out FP fraction) {
131  RigidBody rb;
132  bool result = world.CollisionSystem.Raycast(rayOrigin, rayDirection, raycast, out rb, out normal, out fraction);
133  body = rb;
134 
135  return result;
136  }
137 
138  public TSRaycastHit Raycast(TSRay ray, FP maxDistance, RaycastCallback callback = null) {
139  IBody hitBody;
140  TSVector hitNormal;
141  FP hitFraction;
142 
143  TSVector origin = ray.origin;
144  TSVector direction = ray.direction;
145 
146  if (PhysicsManager.instance.Raycast(origin, direction, callback, out hitBody, out hitNormal, out hitFraction)) {
147  if (hitFraction <= maxDistance) {
148  GameObject other = PhysicsManager.instance.GetGameObject(hitBody);
149  TSRigidBody bodyComponent = other.GetComponent<TSRigidBody>();
150  TSCollider colliderComponent = other.GetComponent<TSCollider>();
151  TSTransform transformComponent = other.GetComponent<TSTransform>();
152  return new TSRaycastHit(bodyComponent, colliderComponent, transformComponent, hitNormal, ray.origin, ray.direction, hitFraction);
153  }
154  } else {
155  direction *= maxDistance;
156  if (PhysicsManager.instance.Raycast(origin, direction, callback, out hitBody, out hitNormal, out hitFraction)) {
157  GameObject other = PhysicsManager.instance.GetGameObject(hitBody);
158  TSRigidBody bodyComponent = other.GetComponent<TSRigidBody>();
159  TSCollider colliderComponent = other.GetComponent<TSCollider>();
160  TSTransform transformComponent = other.GetComponent<TSTransform>();
161  return new TSRaycastHit(bodyComponent, colliderComponent, transformComponent, hitNormal, ray.origin, direction, hitFraction);
162  }
163  }
164  return null;
165  }
166 
167  private void OnRemovedRigidBody(RigidBody body) {
168  GameObject go = gameObjectMap[body];
169 
170  if (go != null) {
171  GameObject.Destroy(go);
172  }
173  }
174 
175  private void CollisionEnter(Contact c) {
176  CollisionDetected(c.body1, c.body2, c, "OnSyncedCollisionEnter");
177  }
178 
179  private void CollisionStay(Contact c) {
180  CollisionDetected(c.body1, c.body2, c, "OnSyncedCollisionStay");
181  }
182 
183  private void CollisionExit(RigidBody body1, RigidBody body2) {
184  CollisionDetected(body1, body2, null, "OnSyncedCollisionExit");
185  }
186 
187  private void TriggerEnter(Contact c) {
188  CollisionDetected(c.body1, c.body2, c, "OnSyncedTriggerEnter");
189  }
190 
191  private void TriggerStay(Contact c) {
192  CollisionDetected(c.body1, c.body2, c, "OnSyncedTriggerStay");
193  }
194 
195  private void TriggerExit(RigidBody body1, RigidBody body2) {
196  CollisionDetected(body1, body2, null, "OnSyncedTriggerExit");
197  }
198 
199  private void CollisionDetected(RigidBody body1, RigidBody body2, Contact c, string callbackName) {
200  if (!gameObjectMap.ContainsKey(body1) || !gameObjectMap.ContainsKey(body2)) {
201  return;
202  }
203 
204  GameObject b1 = gameObjectMap[body1];
205  GameObject b2 = gameObjectMap[body2];
206 
207  if (b1 == null || b2 == null) {
208  return;
209  }
210 
211  b1.SendMessage(callbackName, GetCollisionInfo(body1, body2, c), SendMessageOptions.DontRequireReceiver);
212  b2.SendMessage(callbackName, GetCollisionInfo(body2, body1, c), SendMessageOptions.DontRequireReceiver);
213 
215  }
216 
217  private TSCollision GetCollisionInfo(RigidBody body1, RigidBody body2, Contact c) {
218  if (!collisionInfo.ContainsKey(body1)) {
219  collisionInfo.Add(body1, new Dictionary<RigidBody, TSCollision>());
220  }
221 
222  Dictionary<RigidBody, TSCollision> collisionInfoBody1 = collisionInfo[body1];
223 
224  TSCollision result = null;
225 
226  if (collisionInfoBody1.ContainsKey(body2)) {
227  result = collisionInfoBody1[body2];
228  } else {
229  result = new TSCollision();
230  collisionInfoBody1.Add(body2, result);
231  }
232 
233 
234  result.Update(gameObjectMap[body2], c);
235 
236  return result;
237  }
238 
244  public GameObject GetGameObject(IBody rigidBody) {
245  return gameObjectMap[rigidBody];
246  }
247 
254  public bool IsCollisionEnabled(IBody rigidBody1, IBody rigidBody2) {
255  return LayerCollisionMatrix.CollisionEnabled(gameObjectMap[rigidBody1], gameObjectMap[rigidBody2]);
256  }
257 
258  public IWorldClone GetWorldClone() {
259  return new WorldClone();
260  }
261 
262  }
263 
264 }
Manages the collision matrix of physics simulation.
Manages creation of player prefabs and lockstep execution.
Represents few information about a raycast hit.
Definition: TSRaycastHit.cs:9
TSVector Gravity
Property access to simulated gravity.
static void UpdateCoroutines()
Update all coroutines created.
Provides a few utilities to be used on TrueSync exposed classes.
Definition: UnityUtils.cs:10
IWorld GetWorld()
Instance of the current simulated world.
bool IsCollisionEnabled(IBody rigidBody1, IBody rigidBody2)
Check if the collision between two RigidBodies is enabled.
Represents a physical 3D rigid body.
Definition: TSRigidBody.cs:11
A deterministic version of Unity&#39;s Transform component for 3D physics.
Definition: TSTransform.cs:9
static IPhysicsManager instance
Returns a proper implementation of IPhysicsManager.
A vector structure.
Definition: TSVector.cs:29
Manages the 3D physics simulation.
Abstract collider for 3D shapes.
Definition: TSCollider.cs:12
TSVector ScaledCenter
Returns a version of collider&#39;s center scaled by parent&#39;s transform.
Definition: TSCollider.cs:60
GameObject GetGameObject(IBody rigidBody)
Get the GameObject related to a specific RigidBody.
static bool CollisionEnabled(int layerA, int layerB)
Returns true if the given layers can collide.
TSVector position
Property access to position.
Definition: TSTransform.cs:23
Represents a ray with origin and direction.
Definition: TSRay.cs:7
void Initialize()
Initializes Shape and RigidBody and sets initial values to position and orientation based on Unity&#39;s ...
Definition: TSCollider.cs:172
Manages physics simulation.
IBody3D Body
Returns the body linked to this collider.
Definition: TSCollider.cs:94
static TSBodyComparer bodyComparer
Instance of a TSBodyComparer.
Definition: UnityUtils.cs:53
Represents information about a contact between two 3D bodies.
Definition: TSCollision.cs:25
bool SpeculativeContacts
Property access to speculative contacts.
Represents a common interface to 2D and 3D bodies.
Definition: IBody.cs:6
void AddBody(ICollider iCollider)
Add a new RigidBody to the world.
void UpdateStep()
Goes one step further on the physics simulation.