Skip to content

Commit

Permalink
fix: PhysicsComponent created with GetOrCreate<T> is unusable (stride…
Browse files Browse the repository at this point in the history
…3d#2422)

* Run proper Rigidbody setup when adding ColliderShape

* Added test case for proper setup with GetOrCreate

* Followed similar Bepu format with creation of ReAttach method

* Reformatted files edited

* Revert "Reformatted files edited"

This reverts commit 1c9b03e.
  • Loading branch information
dloe authored Aug 30, 2024
1 parent c424213 commit 32e341c
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 3 deletions.
47 changes: 46 additions & 1 deletion sources/engine/Stride.Physics.Tests/ColliderShapesTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public static bool ScreenPositionToWorldPositionRaycast(Vector2 screenPos, Camer
if (hitResult.Succeeded)
{
return true;
}
}
}

return false;
Expand Down Expand Up @@ -243,6 +243,51 @@ public void ColliderShapesTest1()
Assert.Equal(0.0f, (new Vector3(-2.861034E-06f, 3.889218E-06f, -1f) - hit.Normal).Length(), 3f);
Assert.Equal(0.0f, (new Vector3(-5.366335f, -0.08297831f, -17.9267f) - hit.Point).Length(), 3f);

game.Exit();
});
RunGameTest(game);
}

/// <summary>
/// Verify PhysicsComponent creation through the use of GetOrCreate<T>
/// If component is added this way, must ensure ColliderShape is properly setup if added later
/// </summary>
[Fact]
public void VerifyColliderShapeSetup()
{
var game = new ColliderShapesTest();
game.Script.AddTask(async () =>
{
game.ScreenShotAutomationEnabled = false;
await game.Script.NextFrame();
await game.Script.NextFrame();

var simulation = game.SceneSystem.SceneInstance.RootScene.Entities.First(ent => ent.Name == "Simulation").Get<StaticColliderComponent>().Simulation;
var cube = game.SceneSystem.SceneInstance.RootScene.Entities.First(ent => ent.Name == "CubePrefab1");

var body = cube.GetOrCreate<RigidbodyComponent>();

//verify values not properly set up
Assert.Null(body.ColliderShape);
Assert.Equal(RigidBodyTypes.Static, body.RigidBodyType);
Assert.False(body.OverrideGravity);

//for further debug, can set breakpoint and check body.Simulation.discreteDynamicWorld.CollisionObjectArray before and after
//the collider shape is attached to see it properly added

//add collider shape
body.ColliderShape = new SphereColliderShape(false, 1.0f);
//check if proper colliderShape setup took place
Assert.True(body.ColliderShape != null);
Assert.Equal(ColliderShapeTypes.Sphere, body.ColliderShape.Type);
Assert.Equal(RigidBodyTypes.Dynamic, body.RigidBodyType);

body.OverrideGravity = true;
//to verify InternalRigidBody was properly set up we can change properties such as Mass or OverrideGravity
//that normally would return void if there are no InternalRigidBody values
Assert.True(body.OverrideGravity);


game.Exit();
});
RunGameTest(game);
Expand Down
17 changes: 15 additions & 2 deletions sources/engine/Stride.Physics/Elements/RigidbodyComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,11 @@ public float Mass

mass = value;

if (InternalRigidBody == null) return;
if (InternalRigidBody == null)
{
return;
}


var inertia = ColliderShape.InternalShape.CalculateLocalInertia(value);
InternalRigidBody.SetMassProps(value, inertia);
Expand Down Expand Up @@ -114,7 +118,11 @@ public override ColliderShape ColliderShape
return;

if (InternalRigidBody == null)
{
//When setting ColliderShape, setup could have been previously skipped (eg when PhysicsComponent is created using GetOrCreate)
ReAttach();
return;
}

if (NativeCollisionObject != null)
NativeCollisionObject.CollisionShape = value.InternalShape;
Expand Down Expand Up @@ -193,7 +201,11 @@ public bool OverrideGravity
{
overrideGravity = value;

if (InternalRigidBody == null) return;
if (InternalRigidBody == null)
{
return;
}


if (value)
{
Expand Down Expand Up @@ -341,6 +353,7 @@ protected override void OnAttach()

protected override void OnDetach()
{

MotionState.Dispose();
MotionState.Clear();

Expand Down
26 changes: 26 additions & 0 deletions sources/engine/Stride.Physics/Engine/PhysicsComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -681,6 +681,32 @@ internal void Attach(PhysicsProcessor.AssociatedData data)
}
}

/// <summary>
/// Ran when properties of Components may not be fully setup and need to be reintegrated (eg GetOrCreate<RigidbodyComponent> and adding collidershapes)
/// </summary>
internal void ReAttach()
{
//TODO: Could consider fully detaching and then rebuilding, but ideally this would cause null refs on Rigidbody OnDetach calls
//Shouldnt call detach, because at this point the user has added new components and this runs as a check to rebuild as needed.
//Entire wipes to rebuild causes loss in the data that the user has just added (and is slower)

Entity.Transform.UpdateWorldMatrix();

BoneIndex = -1;

OnAttach();

//ensure ignore collisions
if (ignoreCollisionBuffer != null && NativeCollisionObject != null)
{
foreach (var kvp in ignoreCollisionBuffer)
{
IgnoreCollisionWith(kvp.Key, kvp.Value);
}
ignoreCollisionBuffer = null;
}
}

internal void Detach()
{
Data = null;
Expand Down

0 comments on commit 32e341c

Please sign in to comment.