|
@@ -1,26 +1,86 @@
|
|
|
-# Raycasting
|
|
|
|
|
|
|
+# Physics Queries
|
|
|
|
|
|
|
|
<span class="badge text-bg-primary">Intermediate</span>
|
|
<span class="badge text-bg-primary">Intermediate</span>
|
|
|
<span class="badge text-bg-success">Programmer</span>
|
|
<span class="badge text-bg-success">Programmer</span>
|
|
|
|
|
|
|
|
-> [!WARNING]
|
|
|
|
|
-> This page is outdated, the information contained therein are for Bullet, the previous physics engine
|
|
|
|
|
|
|
+**Physics Queries** are a set of operation to test and retrieve physics object in a given simulation, the most well known form of those queries is the `RayCast` which traces an invisible line through the scene to find intersecting [Collidables](colliders.md). This is useful, for example, to check which objects are in a gun's line of fire, or are under the mouse cursor when the user clicks.
|
|
|
|
|
|
|
|
-**Raycasting** traces an invisible line through the scene to find intersecting [colliders](colliders.md). This is useful, for example, to check which objects are in a gun's line of fire, or are under the mouse cursor when the user clicks.
|
|
|
|
|
|
|
+> [!Note]
|
|
|
|
|
+> Physics queries uses **collider shapes** to find objects. It ignores entities that have no Collidable Component attached or no collider shape set, see [Collidables](colliders.md).
|
|
|
|
|
|
|
|
->[!Note]
|
|
|
|
|
->Raycasting uses **colliders** to calculate intersections. It ignores entities that have no collider component. For more information, see [Colliders](colliders.md).
|
|
|
|
|
-
|
|
|
|
|
-To use a raycast, in the current [Simulation](xref:Stride.Physics.Simulation), use [Simulation.Raycast](xref:Stride.Physics.Simulation.Raycast(Stride.Core.Mathematics.Vector3,Stride.Core.Mathematics.Vector3,Stride.Physics.CollisionFilterGroups,Stride.Physics.CollisionFilterGroupFlags,System.Boolean,Stride.Physics.EFlags)).
|
|
|
|
|
|
|
+To raycast in the current [Simulation](xref:Stride.BepuPhysics.BepuSimulation), see the [Simulation API](xref:Stride.BepuPhysics.BepuSimulation).
|
|
|
|
|
|
|
|
For an example of raycasting, see the **Physics Sample** project included with Stride.
|
|
For an example of raycasting, see the **Physics Sample** project included with Stride.
|
|
|
|
|
|
|
|
-## Example code
|
|
|
|
|
|
|
+## Examples
|
|
|
|
|
+On left click, if there is a 'HostileUnit' in front of 'MyGun', deal damage to it
|
|
|
|
|
+```cs
|
|
|
|
|
+public override void Update()
|
|
|
|
|
+{
|
|
|
|
|
+ var simulation = Entity.GetSimulation();
|
|
|
|
|
+ MyGun.Transform.GetWorldTransformation(out var rayStart, out var worldRot, out _);
|
|
|
|
|
+ var rayDir = worldRot * Vector3.UnitZ;
|
|
|
|
|
+ float range = 10;
|
|
|
|
|
+ // All layers except 0 & 1
|
|
|
|
|
+ var layers = CollisionMask.Everything & ~(CollisionMask.Layer0 | CollisionMask.Layer1);
|
|
|
|
|
+
|
|
|
|
|
+ if (Input.IsMouseButtonPressed(MouseButton.Left) && simulation.RayCast(rayStart, rayDir, range, out HitInfo hitResult, layers))
|
|
|
|
|
+ {
|
|
|
|
|
+ var hostile = hitResult.Collidable.Entity.Get<HostileUnit>();
|
|
|
|
|
+ if (hostile is not null)
|
|
|
|
|
+ hostile.DealDamage(10);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+Using the non-alloc version of a penetrating query to find multiple objects intersecting with the ray
|
|
|
|
|
+```cs
|
|
|
|
|
+var simulation = Entity.GetSimulation();
|
|
|
|
|
+Entity.Transform.GetWorldTransformation(out var rayStart, out var worldRot, out _);
|
|
|
|
|
+var rayDir = worldRot * Vector3.UnitZ;
|
|
|
|
|
+
|
|
|
|
|
+// Allocates a working buffer on the stack for the penetrating test,
|
|
|
|
|
+// The 16 specified here would be the maximum item this test would keep track of,
|
|
|
|
|
+// if the test finds more than 16 objects, it will yield the 16 closest ones
|
|
|
|
|
+System.Span<HitInfoStack> buffer = stackalloc HitInfoStack[16];
|
|
|
|
|
+
|
|
|
|
|
+// The order in which elements are yielded throughout this foreach is not guaranteed
|
|
|
|
|
+// Some hitInfo with a smaller distance may be returned after one with a larger one,
|
|
|
|
|
+// and the opposite is also true.
|
|
|
|
|
+foreach (var hitInfo in simulation.RayCastPenetrating(rayStart, rayDir, 100f, buffer))
|
|
|
|
|
+{
|
|
|
|
|
+ Log.Warning($"T: {hitInfo.Distance}\nNormal: {hitInfo.Normal}\nEntity : {hitInfo.Collidable.Entity}");
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+Moves a box through the scene and return what it collided with
|
|
|
|
|
+```cs
|
|
|
|
|
+var simulation = Entity.GetSimulation();
|
|
|
|
|
+Entity.Transform.GetWorldTransformation(out var center, out var worldRot, out _);
|
|
|
|
|
+var rayDir = worldRot * Vector3.UnitZ;
|
|
|
|
|
+var initialPose = new RigidPose(center, worldRot);
|
|
|
|
|
+var displacement = new BodyVelocity(rayDir, default);
|
|
|
|
|
+var shape = new Box(0.25f, 0.25f, 0.25f);
|
|
|
|
|
|
|
|
-This code sends a raycast from the mouse's screen position:
|
|
|
|
|
|
|
+if (simulation.SweepCast(shape, initialPose, displacement, 10, out HitInfo hitInfo))
|
|
|
|
|
+{
|
|
|
|
|
+ Log.Warning($"T: {hitInfo.Distance}\nNormal: {hitInfo.Normal}\nEntity : {hitInfo.Collidable.Entity}");
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+Find up to 16 physics object a box placed at that position would overlap with
|
|
|
|
|
+```cs
|
|
|
|
|
+var simulation = Entity.GetSimulation();
|
|
|
|
|
+Entity.Transform.GetWorldTransformation(out var center, out var worldRot, out _);
|
|
|
|
|
+var initialPose = new RigidPose(center, worldRot);
|
|
|
|
|
+var shape = new Box(0.25f, 0.25f, 0.25f);
|
|
|
|
|
|
|
|
|
|
+System.Span<CollidableStack> buffer = stackalloc CollidableStack[16];
|
|
|
|
|
+foreach (var hit in simulation.Overlap(shape, initialPose, buffer))
|
|
|
|
|
+{
|
|
|
|
|
+ Log.Warning($"Entity : {hit.Entity}");
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+Send a raycast from the mouse's screen position:
|
|
|
```cs
|
|
```cs
|
|
|
-public static bool ScreenPositionToWorldPositionRaycast(Vector2 screenPos, CameraComponent camera, Simulation simulation)
|
|
|
|
|
|
|
+public static bool ScreenPositionToWorldPositionRaycast(Vector2 screenPos, CameraComponent camera)
|
|
|
{
|
|
{
|
|
|
Matrix invViewProj = Matrix.Invert(camera.ViewProjectionMatrix);
|
|
Matrix invViewProj = Matrix.Invert(camera.ViewProjectionMatrix);
|
|
|
|
|
|
|
@@ -44,17 +104,19 @@ public static bool ScreenPositionToWorldPositionRaycast(Vector2 screenPos, Camer
|
|
|
var vectorFar = Vector3.Transform(sPos, invViewProj);
|
|
var vectorFar = Vector3.Transform(sPos, invViewProj);
|
|
|
vectorFar /= vectorFar.W;
|
|
vectorFar /= vectorFar.W;
|
|
|
|
|
|
|
|
|
|
+ var delta = (vectorFar - vectorNear).XYZ();
|
|
|
|
|
+ var maxDistance = delta.Length();
|
|
|
|
|
+ var dir = delta / maxDistance; // normalize delta
|
|
|
|
|
+
|
|
|
// Raycast from the point on the near plane to the point on the far plane and get the collision result
|
|
// Raycast from the point on the near plane to the point on the far plane and get the collision result
|
|
|
- var result = simulation.Raycast(vectorNear.XYZ(), vectorFar.XYZ());
|
|
|
|
|
- return result.Succeeded;
|
|
|
|
|
|
|
+ return camera.Entity.GetSimulation().RayCast(vectorNear.XYZ(), dir, maxDistance, out HitInfo hit);
|
|
|
}
|
|
}
|
|
|
```
|
|
```
|
|
|
|
|
|
|
|
>[!Note]
|
|
>[!Note]
|
|
|
>There are multiple ways to retrieve a reference to this `Simulation` from inside one of your `ScriptComponent`:
|
|
>There are multiple ways to retrieve a reference to this `Simulation` from inside one of your `ScriptComponent`:
|
|
|
->- The recommended way is through a reference to a physics component, something like `myRigidBody.Simulation` or `myCollision.Simulation` as it is the fastest.
|
|
|
|
|
->- Then through `SceneSystem` by calling `SceneSystem.SceneInstance.GetProcessor<PhysicsProcessor>()?.Simulation`.
|
|
|
|
|
->- Or through `this.GetSimulation()`, note that the `this` is required as it is an extension method.
|
|
|
|
|
|
|
+>- The recommended way is through a reference to a physics component, something like `myBody.Simulation` as it is the fastest.
|
|
|
|
|
+>- Or through the `Entity.GetSimulation()` extension method.
|
|
|
|
|
|
|
|
## See also
|
|
## See also
|
|
|
* [Colliders](colliders.md)
|
|
* [Colliders](colliders.md)
|