Prechádzať zdrojové kódy

Split the physics manual to make it more digestible

Björn Ritzl 4 rokov pred
rodič
commit
b2055cba33

+ 21 - 5
docs/en/en.json

@@ -280,7 +280,7 @@
                         "name": "Collection proxy"
                     },
                     {
-                        "path": "/manuals/physics",
+                        "path": "/manuals/physics-objects",
                         "name": "Collision object"
                     },
                     {
@@ -379,19 +379,35 @@
                 "items": [
                     {
                         "path": "/manuals/physics",
+                        "name": "Physics overview"
+                    },
+                    {
+                        "path": "/manuals/physics-objects",
                         "name": "Collision objects"
                     },
                     {
-                        "path": "/manuals/physics/#collision-shapes",
+                        "path": "/manuals/physics-shapes",
                         "name": "Collision shapes"
                     },
                     {
-                        "path": "/manuals/physics/#ray-casts",
+                        "path": "/manuals/physics-groups",
+                        "name": "Collision groups"
+                    },
+                    {
+                        "path": "/manuals/physics-messages",
+                        "name": "Collision messages"
+                    },
+                    {
+                        "path": "/manuals/physics-resolving-collisions",
+                        "name": "Resolving collisions"
+                    },
+                    {
+                        "path": "/manuals/physics-ray-casts",
                         "name": "Ray casts"
                     },
                     {
-                        "path": "/manuals/physics/#joints",
-                        "name": "Joints"
+                        "path": "/manuals/physics-joints",
+                        "name": "Joints and constraints"
                     }
                 ]
             },

+ 1 - 1
docs/en/manuals/flash.md

@@ -238,7 +238,7 @@ Now, bullets can collide with targets and other bullets. For reference, we have
 
 Note how the *Group* property is set to "target" and *Mask* is set to "bullet".
 
