Rigidbody.cs 28 KB

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