Rigidbody.cs 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. using System;
  4. using System.Collections.Generic;
  5. namespace BansheeEngine
  6. {
  7. /** @addtogroup Physics
  8. * @{
  9. */
  10. /// <summary>
  11. /// Rigidbody is a dynamic physics object that can be moved using forces (or directly). It will interact with other
  12. /// static and dynamic physics objects in the scene accordingly (it will push other non-kinematic rigidbodies,
  13. /// and collide with static objects).
  14. ///
  15. /// The shape and mass of a rigidbody is governed by its colliders. You must attach at least one collider for the
  16. /// rigidbody to be valid. Colliders that are on the same scene object as the rigidbody, or on child scene objects
  17. /// are automatically considered as part of the rigidbody.
  18. /// </summary>
  19. public sealed class Rigidbody : Component
  20. {
  21. internal NativeRigidbody native;
  22. private List<Collider> children = new List<Collider>();
  23. private Joint parentJoint;
  24. [SerializeField]
  25. internal SerializableData serializableData = new SerializableData();
  26. /// <summary>
  27. /// Triggered when some object starts interacting with one of the child colliders. Only triggered if proper
  28. /// collision report mode is turned on.
  29. /// </summary>
  30. public event Action<CollisionData> OnCollisionBegin;
  31. /// <summary>
  32. /// Triggered for every frame that an object remains interacting with one of the child colliders. Only triggered if
  33. /// proper collision report mode is turned on.
  34. /// </summary>
  35. public event Action<CollisionData> OnCollisionStay;
  36. /// <summary>
  37. /// Triggered when some object stops interacting with one of the child colliders. Only triggered if proper collision
  38. /// report mode is turned on.
  39. /// </summary>
  40. public event Action<CollisionData> OnCollisionEnd;
  41. /// <summary>
  42. /// Determines the mass of the object and all of its collider shapes. Only relevant if RigidbodyFlag.AutoMass or
  43. /// RigidbodyFlag.AutoTensors is turned off. Value of zero means the object is immovable (but can be rotated).
  44. /// </summary>
  45. public float Mass
  46. {
  47. get { return serializableData.mass; }
  48. set
  49. {
  50. serializableData.mass = value;
  51. if (native != null)
  52. native.Mass = value;
  53. }
  54. }
  55. /// <summary>
  56. /// Determines if the body is kinematic. Kinematic body will not move in response to external forces (for example
  57. /// gravity, or another object pushing it), essentially behaving like collider. Unlike a collider though, you can
  58. /// still move the object and have other dynamic objects respond correctly (that is, it will push other objects).
  59. /// </summary>
  60. public bool Kinematic
  61. {
  62. get { return serializableData.isKinematic; }
  63. set
  64. {
  65. if (serializableData.isKinematic == value)
  66. return;
  67. serializableData.isKinematic = value;
  68. if (native != null)
  69. {
  70. native.Kinematic = value;
  71. ClearColliders();
  72. UpdateColliders();
  73. }
  74. }
  75. }
  76. /// <summary>
  77. /// Determines if the body is sleeping. Objects that aren't moved/rotated for a while are put to sleep to reduce
  78. /// load on the physics system. You may also manually force objects to sleep or wake up.
  79. /// </summary>
  80. public bool Sleeping
  81. {
  82. get
  83. {
  84. if (native != null)
  85. return native.Sleeping;
  86. return true;
  87. }
  88. set
  89. {
  90. if (native != null)
  91. native.Sleeping = value;
  92. }
  93. }
  94. /// <summary>
  95. /// Threshold of force and torque under which the object will be considered to be put to sleep.
  96. /// </summary>
  97. public float SleepThreshold
  98. {
  99. get { return serializableData.sleepThreshold; }
  100. set
  101. {
  102. serializableData.sleepThreshold = value;
  103. if (native != null)
  104. native.SleepThreshold = value;
  105. }
  106. }
  107. /// <summary>
  108. /// Determines whether or not the rigidbody will have the global gravity force applied to it.
  109. /// </summary>
  110. public bool UseGravity
  111. {
  112. get { return serializableData.useGravity; }
  113. set
  114. {
  115. serializableData.useGravity = value;
  116. if (native != null)
  117. native.UseGravity = value;
  118. }
  119. }
  120. /// <summary>
  121. /// Determines current linear velocity of the body.
  122. /// </summary>
  123. public Vector3 Velocity
  124. {
  125. get
  126. {
  127. if (native != null)
  128. return native.Velocity;
  129. return Vector3.Zero;
  130. }
  131. set
  132. {
  133. if (native != null)
  134. native.Velocity = value;
  135. }
  136. }
  137. /// <summary>
  138. /// Determines current angular velocity of the body.
  139. /// </summary>
  140. public Vector3 AngularVelocity
  141. {
  142. get
  143. {
  144. if (native != null)
  145. return native.AngularVelocity;
  146. return Vector3.Zero;
  147. }
  148. set
  149. {
  150. if (native != null)
  151. native.AngularVelocity = value;
  152. }
  153. }
  154. /// <summary>
  155. /// Determines linear drag of the body. Higher drag values means the object resists linear movement more.
  156. /// </summary>
  157. public float Drag
  158. {
  159. get { return serializableData.linearDrag; }
  160. set
  161. {
  162. serializableData.linearDrag = value;
  163. if (native != null)
  164. native.Drag = value;
  165. }
  166. }
  167. /// <summary>
  168. /// Determines angular drag of the body. Higher drag values means the object resists angular movement more.
  169. /// </summary>
  170. public float AngularDrag
  171. {
  172. get { return serializableData.angularDrag; }
  173. set
  174. {
  175. serializableData.angularDrag = value;
  176. if (native != null)
  177. native.AngularDrag = value;
  178. }
  179. }
  180. /// <summary>
  181. /// Sets the inertia tensor in local mass space. Inertia tensor determines how difficult is to rotate the object.
  182. /// Values of zero in the inertia tensor mean the object will be unable to rotate around a specific axis. Changing
  183. /// this value is only relevant if RigidbodyFlag.AutoTensors is turned off.
  184. /// </summary>
  185. public Vector3 InertiaTensor
  186. {
  187. get { return serializableData.inertiaTensor; }
  188. set
  189. {
  190. serializableData.inertiaTensor = value;
  191. if (native != null)
  192. native.InertiaTensor = value;
  193. }
  194. }
  195. /// <summary>
  196. /// Determines position of the center of the mass. Changing this value is only relevant if RigidbodyFlag.AutoTensors
  197. /// is turned off.
  198. /// </summary>
  199. public Vector3 CenterOfMassPosition
  200. {
  201. get { return serializableData.centerMassPosition; }
  202. set
  203. {
  204. serializableData.centerMassPosition = value;
  205. if (native != null)
  206. native.CenterOfMassPosition = value;
  207. }
  208. }
  209. /// <summary>
  210. /// Determines rotation of the inertia tensor (rotation of the center of mass frame). Changing this value is only
  211. /// relevant if RigidbodyFlag.AutoTensors is turned off.
  212. /// </summary>
  213. public Quaternion CenterOfMassRotation
  214. {
  215. get { return serializableData.centerMassRotation; }
  216. set
  217. {
  218. serializableData.centerMassRotation = value;
  219. if (native != null)
  220. native.CenterOfMassRotation = value;
  221. }
  222. }
  223. /// <summary>
  224. /// Determines maximum angular velocity of the rigidbody. Velocity will be clamped to this value.
  225. /// </summary>
  226. public float MaxAngularVelocity
  227. {
  228. get { return serializableData.maxAngularVelocity; }
  229. set
  230. {
  231. serializableData.maxAngularVelocity = value;
  232. if (native != null)
  233. native.MaxAngularVelocity = value;
  234. }
  235. }
  236. /// <summary>
  237. /// Determines number of iterations to use when solving for position. Higher values can improve precision and
  238. /// numerical stability of the simulation.
  239. /// </summary>
  240. public int PositionSolverCount
  241. {
  242. get { return serializableData.positionSolverCount; }
  243. set
  244. {
  245. serializableData.positionSolverCount = value;
  246. if (native != null)
  247. serializableData.positionSolverCount = value;
  248. }
  249. }
  250. /// <summary>
  251. /// Determines number of iterations to use when solving for velocity. Higher values can improve precision and
  252. /// numerical stability of the simulation.
  253. /// </summary>
  254. public int VelocitySolverCount
  255. {
  256. get { return serializableData.velocitySolverCount; }
  257. set
  258. {
  259. serializableData.velocitySolverCount = value;
  260. if (native != null)
  261. serializableData.velocitySolverCount = value;
  262. }
  263. }
  264. /// <summary>
  265. /// Determines which (if any) collision events are reported.
  266. /// </summary>
  267. public CollisionReportMode CollisionReportMode
  268. {
  269. get { return serializableData.collisionReportMode; }
  270. set
  271. {
  272. if (serializableData.collisionReportMode == value)
  273. return;
  274. serializableData.collisionReportMode = value;
  275. foreach (var entry in children)
  276. entry.UpdateCollisionReportMode();
  277. }
  278. }
  279. /// <summary>
  280. /// Various flags that control the behaviour of the rigidbody.
  281. /// </summary>
  282. public RigidbodyFlag Flags
  283. {
  284. get { return serializableData.flags; }
  285. set
  286. {
  287. if (serializableData.flags == value)
  288. return;
  289. serializableData.flags = value;
  290. if (native != null)
  291. {
  292. native.Flags = value;
  293. native.UpdateMassDistribution();
  294. }
  295. }
  296. }
  297. /// <summary>
  298. /// Moves the rigidbody to a specific position. This method will ensure physically correct movement, meaning the
  299. /// body will collide with other objects along the way.
  300. /// </summary>
  301. /// <param name="position">New position for the body, in world space.</param>
  302. public void Move(Vector3 position)
  303. {
  304. if (native != null)
  305. native.Move(position);
  306. NotifyFlags = TransformChangedFlags.None;
  307. SceneObject.Position = position;
  308. NotifyFlags = TransformChangedFlags.Transform | TransformChangedFlags.Parent;
  309. }
  310. /// <summary>
  311. /// Rotates the rigidbody. This method will ensure physically correct rotation, meaning the body will collide with
  312. /// other objects along the way.
  313. /// </summary>
  314. /// <param name="rotation">New orientation of the body, in world space.</param>
  315. public void Rotate(Quaternion rotation)
  316. {
  317. if (native != null)
  318. native.Rotate(rotation);
  319. NotifyFlags = TransformChangedFlags.None;
  320. SceneObject.Rotation = rotation;
  321. NotifyFlags = TransformChangedFlags.Transform | TransformChangedFlags.Parent;
  322. }
  323. /// <summary>
  324. /// Applies a force to the center of the mass of the rigidbody. This will produce linear momentum.
  325. /// </summary>
  326. /// <param name="force">Force to apply.</param>
  327. /// <param name="mode">Determines what type of force was applied.</param>
  328. public void AddForce(Vector3 force, ForceMode mode = ForceMode.Force)
  329. {
  330. if (native != null)
  331. native.AddForce(force, mode);
  332. }
  333. /// <summary>
  334. /// Applies a torque to the rigidbody. This will produce angular momentum.
  335. /// </summary>
  336. /// <param name="torque">Torque to apply.</param>
  337. /// <param name="mode">Determines what type of torque was applied.</param>
  338. public void AddTorque(Vector3 torque, ForceMode mode = ForceMode.Force)
  339. {
  340. if (native != null)
  341. native.AddTorque(torque, mode);
  342. }
  343. /// <summary>
  344. /// Applies a force to a specific point on the rigidbody. This will in most cases produce both linear and angular
  345. /// momentum.
  346. /// </summary>
  347. /// <param name="force">Force to apply.</param>
  348. /// <param name="position">World space point to apply the force at.</param>
  349. /// <param name="mode">Determines what type of force was applied.</param>
  350. public void AddForceAtPoint(Vector3 force, Vector3 position, PointForceMode mode = PointForceMode.Force)
  351. {
  352. if (native != null)
  353. native.AddForceAtPoint(force, position, mode);
  354. }
  355. /// <summary>
  356. /// Returns the total (linear + angular) velocity at a specific point.
  357. /// </summary>
  358. /// <param name="position">Point in world space.</param>
  359. /// <returns>Total velocity of the point.</returns>
  360. public Vector3 GetVelocityAtPoint(Vector3 position)
  361. {
  362. if (native != null)
  363. return native.GetVelocityAtPoint(position);
  364. return position;
  365. }
  366. /// <summary>
  367. /// Triggered when one of the child colliders begins touching another object.
  368. /// </summary>
  369. /// <param name="data">Data about the collision.</param>
  370. internal void DoOnCollisionBegin(CollisionData data)
  371. {
  372. if (OnCollisionBegin != null)
  373. OnCollisionBegin(data);
  374. }
  375. /// <summary>
  376. /// Triggered when one of the child colliders ends touching another object.
  377. /// </summary>
  378. /// <param name="data">Data about the collision.</param>
  379. internal void DoOnCollisionStay(CollisionData data)
  380. {
  381. if (OnCollisionStay != null)
  382. OnCollisionStay(data);
  383. }
  384. /// <summary>
  385. /// Triggered when one of the child colliders ends touching another object.
  386. /// </summary>
  387. /// <param name="data">Data about the collision.</param>
  388. internal void DoOnCollisionEnd(CollisionData data)
  389. {
  390. if (OnCollisionEnd != null)
  391. OnCollisionEnd(data);
  392. }
  393. /// <summary>
  394. /// Sets that joint that this rigidbody is attached to. Allows the rigidbody to notify the joint when it moves.
  395. /// </summary>
  396. /// <param name="joint">Joint the rigidbody is attached to, or null if none.</param>
  397. internal void SetJoint(Joint joint)
  398. {
  399. parentJoint = joint;
  400. }
  401. /// <summary>
  402. /// Recalculates rigidbody's mass, inertia tensors and center of mass depending on the currently set child
  403. /// colliders. This should be called whenever relevant child collider properties change(like mass or shape).
  404. ///
  405. /// If automatic tensor calculation is turned off then this will do nothing. If automatic mass calculation is turned
  406. /// off then this will use the mass set directly on the body using <see cref="Mass"/>.
  407. /// </summary>
  408. internal void UpdateMassDistribution()
  409. {
  410. if (native != null)
  411. native.UpdateMassDistribution();
  412. }
  413. /// <summary>
  414. /// Unregisters all child colliders from the Rigidbody.
  415. /// </summary>
  416. internal void ClearColliders()
  417. {
  418. foreach (var collider in children)
  419. collider.SetRigidbody(null, true);
  420. children.Clear();
  421. if (native != null)
  422. native.RemoveColliders();
  423. }
  424. /// <summary>
  425. /// Registers a new collider with the Rigidbody. This collider will then be used to calculate Rigidbody's geometry
  426. /// used for collisions, and optionally (depending on set flags) total mass, inertia tensors and center of mass.
  427. /// </summary>
  428. /// <param name="collider">Collider to register.</param>
  429. internal void AddCollider(Collider collider)
  430. {
  431. if (native == null)
  432. return;
  433. children.Add(collider);
  434. native.AddCollider(collider);
  435. }
  436. /// <summary>
  437. /// Unregisters the collider from the Rigidbody.
  438. /// </summary>
  439. /// <param name="collider">Collider to unregister.</param>
  440. internal void RemoveCollider(Collider collider)
  441. {
  442. if (native == null)
  443. return;
  444. if (children.Exists(x => x == collider))
  445. {
  446. native.RemoveCollider(collider);
  447. children.Remove(collider);
  448. }
  449. }
  450. private void OnInitialize()
  451. {
  452. NotifyFlags = TransformChangedFlags.Transform | TransformChangedFlags.Parent;
  453. }
  454. private void OnEnable()
  455. {
  456. RestoreNative();
  457. }
  458. private void OnDisable()
  459. {
  460. DestroyNative();
  461. }
  462. private void OnDestroy()
  463. {
  464. DestroyNative();
  465. }
  466. private void OnTransformChanged(TransformChangedFlags flags)
  467. {
  468. if (!SceneObject.Active)
  469. return;
  470. if ((flags & TransformChangedFlags.Parent) != 0)
  471. {
  472. ClearColliders();
  473. UpdateColliders();
  474. if ((serializableData.flags & RigidbodyFlag.AutoTensors) != 0)
  475. native.UpdateMassDistribution();
  476. #if DEBUG
  477. CheckForNestedRigibody();
  478. #endif
  479. }
  480. native.Position = SceneObject.Position;
  481. native.Rotation = SceneObject.Rotation;
  482. if (parentJoint != null)
  483. parentJoint.NotifyRigidbodyMoved(this);
  484. }
  485. /// <summary>
  486. /// Searches child scene objects for Collider components and attaches them to the rigidbody. Make sure to call
  487. /// <see cref="ClearColliders"/> if you need to clear old colliders first.
  488. /// </summary>
  489. private void UpdateColliders()
  490. {
  491. Stack<SceneObject> todo = new Stack<SceneObject>();
  492. todo.Push(SceneObject);
  493. while (todo.Count > 0)
  494. {
  495. SceneObject currentSO = todo.Pop();
  496. if (currentSO.GetComponent<Collider>() != null)
  497. {
  498. Collider[] colliders = currentSO.GetComponents<Collider>();
  499. foreach (var entry in colliders)
  500. {
  501. if (!entry.IsValidParent(this))
  502. continue;
  503. if (entry.native == null)
  504. continue;
  505. entry.SetRigidbody(this, true);
  506. entry.native.Rigidbody = native;
  507. children.Add(entry);
  508. native.AddCollider(entry);
  509. }
  510. }
  511. int childCount = currentSO.GetNumChildren();
  512. for (int i = 0; i < childCount; i++)
  513. {
  514. SceneObject child = currentSO.GetChild(i);
  515. if (child.GetComponent<Rigidbody>() != null)
  516. continue;
  517. todo.Push(child);
  518. }
  519. }
  520. }
  521. /// <summary>
  522. /// Checks if the rigidbody is nested under another rigidbody, and throws out a warning if so.
  523. /// </summary>
  524. private void CheckForNestedRigibody()
  525. {
  526. SceneObject currentSO = SceneObject.Parent;
  527. while (currentSO != null)
  528. {
  529. if (currentSO.GetComponent<Rigidbody>() != null)
  530. {
  531. Debug.LogWarning("Nested Rigidbodies detected. This will result in inconsistent transformations. " +
  532. "To parent one Rigidbody to another move its colliders to the new parent, but remove the " +
  533. "Rigidbody component.");
  534. return;
  535. }
  536. currentSO = currentSO.Parent;
  537. }
  538. }
  539. /// <summary>
  540. /// Destroys the internal rigidbody representation.
  541. /// </summary>
  542. private void DestroyNative()
  543. {
  544. ClearColliders();
  545. if (native != null)
  546. {
  547. native.Destroy();
  548. native = null;
  549. }
  550. }
  551. /// <summary>
  552. /// Restores internal rigidbody representation and assigns it the properties stored by the component.
  553. /// </summary>
  554. private void RestoreNative()
  555. {
  556. native = new NativeRigidbody(SceneObject);
  557. native.Component = this;
  558. UpdateColliders();
  559. #if DEBUG
  560. CheckForNestedRigibody();
  561. #endif
  562. native.Position = SceneObject.Position;
  563. native.Rotation = SceneObject.Rotation;
  564. // Note: Merge into one call to avoid many virtual function calls
  565. native.PositionSolverCount = serializableData.positionSolverCount;
  566. native.VelocitySolverCount = serializableData.velocitySolverCount;
  567. native.MaxAngularVelocity = serializableData.maxAngularVelocity;
  568. native.Drag = serializableData.linearDrag;;
  569. native.AngularDrag = serializableData.angularDrag;
  570. native.SleepThreshold = serializableData.sleepThreshold;
  571. native.UseGravity = serializableData.useGravity;
  572. native.Kinematic = serializableData.isKinematic;
  573. native.Flags = serializableData.flags;
  574. if ((serializableData.flags & RigidbodyFlag.AutoTensors) == 0)
  575. {
  576. native.CenterOfMassPosition = serializableData.centerMassPosition;
  577. native.CenterOfMassRotation = serializableData.centerMassRotation;
  578. native.InertiaTensor = serializableData.inertiaTensor;
  579. native.Mass = serializableData.mass;
  580. }
  581. else
  582. {
  583. if ((serializableData.flags & RigidbodyFlag.AutoMass) == 0)
  584. native.Mass = serializableData.mass;
  585. native.UpdateMassDistribution();
  586. }
  587. }
  588. /// <summary>
  589. /// Holds all data the rigidbody component needs to persist through serialization.
  590. /// </summary>
  591. [SerializeObject]
  592. internal class SerializableData
  593. {
  594. public int positionSolverCount = 4;
  595. public int velocitySolverCount = 1;
  596. public RigidbodyFlag flags = RigidbodyFlag.AutoTensors | RigidbodyFlag.AutoMass;
  597. public CollisionReportMode collisionReportMode = CollisionReportMode.None;
  598. public Vector3 centerMassPosition = Vector3.Zero;
  599. public Quaternion centerMassRotation = Quaternion.Identity;
  600. public Vector3 inertiaTensor = Vector3.Zero;
  601. public float mass = 0.0f;
  602. public float maxAngularVelocity = 1.0f;
  603. public float linearDrag = 0.0f;
  604. public float angularDrag = 0.0f;
  605. public float sleepThreshold = 0.0f;
  606. public bool useGravity = true;
  607. public bool isKinematic = false;
  608. }
  609. }
  610. /// <summary>
  611. /// Type of force or torque that can be applied to a rigidbody.
  612. /// </summary>
  613. public enum ForceMode
  614. {
  615. /// <summary>
  616. /// Value applied is a force.
  617. /// </summary>
  618. Force,
  619. /// <summary>
  620. /// Value applied is an impulse (a direct change in its linear or angular momentum).
  621. /// </summary>
  622. Impulse,
  623. /// <summary>
  624. /// Value applied is velocity.
  625. /// </summary>
  626. Velocity,
  627. /// <summary>
  628. /// Value applied is accelearation.
  629. /// </summary>
  630. Acceleration
  631. }
  632. /// <summary>
  633. /// Type of force that can be applied to a rigidbody at an arbitrary point.
  634. /// </summary>
  635. public enum PointForceMode
  636. {
  637. /// <summary>
  638. /// Value applied is a force.
  639. /// </summary>
  640. Force,
  641. /// <summary>
  642. /// Value applied is an impulse (a direct change in its linear or angular momentum).
  643. /// </summary>
  644. Impulse,
  645. }
  646. /// <summary>
  647. /// Flags that control options of a Rigidbody object.
  648. /// </summary>
  649. [Flags]
  650. public enum RigidbodyFlag
  651. {
  652. /// <summary>
  653. /// No options.
  654. /// </summary>
  655. None = 0x00,
  656. /// <summary>
  657. /// Automatically calculate center of mass transform and inertia tensors from child shapes (colliders)
  658. /// </summary>
  659. AutoTensors = 0x01,
  660. /// <summary>
  661. /// Calculate mass distribution from child shapes (colliders). Only relevant when auto-tensors is on.
  662. /// </summary>
  663. AutoMass = 0x02,
  664. /// <summary>
  665. /// Enables continous collision detection. This can prevent fast moving bodies from tunneling through each other.
  666. /// This must also be enabled globally in Physics otherwise the flag will be ignored.
  667. /// </summary>
  668. CCD = 0x04
  669. }
  670. /** @} */
  671. }