-In Flash, collision detection occurs only when explicitly called by the script. In Defold, collision detection occurs continuously in the background as long as a collision object remains enabled. When a collision occurs, messages are sent to all components of a game object (most relevantly, the script components). These are the [collision_response and contact_point_response](/manuals/physics/#collision-messages) messages, which contain all the information required to resolve the collision as desired.
+In Flash, collision detection occurs only when explicitly called by the script. In Defold, collision detection occurs continuously in the background as long as a collision object remains enabled. When a collision occurs, messages are sent to all components of a game object (most relevantly, the script components). These are the [collision_response and contact_point_response](/manuals/physics-messages) messages, which contain all the information required to resolve the collision as desired.
 
 The advantage of Defold collision detection is that it is more advanced than that of Flash, with the ability to detect collisions between relatively complex shapes with very little setup effort. Collision detection is automatic, meaning looping through the various objects in the different collision groups and explicitly performing hit tests is not required. The main drawback is that there is no equivalent to the Flash shapeFlag. However, for most uses combinations of the basic box and sphere shapes suffice. For more complex scenarios, custom shapes [are possible](//forum.defold.com/t/does-defold-support-only-three-shapes-for-collision-solved/1985).
 

+ 17 - 0
docs/en/manuals/physics-groups.md

@@ -0,0 +1,17 @@
+---
+title: Collision groups in Defold
+brief: The physics engine allows you to group your physics objects and filter how they should collide.
+---
+
+# Group and mask
+
+The physics engine allows you to group your physics objects and filter how they should collide. This is handled by named _collision groups_. For each collision object you create two properties control how the object collides with other objects, *Group* and *Mask*.
+
+For a collision between two objects to register both objects must mutually specify each other's groups in their *Mask* field.
+
+![Physics collision group](images/physics/collision_group.png){srcset="images/physics/[email protected] 2x"}
+
+The *Mask* field can contain multiple group names, allowing for complex interaction scenarios.
+
+## Detecting collisions
+When two collision objects with matching groups and masks collide the physics engine will generate [collision messages](/manuals/physics-messages) that can be used in games to react to collisions.

+ 55 - 0
docs/en/manuals/physics-joints.md

@@ -0,0 +1,55 @@
+---
+title: Physics joints in Defold
+brief: Defold supports joints for 2D physics. This manual explains how to create and work with joints.
+---
+
+# Joints
+
+Defold supports joints for 2D physics. A joint connects two collision objects using some kind of constraint. The supported joint types are:
+
+* Fixed (physics.JOINT_TYPE_FIXED) - A rope joint that restricts the maximum distance between two points. In Box2D referred to as a Rope joint.
+* Hinge (physics.JOINT_TYPE_HINGE) - A hinge joint specifies an anchor point on two collision objects and moves them so that the two collision objects are always in the same place, and the relative rotation of the collision objects is not restricted. The hinge joint can enable a motor with a defined maximum engine torque and speed. In Box2D referred to as a Revolute joint.
+* Spring (physics.JOINT_TYPE_SPRING) - A spring joint keeps two collision objects at a constant distance from each other. The spring joint can be made soft like a spring with a frequency and damping ratio. In Box2D referred to as a Distance joint.
+* Slider (physics.JOINT_TYPE_SLIDER) - A slider joint allows for relative translation of two collision objects along a specified axis and prevents relative rotation. In Box2D referred to as a Prismatic joint.
+
+## Creating joints
+
+Joints can currently only be created programmatically using [`physics.create_joint()`](/ref/physics/#physics.create_joint:joint_type-collisionobject_a-joint_id-position_a-collisionobject_b-position_b-[properties]):
+::: sidenote
+Editor support for creating joints is planned but no release date has been decided.
+:::
+
+```lua
+-- connect two collision objects with a fixed joint constraint (rope)
+physics.create_joint(physics.JOINT_TYPE_FIXED, "obj_a#collisionobject", "my_test_joint", vmath.vector3(10, 0, 0), "obj_b#collisionobject", vmath.vector3(0, 20, 0), { max_length = 20 })
+```
+
+The above will create a fixed joint with id `my_test_joint` connected between the two collision object `obj_a#collisionobject` and `obj_b#collisionobject`. The joint is connected 10 pixels to the left of the center of collision object `obj_a#collisionobject` and 20 pixels above the center of collision object `obj_b#collisionobject`. The maximum length of the joint is 20 pixels.
+
+## Destroying joints
+
+A joint can be destroyed using [`physics.destroy_joint()`](/ref/physics/#physics.destroy_joint:collisionobject-joint_id):
+
+```lua
+-- destroy a joint previously connected to the first collision object
+physics.destroy_joint("obj_a#collisionobject", "my_test_joint")
+```
+
+## Reading from and Updating joints
+
+The properties of a joint can be read using [`physics.get_joint_properties()`](/ref/physics/#physics.get_joint_properties:collisionobject-joint_id) and set using [`physics.set_joint_properties()`](/ref/physics/#physics.set_joint_properties:collisionobject-joint_id-properties):
+
+```lua
+function update(self, dt)
+    if self.accelerating then
+        local hinge_props = physics.get_joint_properties("obj_a#collisionobject", "my_hinge")
+        -- increase motor speed by 100 revolutions per second
+        hinge_props.motor_speed = hinge_props.motor_speed + 100 * 2 * math.pi * dt
+        physics.set_joint_properties("obj_a#collisionobject", "my_hinge", hinge_props)
+    end
+end
+```
+
+## Get joint reaction force and torque
+
+The reaction force and torque applied to a joint can be read using [`physics.get_joint_reaction_force()`](/ref/physics/#physics.get_joint_reaction_force:collisionobject-joint_id) and [`physics.get_joint_reaction_torque()`](/ref/physics/#physics.get_joint_reaction_torque:collisionobject-joint_id).

+ 75 - 0
docs/en/manuals/physics-messages.md

@@ -0,0 +1,75 @@
+---
+title: Collision messages in Defold
+brief: When two objects collide, the engine will broadcast messages to all components in both objects.
+---
+
+# Collision messages
+
+When two objects collide, the engine will broadcast messages to all components in both objects:
+
+## Collision response
+
+The `"collision_response"` message is sent for all collision objects. It has the following fields set:
+
+`other_id`
+: the id of the instance the collision object collided with (`hash`)
+
+`other_position`
+: the world position of the instance the collision object collided with (`vector3`)
+
+`other_group`
+: the collision group of the other collision object (`hash`)
+
+The collision_response message is only adequate to resolve collisions where you don't need any details on the actual intersection of the objects, for example if you want to detect if a bullet hits an enemy. There is only one of these messages sent for any colliding pair of objects each frame.
+
+## Contact point response
+
+The `"contact_point_response"` message is sent when one of the colliding objects is dynamic or kinematic. It has the following fields set:
+
+`position`
+: world position of the contact point (`vector3`).
+
+`normal`
+: normal in world space of the contact point, which points from the other object towards the current object (`vector3`).
+
+`relative_velocity`
+: the relative velocity of the collision object as observed from the other object (`vector3`).
+
+`distance`
+: the penetration distance between the objects -- non negative (`number`).
+
+`applied_impulse`
+: the impulse the contact resulted in (`number`).
+
+`life_time`
+: (*not currently used!*) life time of the contact (`number`).
+
+`mass`
+: the mass of the current collision object in kg (`number`).
+
+`other_mass`
+: the mass of the other collision object in kg (`number`).
+
+`other_id`
+: the id of the instance the collision object is in contact with (`hash`).
+
+`other_position`
+: the world position of the other collision object (`vector3`).
+
+`group`
+: the collision group of the other collision object (`hash`).
+
+For a game or application where you need to separate objects perfectly, the `"contact_point_response"` message gives you all information you need. However, note that for any given collision pair, several `"contact_point_response"` messages can be received each frame, depending on the nature of the collision. See [Resolving collisions for more information](/manuals/physics-resolving-collisions).
+
+## Trigger response
+
+The `"trigger_response"`  message is sent when a colliding object is of type "trigger".
+
+
+In a trigger collision `"collision_response"` messages are sent. In addition, triggers also send a special `"trigger_response"` message when the collision begins and ends. The message has the following fields:
+
+`other_id`
+: the id of the instance the collision object collided with (`hash`).
+
+`enter`
+: `true` if the interaction was an entry into the trigger, `false` if it was an exit. (`boolean`).

+ 110 - 0
docs/en/manuals/physics-objects.md

@@ -0,0 +1,110 @@
+---
+title: Collision objects in Defold
+brief: A collision object is a component you use to give a game object physical behaviour. A collision object has physical properties and a spatial shape.
+---
+
+# Collision objects
+
+A collision object is a component you use to give a game object physical behaviour. A collision object has physical properties like weight, restitution and friction and its spatial extension is defined by one or more _shapes_ that you attach to the component. Defold supports the following types of collision objects:
+
+Static objects
+: Static objects never move but a dynamic object that collides with a static object will react by bouncing and/or sliding. Static objects are very useful for building level geometry (i.e. ground and walls) that does not move. They are also cheaper performance-wise than dynamic objects. You cannot move or otherwise change static objects.
+
+Dynamic objects
+: Dynamic objects are simulated by the physics engine. The engine solves all collisions and applies resulting forces. Dynamic objects are good for objects that should behave realistically but you *cannot* directly manipulate the position and orientation of a dynamic object. The only way to affect them is indirectly, by [applying forces](/ref/physics/#apply_force) or changing the angular [damping](/ref/stable/physics/#angular_damping) and [velocity](/ref/stable/physics/#linear_velocity) and the linear [damping](/ref/stable/physics/#linear_damping) and [velocity](/ref/stable/physics/#angular_velocity).
+
+Kinematic objects
+: Kinematic objects register collisions with other physics objects, but the physics engine do not perform any automatic simulation. The job of resolving collisions, or ignoring them, is left to you. Kinematic objects are very good for player or script controlled objects that require fine grained control of the physical reactions, like a player character.
+
+Triggers
+: Triggers are objects that register simple collisions. Triggers are light weight collision objects. They are similar to [ray casts](/manuals/physics-ray-cast) in that they read the physics world as opposed to interacting with it. They are good for objects that just need to register a hit (like a bullet) or as part of game logic where you want to trigger certain actions when an object reaches a specific point. Trigger are computationally cheaper than kinematic objects and should be used in favor of those if possible.
+
+
+## Adding a collision object component
+
+A collision object component has a set of *Properties* that sets its type and physics properties. It also contains one or more *Shapes* that define the whole shape of the physics object.
+
+To add a collision object component to a game object:
+
+1. In the *Outline* view, <kbd>right click</kbd> the game object and select <kbd>Add Component ▸ Collision Object</kbd> from the context menu. This creates a new component with no shapes.
+2. <kbd>Right click</kbd> the new component and select <kbd>Add Shape ▸ Box / Capsule / Sphere</kbd>. This adds a new shape to the collision object component. You can add any number of shapes to the component. You can also use a tilemap or a convex hull to define the shape of the physics object.
+3. Use the move, rotate and scale tools to edit the shapes.
+4. Select the component in the *Outline* and edit the collision object's *Properties*.
+
+![Physics collision object](images/physics/collision_object.png){srcset="images/physics/[email protected] 2x"}
+
+
+## Adding a collision shape
+
+A collision component can either use several primitive shapes or a single complex shape. Learn more about the various shapes and how to add them to a collision component in the [Collision Shapes manual](/manuals/physics-shapes).
+
+
+## Collision object properties
+
+Id
+: The identity of the component.
+
+Collision Shape
+: This property is used for tile map geometry that does not use ordinary primitive shapes. See [Collision Shapes for more information](/manuals/physics-shapes).
+
+Type
+: The type of collision object: `Dynamic`, `Kinematic`, `Static` or `Trigger`. If you set the object to dynamic you _must_ set the *Mass* property to a non zero value. For dynamic or static objects you should also check that the *Friction* and *Restitution* values are good for your use-case.
+
+Friction
+: Friction makes it possible for objects to slide realistically against each other. The friction value is usually set between `0` (no friction at all---a very slippery object) and `1` (strong friction---an abrasive object). However, any positive value is valid.
+
+  The friction strength is proportional to the normal force (this is called Coulomb friction). When the friction force is computed between two shapes (`A` and `B`), the friction values of both objects are combined by the geometric mean:
+
+  $$
+  F_{combined} = \sqrt{ F_A \times F_B }
+  $$
+
+  This means that if one of the objects has zero friction then the contact between them will have zero friction.
+
+Restitution
+: The restitution value sets the "bounciness" of the object. The value is usually between 0 (inelastic collision—the object does not bounce at all) and 1 (perfectly elastic collision---the object's velocity will be exactly reflected in the bounce)
+
+  Restitution values between two shapes (`A` and `B`) are combined using the following formula:
+
+  $$
+  R = \max{ \left( R_A, R_B \right) }
+  $$
+
+  When a shape develops multiple contacts, restitution is simulated approximately because Box2D uses an iterative solver. Box2D also uses inelastic collisions when the collision velocity is small to prevent bounce-jitter
+
+Linear damping
+: Linear damping reduces the linear velocity of the body. It is different from friction, which only occurs during contact, and can be used to give objects a floaty appearance, like they are moving through something thicker than air. Valid values are between 0 and 1.
+
+  Box2D approximates damping for stability and performance. At small values, the damping effect is independent of the time step while at larger damping values, the damping effect varies with the time step. If you run your game with a fixed time step, this never becomes an issue.
+
+Angular damping
+: Angular damping works like linear damping but reduces the angular velocity of the body. Valid values are between 0 and 1.
+
+Locked rotation
+: Setting this property totally disables rotation on the collision object, no matter what forces are brought to it.
+
+Group
+: The name of the collison group the object should belong to. You can have 16 different groups and you name them as you see fit for your game. For example "players", "bullets", "enemies" and "world". If the *Collision Shape* is set to a tile map, this field is not used but the groups names are taken from the tile source. [Learn more about collision groups](/manuals/physics-groups).
+
+Mask
+: The other _groups_ this object should collide with. You can name one group or specify multiple groups in a comma separated list. If you leave the Mask field empty, the object will not collide with anything. [Learn more about collision groups](/manuals/physics-groups).
+
+
+## Runtime properties
+
+A physics object has a number of different properties that can be read and changed using `go.get()` and `go.set()`:
+
+`angular_damping`
+: The angular damping value for the collision object component (`number`). [API reference](/ref/physics/#angular_damping).
+
+`angular_velocity`
+: The current angular velocity of the collision object component (`vector3`). [API reference](/ref/physics/#angular_velocity).
+
+`linear_damping`
+: The linear damping value for the collision object (`number`). [API reference](/ref/physics/#linear_damping).
+
+`linear_velocity`
+: The current linear velocity of the collision object component (`vector3`). [API reference](/ref/physics/#linear_velocity).
+
+`mass`
+: The defined physical mass of the collision object component (`number`). [API reference](/ref/physics/#mass).

+ 29 - 0
docs/en/manuals/physics-ray-casts.md

@@ -0,0 +1,29 @@
+---
+title: Ray casts in Defold
+brief: Ray casts are used to read the physics world along a linear ray. This manual explains how this works.
+---
+
+## Ray casts
+
+Ray casts are used to read the physics world along a linear ray. To cast a ray into the physics world, you provide a start and end position as well as a set of collision groups to test against.
+
+If the ray hits a physics object you will get information about the object it hit. Rays intersect with dynamic, kinematic and static objects. They do not interact with triggers.
+
+```lua
+function update(self, dt)
+  -- request ray cast
+  local my_start = vmath.vector3(0, 0, 0)
+  local my_end = vmath.vector3(100, 1000, 1000)
+  local my_groups = { hash("my_group1"), hash("my_group2") }
+
+  local result = physics.raycast(my_start, my_end, my_groups)
+  if result then
+      -- act on the hit (see 'ray_cast_response' message for all values)
+      print(result.id)
+  end
+end
+```
+
+::: sidenote
+Ray casts will ignore collision objects that contain the starting point of the ray. This is a limitation in Box2D.
+:::

+ 87 - 0
docs/en/manuals/physics-resolving-collisions.md

@@ -0,0 +1,87 @@
+---
+title: Resolving kinematic collsions in Defold
+brief: This manual explains how to resolve kinematic physics collisions.
+---
+
+# Resolving kinematic collisions
+
+Using kinematic collision objects require you to resolve collisions yourself and move the objects as a reaction. A naive implementation of separating two colliding objects looks like this:
+
+```lua
+function on_message(self, message_id, message, sender)
+  -- Handle collision
+  if message_id == hash("contact_point_response") then
+    local newpos = go.get_position() + message.normal * message.distance
+    go.set_position(newpos)
+  end
+end
+```
+
+This code will separate your kinematic object from other physics object it penetrates, but the separation often overshoots and you will see jitter in many cases. To understand the problem better, consider the following case where a player character has collided with two objects, *A* and *B*:
+
+![Physics collision](images/physics/collision_multi.png){srcset="images/physics/[email protected] 2x"}
+
+The physics engine will send multiple `"contact_point_response"` message, one for object *A* and one for object *B* the frame the collision occurs. If you move the character in response to each penetration, as in the naive code above, the resulting separation would be:
+
+- Move the character out of object *A* according to its penetration distance (the black arrow)
+- Move the character out of object *B* according to its penetration distance (the black arrow)
+
+The order of these is arbitrary but the result is the same either way: a total separation that is the *sum of the individual penetration vectors*:
+
+![Physics separation naive](images/physics/separation_naive.png){srcset="images/physics/[email protected] 2x"}
+
+To properly separate the character from objects *A* and *B*, you need to handle each contact point's penetration distance and check if any previous separations have already, wholly or partially, solved the separation.
+
+Suppose that the first contact point message comes from object *A* and that you move the character out by *A*'s penetration vector:
+
+![Physics separation step 1](images/physics/separation_step1.png){srcset="images/physics/[email protected] 2x"}
+
+Then the character has already been partially separated from *B*. The final compensation necessary to perform full separation from object *B* is indicated by the black arrow above. The length of the compensation vector can be calculated by projecting the penetration vector of *A* onto the penetration vector of *B*:
+
+![Projection](images/physics/projection.png){srcset="images/physics/[email protected] 2x"}
+
+$$l = vmath.project(A, B) \times vmath.length(B)$$
+
+The compensation vector can be found by reducing the length of *B* by *l*. To calculate this for an arbitrary number of penetrations, you can accumulate the necessary correction in a vector by, for each contact point, and starting with a zero length correction vector:
+
+1. Project the current correction against the contact's penetration vector.
+2. Calculate what compensation is left from the penetration vector (as per the formula above).
+3. Move the object by the compensation vector.
+4. Add the compensation to the accumulated correction.
+
+A complete implementation looks like this:
+
+```lua
+function init(self)
+  -- correction vector
+  self.correction = vmath.vector3()
+end
+
+function update(self, dt)
+  -- reset correction
+  self.correction = vmath.vector3()
+end
+
+function on_message(self, message_id, message, sender)
+  -- Handle collision
+  if message_id == hash("contact_point_response") then
+    -- Get the info needed to move out of collision. We might
+    -- get several contact points back and have to calculate
+    -- how to move out of all of them by accumulating a
+    -- correction vector for this frame:
+    if message.distance > 0 then
+      -- First, project the accumulated correction onto
+      -- the penetration vector
+      local proj = vmath.project(self.correction, message.normal * message.distance)
+      if proj < 1 then
+        -- Only care for projections that does not overshoot.
+        local comp = (message.distance - message.distance * proj) * message.normal
+        -- Apply compensation
+        go.set_position(go.get_position() + comp)
+        -- Accumulate correction done
+        self.correction = self.correction + comp
+      end
+    end
+  end
+end
+```

+ 61 - 0
docs/en/manuals/physics-shapes.md

@@ -0,0 +1,61 @@
+---
+title: Collision shapes
+brief: A collision component can either use several primitive shapes or a single complex shape.
+---
+
+# Collision shapes
+
+A collision component can either use several primitive shapes or a single complex shape. The primitive shapes are *box*, *sphere* and *capsule*. A complex shape can either be created from a tilemap component or from a convex hull shape.
+
+## Box shape
+A box has a position, rotation and dimensions (width, height and depth):
+
+![Box shape](images/physics/box.png)
+
+## Sphere shape
+A sphere has a position, rotation and diameter:
+
+![Sphere shape](images/physics/sphere.png)
+
+## Capsule shape
+A capsule has a position, rotation, diameter and height:
+
+![Sphere shape](images/physics/capsule.png)
+
+## Tilemap collision shape
+Defold includes a feature allowing you to easily generate physics shapes for a tile map. The [Tilemap manual](/manuals/tilemap/) explains how to add collision groups to a tile source and assign tiles to collision groups ([example](/examples/tilemap/collisions/)).
+
+To add collision to a tile map:
+
+1. Add the tilemap to a game object by <kbd>right-clicking</kbd> the game object and selecting <kbd>Add Component File</kbd>. Select the tile map file.
+2. Add a collision object component to the game object by <kbd>right-clicking</kbd> the game object and selecting <kbd>Add Component ▸ Collision Object</kbd>.
+3. Instead of adding shapes to the component, set the *Collision Shape* property to the *tilemap* file.
+4. Set up the collision object component *Properties* as usual.
+
+![Tilesource collision](images/physics/collision_tilemap.png){srcset="images/physics/[email protected] 2x"}
+
+::: important
+Note that the *Group* property is **not** used here since the collision groups are defined in the tile map's tile source.
+:::
+
+## Convex hull shape
+Defold includes a feature allowing you to create a convex hull shape from three or more points. You can use an external tool such as the [Defold Polygon Editor](/assets/defoldpolygoneditor/) or the [Physics Body Editor](/assets/physicsbodyeditor/) to create a convex hull shape.
+
+1. Create convex hull shape file (file extension `.convexshape`) using an external editor.
+2. Instead of adding shapes to the collision object component, set the *Collision Shape* property to the *convex shape* file.
+
+::: sidenote
+The shape will not be drawn in the editor. You can [enable Physics debugging](/manuals/debugging/#debugging-problems-with-physics) at runtime to see the shape.
+:::
+
+
+# Scaling collision shapes
+It is possible to let the collision object and its shapes inherit the scale of the game object. Check the [Allow Dynamic Transforms](/manuals/project-settings/#allow-dynamic-transforms) checkbox in the Physics section of *game.project* to enable this. Note that only uniform scaling is supported and that the smallest scale value will be used if the scale isn't uniform.
+
+
+# Rotating collision shapes in 3D physics
+Collision shapes in 3D physics can be rotated around all axis.
+
+
+# Rotating collision shapes in 2D physics
+Collision shapes in 2D physics can only be rotated around the z-axis. Rotation around the x or y axis will yield incorrect results and should be avoided, even when rotating 180 degrees to essentially flip the shape along the x or y axis. To flip a physics shape it is recommended to use [`physics.set_hlip(url, flip)`](/ref/stable/physics/?#physics.set_hflip:url-flip) and [`physics.set_vlip(url, flip)`](/ref/stable/physics/?#physics.set_vflip:url-flip).

+ 10 - 397
docs/en/manuals/physics.md

@@ -1,420 +1,33 @@
 ---
 title: Physics in Defold
-brief: Defold includes physics engines for 2D and 3D. They allow you to simulate Newtonian physics interactions between different types of collision objects. This manual explains how this works.
+brief: Defold includes physics engines for 2D and 3D. They allow you to simulate Newtonian physics interactions between different types of collision objects.
 ---
 
 # Physics
 
 Defold includes a modified version of the [Box2D](http://www.box2d.org) physics engine (version 2.1) for 2D physics simulations and the Bullet physics engine (version 2.77) for 3D physics. It allows you to simulate Newtonian physics interactions between different types of _collision objects_. This manual explains how this works.
 
-## Collision objects
+The main concepts of the physics engines used in Defold are:
 
-A collision object is a component you use to give a game object physical behaviour. A collision object has physical properties like weight, restitution and friction and its spatial extension is defined by one or more _shapes_ that you attach to the component. Defold supports the following types of collision objects:
+* Collision objects - A collision object is a component you use to give a game object physical behaviour. A collision object has physical properties like weight, friction and shape. [Learn how to create a collision object](/manuals/physics-objects).
+* Collision shapes - A collision object can either use several primitive shapes or a single complex shape to define its spatial extension. [Learn how to add shapes to a collision object](/manuals/physics-shapes).
+* Collision groups - All collision objects must belong to a predefined group and each collision object can specify a list of other groups it can collide with. [Learn how to use collision groups](/manuals/physics-groups).
+* Collision messages - When two collision objects collide the physics engine send messages to the game objects the components belong to. [Learn more about collision messages](/manuals/physics-messages)
 
-Static objects
-: Static objects never move but a dynamic object that collides with a static object will react by bouncing and/or sliding. Static objects are very useful for building level geometry (i.e. ground and walls) that does not move. They are also cheaper performance-wise than dynamic objects. You cannot move or otherwise change static objects.
+In addition to the collision objects themselves you can also define collision object constraints, more commonly known as joints, to connect two collision objects and limit or in other ways apply force and influence how they behave in the physics simulation. [Learn more about joins](/manuals/physics-joints).
 
-Dynamic objects
-: Dynamic objects are simulated by the physics engine. The engine solves all collisions and applies resulting forces. Dynamic objects are good for objects that should behave realistically but you *cannot* directly manipulate the position and orientation of a dynamic object. The only way to affect them is indirectly, by [applying forces](/ref/physics/#apply_force).
+You can also probe and read the physics world along a linear ray know as ray casts. [Learn more about ray casts](/manuals/physics-ray-casts).
 
-Kinematic objects
-: Kinematic objects register collisions with other physics objects, but the physics engine do not perform any automatic simulation. The job of resolving collisions, or ignoring them, is left to you. Kinematic objects are very good for player or script controlled objects that require fine grained control of the physical reactions, like a player character.
 
-Triggers
-: Triggers are objects that register simple collisions. They are good for objects that just need to register a hit (like a bullet) or as part of game logic where you want to trigger certain actions when an object reaches a specific point. Trigger are computationally cheaper than kinematic objects and should be used in favor of those if possible.
-
-## Adding a collision object component
-
-A collision object component has a set of *Properties* that sets its type and physics properties. It also contains one or more *Shapes* that define the whole shape of the physics object.
-
-To add a collision object component to a game object:
-
-1. In the *Outline* view, <kbd>right click</kbd> the game object and select <kbd>Add Component ▸ Collision Object</kbd> from the context menu. This creates a new component with no shapes.
-2. <kbd>Right click</kbd> the new component and select <kbd>Add Shape ▸ Box / Capsule / Sphere</kbd>. This adds a new shape to the collision object component. You can add any number of shapes to the component. You can also use a tilemap or a convex hull to define the shape of the physics object.
-3. Use the move, rotate and scale tools to edit the shapes.
-4. Select the component in the *Outline* and edit the collision object's *Properties*.
-
-![Physics collision object](images/physics/collision_object.png){srcset="images/physics/[email protected] 2x"}
-
-
-## Collision object properties
-
-Id
-: The identity of the component.
-
-Collision Shape
-: This property is used for tile map geometry that does not use ordinary primitive shapes. See below for more information.
-
-Type
-: The type of collision object: `Dynamic`, `Kinematic`, `Static` or `Trigger`. If you set the object to dynamic you _must_ set the *Mass* property to a non zero value. For dynamic or static objects you should also check that the *Friction* and *Restitution* values are good for your use-case.
-
-Friction
-: Friction makes it possible for objects to slide realistically against each other. The friction value is usually set between `0` (no friction at all---a very slippery object) and `1` (strong friction---an abrasive object). However, any positive value is valid.
-
-  The friction strength is proportional to the normal force (this is called Coulomb friction). When the friction force is computed between two shapes (`A` and `B`), the friction values of both objects are combined by the geometric mean:
-
-  $$
-  F_{combined} = \sqrt{ F_A \times F_B }
-  $$
-
-  This means that if one of the objects has zero friction then the contact between them will have zero friction.
-
-Restitution
-: The restitution value sets the "bounciness" of the object. The value is usually between 0 (inelastic collision—the object does not bounce at all) and 1 (perfectly elastic collision---the object's velocity will be exactly reflected in the bounce)
-
-  Restitution values between two shapes (`A` and `B`) are combined using the following formula:
-
-  $$
-  R = \max{ \left( R_A, R_B \right) }
-  $$
-
-  When a shape develops multiple contacts, restitution is simulated approximately because Box2D uses an iterative solver. Box2D also uses inelastic collisions when the collision velocity is small to prevent bounce-jitter
-
-Linear damping
-: Linear damping reduces the linear velocity of the body. It is different from friction, which only occurs during contact, and can be used to give objects a floaty appearance, like they are moving through something thicker than air. Valid values are between 0 and 1.
-
-  Box2D approximates damping for stability and performance. At small values, the damping effect is independent of the time step while at larger damping values, the damping effect varies with the time step. If you run your game with a fixed time step, this never becomes an issue.
-
-Angular damping
-: Angular damping works like linear damping but reduces the angular velocity of the body. Valid values are between 0 and 1.
-
-Locked rotation
-: Setting this property totally disables rotation on the collision object, no matter what forces are brought to it.
-
-Group
-: The name of the collison group the object should belong to. You can have 16 different groups and you name them as you see fit for your game. For example "players", "bullets", "enemies" and "world". If the *Collision Shape* is set to a tile map, this field is not used but the groups names are taken from the tile source.
-
-Mask
-: The other _groups_ this object should collide with. You can name one group or specify multiple groups in a comma separated list. If you leave the Mask field empty, the object will not collide with anything.
-
-
-## Collision shapes
-
-A collision component can either use several primitive shapes or a single complex shape. The primitive shapes are *box*, *sphere* and *capsule*. A complex shape can either be created from a tilemap component or from a convex hull shape.
-
-### Box shape
-A box has a position, rotation and dimensions (width, height and depth):
-
-![Box shape](images/physics/box.png)
-
-### Sphere shape
-A sphere has a position, rotation and diameter:
-
-![Sphere shape](images/physics/sphere.png)
-
-### Capsule shape
-A capsule has a position, rotation, diameter and height:
-
-![Sphere shape](images/physics/capsule.png)
-
-### Tilemap collision shape
-Defold includes a feature allowing you to easily generate physics shapes for a tile map. The [Tilemap manual](/manuals/tilemap/) explains how to add collision groups to a tile source and assign tiles to collision groups ([example](/examples/tilemap/collisions/)).
-
-To add collision to a tile map:
-
-1. Add the tilemap to a game object by <kbd>right-clicking</kbd> the game object and selecting <kbd>Add Component File</kbd>. Select the tile map file.
-2. Add a collision object component to the game object by <kbd>right-clicking</kbd> the game object and selecting <kbd>Add Component ▸ Collision Object</kbd>.
-3. Instead of adding shapes to the component, set the *Collision Shape* property to the *tilemap* file.
-4. Set up the collision object component *Properties* as usual.
-
-![Tilesource collision](images/physics/collision_tilemap.png){srcset="images/physics/[email protected] 2x"}
-
-::: important
-Note that the *Group* property is **not** used here since the collision groups are defined in the tile map's tile source.
-:::
-
-### Convex hull shape
-Defold includes a feature allowing you to create a convex hull shape from three or more points. You can use an external tool such as the [Defold Polygon Editor](/assets/defoldpolygoneditor/) or the [Physics Body Editor](/assets/physicsbodyeditor/) to create a convex hull shape.
-
-1. Create convex hull shape file (file extension `.convexshape`) using an external editor.
-2. Instead of adding shapes to the collision object component, set the *Collision Shape* property to the *convex shape* file.
-
-::: sidenote
-The shape will not be drawn in the editor. You can [enable Physics debugging](/manuals/debugging/#debugging-problems-with-physics) at runtime to see the shape.
-:::
-
-
-### Scaling collision shapes
-
-It is possible to let the collision object and its shapes inherit the scale of the game object. Check the [Allow Dynamic Transforms](/manuals/project-settings/#allow-dynamic-transforms) checkbox in the Physics section of *game.project* to enable this. Note that only uniform scaling is supported and that the smallest scale value will be used if the scale isn't uniform.
-
-
-### Rotating collision shapes in 3D physics
-Collision shapes in 3D physics can be rotated around all axis.
-
-
-### Rotating collision shapes in 2D physics
-Collision shapes in 2D physics can only be rotated around the z-axis. Rotation around the x or y axis will yield incorrect results and should be avoided, even when rotating 180 degrees to essentially flip the shape along the x or y axis. To flip a physics shape it is recommended to use [`physics.set_hlip(url, flip)`](/ref/stable/physics/?#physics.set_hflip:url-flip) and [`physics.set_vlip(url, flip)`](/ref/stable/physics/?#physics.set_vflip:url-flip).
-
-
-### Units used by the physics engine simulation
+## Units used by the physics engine simulation
 
 The physics engine simulates Newtonian physics and it is designed to work well with meters, kilograms and seconds (MKS) units. Furthermore, the physics engine is tuned to work well with moving objects of a size in the 0.1 to 10 meters range (static objects can be larger) and by default the engine treats 1 unit (pixel) as 1 meter. This conversion between pixels and meters is convenient on a simulation level, but from a game creation perspective it isn't very useful. With default settings a collision shape with a size of 200 pixels would be treated as having a size of 200 meters which is well outside of the recommended range, at least for a moving object. In general it is required that the physics simulation is scaled for it to work well with the typical size of objects in a game. The scale of the physics simulation can be changed in `game.project` via the [physics scale setting](/manuals/project-settings/#physics). Setting this value to for instance 0.02 would mean that 200 pixels would be treated as a 4 meters. Do note that the gravity (also changed in `game.project`) has to be increased to accommodate for the change in scale.
 
-## Group and mask
-
-The physics engine allows you to group your physics objects and filter how they should collide. This is handled by named _collision groups_. For each collision object you create two properties control how the object collides with other objects, *Group* and *Mask*.
-
-For a collision between two objects to register both objects must mutually specify each other's groups in their *Mask* field.
-
-![Physics collision group](images/physics/collision_group.png){srcset="images/physics/[email protected] 2x"}
-
-The *Mask* field can contain multiple group names, allowing for complex interaction scenarios.
-
-## Runtime properties
-
-A physics object has a number of different properties that can be read and changed using `go.get()` and `go.set()`:
-
-`angular_damping`
-: The angular damping value for the collision object component (`number`). [API reference](/ref/physics/#angular_damping).
-
-`angular_velocity`
-: The current angular velocity of the collision object component (`vector3`). [API reference](/ref/physics/#angular_velocity).
-
-`linear_damping`
-: The linear damping value for the collision object (`number`). [API reference](/ref/physics/#linear_damping).
-
-`linear_velocity`
-: The current linear velocity of the collision object component (`vector3`). [API reference](/ref/physics/#linear_velocity).
-
-`mass`
-: The defined physical mass of the collision object component (`number`). [API reference](/ref/physics/#mass).
-
-
-## Collision messages
-
-When two objects collide, the engine will broadcast messages to all components in both objects:
-
-**`"collision_response"`**
-
-This message is sent for all collision objects. It has the following fields set:
-
-`other_id`
-: the id of the instance the collision object collided with (`hash`)
-
-`other_position`
-: the world position of the instance the collision object collided with (`vector3`)
-
-`other_group`
-: the collision group of the other collision object (`hash`)
-
-The collision_response message is only adequate to resolve collisions where you don't need any details on the actual intersection of the objects, for example if you want to detect if a bullet hits an enemy. There is only one of these messages sent for any colliding pair of objects each frame.
-
-**`"contact_point_response"`**
-
-This message is sent when one of the colliding objects is dynamic or kinematic. It has the following fields set:
-
-`position`
-: world position of the contact point (`vector3`).
-
-`normal`
-: normal in world space of the contact point, which points from the other object towards the current object (`vector3`).
-
-`relative_velocity`
-: the relative velocity of the collision object as observed from the other object (`vector3`).
-
-`distance`
-: the penetration distance between the objects -- non negative (`number`).
-
-`applied_impulse`
-: the impulse the contact resulted in (`number`).
-
-`life_time`
-: (*not currently used!*) life time of the contact (`number`).
-
-`mass`
-: the mass of the current collision object in kg (`number`).
-
-`other_mass`
-: the mass of the other collision object in kg (`number`).
-
-`other_id`
-: the id of the instance the collision object is in contact with (`hash`).
-
-`other_position`
-: the world position of the other collision object (`vector3`).
-
-`group`
-: the collision group of the other collision object (`hash`).
-
-For a game or application where you need to separate objects perfectly, the `"contact_point_response"` message gives you all information you need. However, note that for any given collision pair, several `"contact_point_response"` messages can be received each frame, depending on the nature of the collision. See below for more information.
-
-## Trigger messages
-
-Triggers are light weight collision objects. Thay are similar to ray casts in that they read the physics world as opposed to interacting with it.
-
-In a trigger collision `"collision_response"` messages are sent. In addition, triggers also send a special `"trigger_response"` message when the collision begins and ends. The message has the following fields:
-
-`other_id`
-: the id of the instance the collision object collided with (`hash`).
-
-`enter`
-: `true` if the interaction was an entry into the trigger, `false` if it was an exit. (`boolean`).
-
-## Resolving kinematic collisions
-
-Using kinematic collision objects require you to resolve collisions yourself and move the objects as a reaction. A naive implementation of separating two colliding objects looks like this:
-
-```lua
-function on_message(self, message_id, message, sender)
-  -- Handle collision
-  if message_id == hash("contact_point_response") then
-    local newpos = go.get_position() + message.normal * message.distance
-    go.set_position(newpos)
-  end
-end
-```
-
-This code will separate your kinematic object from other physics object it penetrates, but the separation often overshoots and you will see jitter in many cases. To understand the problem better, consider the following case where a player character has collided with two objects, *A* and *B*:
-
-![Physics collision](images/physics/collision_multi.png){srcset="images/physics/[email protected] 2x"}
-
-The physics engine will send multiple `"contact_point_response"` message, one for object *A* and one for object *B* the frame the collision occurs. If you move the character in response to each penetration, as in the naive code above, the resulting separation would be:
-
-- Move the character out of object *A* according to its penetration distance (the black arrow)
-- Move the character out of object *B* according to its penetration distance (the black arrow)
-
-The order of these is arbitrary but the result is the same either way: a total separation that is the *sum of the individual penetration vectors*:
-
-![Physics separation naive](images/physics/separation_naive.png){srcset="images/physics/[email protected] 2x"}
-
-To properly separate the character from objects *A* and *B*, you need to handle each contact point's penetration distance and check if any previous separations have already, wholly or partially, solved the separation.
-
-Suppose that the first contact point message comes from object *A* and that you move the character out by *A*'s penetration vector:
-
-![Physics separation step 1](images/physics/separation_step1.png){srcset="images/physics/[email protected] 2x"}
-
-Then the character has already been partially separated from *B*. The final compensation necessary to perform full separation from object *B* is indicated by the black arrow above. The length of the compensation vector can be calculated by projecting the penetration vector of *A* onto the penetration vector of *B*:
-
-![Projection](images/physics/projection.png){srcset="images/physics/[email protected] 2x"}
-
-$$l = vmath.project(A, B) \times vmath.length(B)$$
-
-The compensation vector can be found by reducing the length of *B* by *l*. To calculate this for an arbitrary number of penetrations, you can accumulate the necessary correction in a vector by, for each contact point, and starting with a zero length correction vector:
-
-1. Project the current correction against the contact's penetration vector.
-2. Calculate what compensation is left from the penetration vector (as per the formula above).
-3. Move the object by the compensation vector.
-4. Add the compensation to the accumulated correction.
-
-A complete implementation looks like this:
-
-```lua
-function init(self)
-  -- correction vector
-  self.correction = vmath.vector3()
-end
-
-function update(self, dt)
-  -- reset correction
-  self.correction = vmath.vector3()
-end
-
-function on_message(self, message_id, message, sender)
-  -- Handle collision
-  if message_id == hash("contact_point_response") then
-    -- Get the info needed to move out of collision. We might
-    -- get several contact points back and have to calculate
-    -- how to move out of all of them by accumulating a
-    -- correction vector for this frame:
-    if message.distance > 0 then
-      -- First, project the accumulated correction onto
-      -- the penetration vector
-      local proj = vmath.project(self.correction, message.normal * message.distance)
-      if proj < 1 then
-        -- Only care for projections that does not overshoot.
-        local comp = (message.distance - message.distance * proj) * message.normal
-        -- Apply compensation
-        go.set_position(go.get_position() + comp)
-        -- Accumulate correction done
-        self.correction = self.correction + comp
-      end
-    end
-  end
-end
-```
-
-## Ray casts
-
-Ray casts are used to read the physics world along a linear ray. To cast a ray into the physics world, you provide a start and end position as well as a set of collision groups to test against.
-
-If the ray hits a physics object you will get information about the object it hit. Rays intersect with dynamic, kinematic and static objects. They do not interact with triggers.
-
-```lua
-function update(self, dt)
-  -- request ray cast
-  local my_start = vmath.vector3(0, 0, 0)
-  local my_end = vmath.vector3(100, 1000, 1000)
-  local my_groups = { hash("my_group1"), hash("my_group2") }
-
-  local result = physics.raycast(my_start, my_end, my_groups)
-  if result then
-      -- act on the hit (see 'ray_cast_response' message for all values)
-      print(result.id)
-  end
-end
-```
-
-::: sidenote
-Ray casts will ignore collision objects that contain the starting point of the ray. This is a limitation in Box2D.
-:::
-
-## Joints
-
-Defold supports joints for 2D physics. A joint connects two collision objects using some kind of constraint. The supported joint types are:
-
-* Fixed (physics.JOINT_TYPE_FIXED) - A rope joint that restricts the maximum distance between two points. In Box2D referred to as a Rope joint.
-* Hinge (physics.JOINT_TYPE_HINGE) - A hinge joint specifies an anchor point on two collision objects and moves them so that the two collision objects are always in the same place, and the relative rotation of the collision objects is not restricted. The hinge joint can enable a motor with a defined maximum engine torque and speed. In Box2D referred to as a Revolute joint.
-* Spring (physics.JOINT_TYPE_SPRING) - A spring joint keeps two collision objects at a constant distance from each other. The spring joint can be made soft like a spring with a frequency and damping ratio. In Box2D referred to as a Distance joint.
-* Slider (physics.JOINT_TYPE_SLIDER) - A slider joint allows for relative translation of two collision objects along a specified axis and prevents relative rotation. In Box2D referred to as a Prismatic joint.
-
-### Creating joints
-
-Joints can currently only be created programmatically using [`physics.create_joint()`](/ref/physics/#physics.create_joint:joint_type-collisionobject_a-joint_id-position_a-collisionobject_b-position_b-[properties]):
-::: sidenote
-Editor support for creating joints is planned but no release date has been decided.
-:::
-
-```lua
--- connect two collision objects with a fixed joint constraint (rope)
-physics.create_joint(physics.JOINT_TYPE_FIXED, "obj_a#collisionobject", "my_test_joint", vmath.vector3(10, 0, 0), "obj_b#collisionobject", vmath.vector3(0, 20, 0), { max_length = 20 })
-```
-
-The above will create a fixed joint with id `my_test_joint` connected between the two collision object `obj_a#collisionobject` and `obj_b#collisionobject`. The joint is connected 10 pixels to the left of the center of collision object `obj_a#collisionobject` and 20 pixels above the center of collision object `obj_b#collisionobject`. The maximum length of the joint is 20 pixels.
-
-### Destroying joints
-
-A joint can be destroyed using [`physics.destroy_joint()`](/ref/physics/#physics.destroy_joint:collisionobject-joint_id):
-
-```lua
--- destroy a joint previously connected to the first collision object
-physics.destroy_joint("obj_a#collisionobject", "my_test_joint")
-```
-
-### Reading from and Updating joints
-
-The properties of a joint can be read using [`physics.get_joint_properties()`](/ref/physics/#physics.get_joint_properties:collisionobject-joint_id) and set using [`physics.set_joint_properties()`](/ref/physics/#physics.set_joint_properties:collisionobject-joint_id-properties):
-
-```lua
-function update(self, dt)
-    if self.accelerating then
-        local hinge_props = physics.get_joint_properties("obj_a#collisionobject", "my_hinge")
-        -- increase motor speed by 100 revolutions per second
-        hinge_props.motor_speed = hinge_props.motor_speed + 100 * 2 * math.pi * dt
-        physics.set_joint_properties("obj_a#collisionobject", "my_hinge", hinge_props)
-    end
-end
-```
-
-### Get joint reaction force and torque
-
-The reaction force and torque applied to a joint can be read using [`physics.get_joint_reaction_force()`](/ref/physics/#physics.get_joint_reaction_force:collisionobject-joint_id) and [`physics.get_joint_reaction_torque()`](/ref/physics/#physics.get_joint_reaction_torque:collisionobject-joint_id).
-
 
 ## Caveats and common issues
 
 Collection proxies
-: Through collection proxies it is possible to load more than one top level collection, or *game world* into the engine. When doing so it is important to know that each top level collection is a separate physical world. Physics interactions (collisions, triggers, ray-casts) only happen between objects belonging to the same world. So even if the collision objects from two worlds visually sits right on top of each other, there cannot be any physics interaction between them.
+: Through collection proxies it is possible to load more than one top level collection, or *game world* into the engine. When doing so it is important to know that each top level collection is a separate physical world. Physics interactions ([collisions, triggers](/manuals/physics-messages) and [ray-casts](/manuals/physics-ray-casts)) only happen between objects belonging to the same world. So even if the collision objects from two worlds visually sits right on top of each other, there cannot be any physics interaction between them.
 
 Collisions not detected
 : If you have problems with collisions not being handled or detected properly then make sure to read up on [physics debugging in the Debugging manual](/manuals/debugging/#debugging-problems-with-physics).