feat(physics): add runtime physics scaffolding

This commit is contained in:
2026-04-15 11:58:27 +08:00
parent d17ddffdef
commit 3317e47009
31 changed files with 2120 additions and 0 deletions

View File

@@ -1,5 +1,10 @@
#include <gtest/gtest.h>
#include <XCEngine/Components/BoxColliderComponent.h>
#include <XCEngine/Components/CapsuleColliderComponent.h>
#include <XCEngine/Components/RigidbodyComponent.h>
#include <XCEngine/Components/SphereColliderComponent.h>
#include <XCEngine/Physics/PhysicsWorld.h>
#include <XCEngine/Scene/SceneRuntime.h>
#include <XCEngine/Scripting/IScriptRuntime.h>
#include <XCEngine/Scripting/ScriptComponent.h>
@@ -319,6 +324,83 @@ TEST_F(SceneRuntimeTest, StartAndStopForwardToScriptEngine) {
EXPECT_EQ(runtime.GetScene(), nullptr);
}
TEST_F(SceneRuntimeTest, StartCreatesPhysicsWorldAndScansScenePhysicsComponents) {
Scene* runtimeScene = CreateScene("RuntimeScene");
GameObject* ground = runtimeScene->CreateGameObject("Ground");
ground->AddComponent<BoxColliderComponent>();
GameObject* player = runtimeScene->CreateGameObject("Player");
player->AddComponent<RigidbodyComponent>();
player->AddComponent<SphereColliderComponent>();
GameObject* trigger = runtimeScene->CreateGameObject("Trigger", player);
trigger->AddComponent<CapsuleColliderComponent>();
runtime.Start(runtimeScene);
XCEngine::Physics::PhysicsWorld* physicsWorld = runtime.GetPhysicsWorld();
ASSERT_NE(physicsWorld, nullptr);
EXPECT_EQ(physicsWorld->GetCreateInfo().scene, runtimeScene);
EXPECT_EQ(
physicsWorld->IsInitialized(),
XCEngine::Physics::PhysicsWorld::IsPhysXAvailable());
EXPECT_EQ(physicsWorld->GetTrackedRigidbodyCount(), 1u);
EXPECT_EQ(physicsWorld->GetTrackedColliderCount(), 3u);
runtime.Stop();
EXPECT_EQ(runtime.GetPhysicsWorld(), nullptr);
}
TEST_F(SceneRuntimeTest, ReplaceSceneRebuildsPhysicsWorldAgainstNewScene) {
Scene* firstScene = CreateScene("FirstScene");
GameObject* firstActor = firstScene->CreateGameObject("FirstActor");
firstActor->AddComponent<RigidbodyComponent>();
firstActor->AddComponent<BoxColliderComponent>();
runtime.Start(firstScene);
auto secondScene = std::make_unique<Scene>("SecondScene");
GameObject* secondActor = secondScene->CreateGameObject("SecondActor");
secondActor->AddComponent<SphereColliderComponent>();
secondActor->AddComponent<CapsuleColliderComponent>();
runtime.ReplaceScene(secondScene.get());
XCEngine::Physics::PhysicsWorld* physicsWorld = runtime.GetPhysicsWorld();
ASSERT_NE(physicsWorld, nullptr);
EXPECT_EQ(physicsWorld->GetCreateInfo().scene, secondScene.get());
EXPECT_EQ(physicsWorld->GetTrackedRigidbodyCount(), 0u);
EXPECT_EQ(physicsWorld->GetTrackedColliderCount(), 2u);
runtime.Stop();
}
TEST_F(SceneRuntimeTest, RuntimePhysicsWorldTracksComponentAndGameObjectRemoval) {
Scene* runtimeScene = CreateScene("RuntimeScene");
runtime.Start(runtimeScene);
XCEngine::Physics::PhysicsWorld* physicsWorld = runtime.GetPhysicsWorld();
ASSERT_NE(physicsWorld, nullptr);
EXPECT_EQ(physicsWorld->GetTrackedRigidbodyCount(), 0u);
EXPECT_EQ(physicsWorld->GetTrackedColliderCount(), 0u);
GameObject* actor = runtimeScene->CreateGameObject("Actor");
actor->AddComponent<RigidbodyComponent>();
SphereColliderComponent* sphereCollider = actor->AddComponent<SphereColliderComponent>();
actor->AddComponent<BoxColliderComponent>();
EXPECT_EQ(physicsWorld->GetTrackedRigidbodyCount(), 1u);
EXPECT_EQ(physicsWorld->GetTrackedColliderCount(), 2u);
actor->RemoveComponent(sphereCollider);
EXPECT_EQ(physicsWorld->GetTrackedRigidbodyCount(), 1u);
EXPECT_EQ(physicsWorld->GetTrackedColliderCount(), 1u);
runtimeScene->DestroyGameObject(actor);
EXPECT_EQ(physicsWorld->GetTrackedRigidbodyCount(), 0u);
EXPECT_EQ(physicsWorld->GetTrackedColliderCount(), 0u);
}
TEST_F(SceneRuntimeTest, FrameOrderRunsScriptLifecycleBeforeNativeComponents) {
Scene* runtimeScene = CreateScene("RuntimeScene");
GameObject* host = runtimeScene->CreateGameObject("Host");