feat(scripting): expose PhysX rigidbody and raycast APIs

This commit is contained in:
2026-04-15 13:58:30 +08:00
parent 914c9361ed
commit bda8a35d77
13 changed files with 787 additions and 0 deletions

View File

@@ -592,6 +592,105 @@ TEST_F(MonoScriptRuntimeTest, SceneRuntimeDispatchesManagedCollisionMessagesWith
sceneRuntime.Stop();
}
TEST_F(MonoScriptRuntimeTest, ManagedRigidbodyWrapperAndPhysicsRaycastOperateAgainstRuntimePhysicsWorld) {
if (!XCEngine::Physics::PhysicsWorld::IsPhysXAvailable()) {
GTEST_SKIP() << "PhysX is not available in this configuration.";
}
Scene* runtimeScene = CreateScene("MonoRuntimeScene");
GameObject* host = runtimeScene->CreateGameObject("Host");
host->AddComponent<SphereColliderComponent>();
ScriptComponent* component = AddScript(host, "Gameplay", "PhysicsApiProbe");
GameObject* rayTarget = runtimeScene->CreateGameObject("RayTarget");
rayTarget->GetTransform()->SetPosition(XCEngine::Math::Vector3(0.0f, 3.0f, -4.0f));
BoxColliderComponent* targetCollider = rayTarget->AddComponent<BoxColliderComponent>();
targetCollider->SetSize(XCEngine::Math::Vector3(2.0f, 2.0f, 0.5f));
SceneRuntime sceneRuntime;
sceneRuntime.Start(runtimeScene);
sceneRuntime.Update(0.016f);
sceneRuntime.FixedUpdate(0.02f);
bool initialHasRigidbody = true;
bool addedRigidbody = false;
bool hasRigidbodyAfterAdd = false;
bool rigidbodyLookupSucceeded = false;
int32_t observedBodyType = -1;
float observedMass = 0.0f;
float observedLinearDamping = 0.0f;
float observedAngularDamping = 0.0f;
bool observedUseGravity = true;
bool observedEnableCCD = false;
XCEngine::Math::Vector3 observedLinearVelocity;
XCEngine::Math::Vector3 observedAngularVelocity;
bool raycastHitDetected = false;
std::string raycastHitName;
float raycastHitDistance = 0.0f;
bool raycastHitWasTrigger = true;
XCEngine::Math::Vector3 raycastHitPoint;
XCEngine::Math::Vector3 raycastHitNormal;
EXPECT_TRUE(runtime->TryGetFieldValue(component, "InitialHasRigidbody", initialHasRigidbody));
EXPECT_TRUE(runtime->TryGetFieldValue(component, "AddedRigidbody", addedRigidbody));
EXPECT_TRUE(runtime->TryGetFieldValue(component, "HasRigidbodyAfterAdd", hasRigidbodyAfterAdd));
EXPECT_TRUE(runtime->TryGetFieldValue(component, "RigidbodyLookupSucceeded", rigidbodyLookupSucceeded));
EXPECT_TRUE(runtime->TryGetFieldValue(component, "ObservedBodyType", observedBodyType));
EXPECT_TRUE(runtime->TryGetFieldValue(component, "ObservedMass", observedMass));
EXPECT_TRUE(runtime->TryGetFieldValue(component, "ObservedLinearDamping", observedLinearDamping));
EXPECT_TRUE(runtime->TryGetFieldValue(component, "ObservedAngularDamping", observedAngularDamping));
EXPECT_TRUE(runtime->TryGetFieldValue(component, "ObservedUseGravity", observedUseGravity));
EXPECT_TRUE(runtime->TryGetFieldValue(component, "ObservedEnableCCD", observedEnableCCD));
EXPECT_TRUE(runtime->TryGetFieldValue(component, "ObservedLinearVelocity", observedLinearVelocity));
EXPECT_TRUE(runtime->TryGetFieldValue(component, "ObservedAngularVelocity", observedAngularVelocity));
EXPECT_TRUE(runtime->TryGetFieldValue(component, "RaycastHitDetected", raycastHitDetected));
EXPECT_TRUE(runtime->TryGetFieldValue(component, "RaycastHitName", raycastHitName));
EXPECT_TRUE(runtime->TryGetFieldValue(component, "RaycastHitDistance", raycastHitDistance));
EXPECT_TRUE(runtime->TryGetFieldValue(component, "RaycastHitWasTrigger", raycastHitWasTrigger));
EXPECT_TRUE(runtime->TryGetFieldValue(component, "RaycastHitPoint", raycastHitPoint));
EXPECT_TRUE(runtime->TryGetFieldValue(component, "RaycastHitNormal", raycastHitNormal));
EXPECT_FALSE(initialHasRigidbody);
EXPECT_TRUE(addedRigidbody);
EXPECT_TRUE(hasRigidbodyAfterAdd);
EXPECT_TRUE(rigidbodyLookupSucceeded);
EXPECT_EQ(observedBodyType, static_cast<int32_t>(XCEngine::Physics::PhysicsBodyType::Dynamic));
EXPECT_FLOAT_EQ(observedMass, 2.5f);
EXPECT_FLOAT_EQ(observedLinearDamping, 0.25f);
EXPECT_FLOAT_EQ(observedAngularDamping, 0.5f);
EXPECT_FALSE(observedUseGravity);
EXPECT_TRUE(observedEnableCCD);
ExpectVector3Near(observedLinearVelocity, XCEngine::Math::Vector3(0.0f, 0.0f, 0.0f));
ExpectVector3Near(observedAngularVelocity, XCEngine::Math::Vector3(0.0f, 1.0f, 0.0f));
EXPECT_TRUE(raycastHitDetected);
EXPECT_EQ(raycastHitName, "RayTarget");
EXPECT_NEAR(raycastHitDistance, 3.75f, 0.05f);
EXPECT_FALSE(raycastHitWasTrigger);
ExpectVector3Near(raycastHitPoint, XCEngine::Math::Vector3(0.0f, 3.0f, -3.75f), 0.05f);
ExpectVector3Near(raycastHitNormal, XCEngine::Math::Vector3(0.0f, 0.0f, 1.0f), 0.01f);
EXPECT_NE(sceneRuntime.GetPhysicsWorld(), nullptr);
EXPECT_EQ(sceneRuntime.GetPhysicsWorld()->GetTrackedRigidbodyCount(), 1u);
RigidbodyComponent* rigidbody = host->GetComponent<RigidbodyComponent>();
ASSERT_NE(rigidbody, nullptr);
EXPECT_EQ(host->GetComponents<RigidbodyComponent>().size(), 1u);
EXPECT_EQ(rigidbody->GetBodyType(), XCEngine::Physics::PhysicsBodyType::Dynamic);
EXPECT_FLOAT_EQ(rigidbody->GetMass(), 2.5f);
EXPECT_FLOAT_EQ(rigidbody->GetLinearDamping(), 0.25f);
EXPECT_FLOAT_EQ(rigidbody->GetAngularDamping(), 0.5f);
EXPECT_FALSE(rigidbody->GetUseGravity());
EXPECT_TRUE(rigidbody->GetEnableCCD());
EXPECT_GT(rigidbody->GetLinearVelocity().x, 0.0f);
const XCEngine::Math::Vector3 hostPosition = host->GetTransform()->GetPosition();
EXPECT_GT(hostPosition.x, 0.01f);
EXPECT_NEAR(hostPosition.y, 0.0f, 0.01f);
sceneRuntime.Stop();
}
TEST_F(MonoScriptRuntimeTest, ManagedInputApiReadsCurrentNativeInputManagerState) {
XCEngine::Input::InputManager& inputManager = XCEngine::Input::InputManager::Get();
inputManager.Initialize(nullptr);