physics: character controller (Jolt CharacterVirtual)
- CharacterControllerComponent: capsule params (radius/halfHeight, mass, max slope, step height); entity origin = feet via shape offset - CharacterController per-entity wrapper: gravity integration + grounded clamp, ExtendedUpdate (sweep/slide + stick-to-floor + walk-stairs), SetLinearVelocity/Jump/IsGrounded facade - PhysicsWorld: SyncCharacters reconcile (create/rebuild on param change, editor-drag teleport), UpdateCharacters after physics Update (Jolt recommended order), writes back to Transform - Inspector: params + grounded/velocity telemetry + jump debug button - Serialization: params only, state rebuilt by reconcile
This commit is contained in:
@@ -121,6 +121,11 @@ void InspectorPanel::Draw(const EditorContext& ctx, entt::entity selected)
|
||||
{
|
||||
reg.emplace<Engine::ECS::JointComponent>(selected);
|
||||
}
|
||||
if (!reg.all_of<Engine::ECS::CharacterControllerComponent>(selected) &&
|
||||
ImGui::MenuItem("Character Controller"))
|
||||
{
|
||||
reg.emplace<Engine::ECS::CharacterControllerComponent>(selected);
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
ImGui::Separator();
|
||||
@@ -391,6 +396,38 @@ void InspectorPanel::Draw(const EditorContext& ctx, entt::entity selected)
|
||||
}
|
||||
}
|
||||
|
||||
// ---- CharacterController(参数编辑;状态在 PhysicsWorld 运行时)----
|
||||
if (auto* cc = reg.try_get<Engine::ECS::CharacterControllerComponent>(selected))
|
||||
{
|
||||
if (ImGui::CollapsingHeader("Character Controller",
|
||||
ImGuiTreeNodeFlags_DefaultOpen))
|
||||
{
|
||||
// 实体原点 = 脚底(胶囊底端),总高 = 2*(halfHeight + radius)
|
||||
ImGui::DragFloat("radius", &cc->radius, 0.02f, 0.05f, 5.0f);
|
||||
ImGui::DragFloat("halfHeight", &cc->capsuleHalfHeight, 0.02f, 0.0f, 5.0f);
|
||||
ImGui::DragFloat("mass", &cc->mass, 1.0f, 1.0f, 500.0f, "%.0f");
|
||||
ImGui::DragFloat("max slope deg", &cc->maxSlopeAngle, 1.0f, 1.0f, 89.0f);
|
||||
ImGui::DragFloat("step height", &cc->stepHeight, 0.02f, 0.0f, 2.0f);
|
||||
|
||||
// 遥测(只读):运行时状态在 PhysicsWorld 的 CharacterController
|
||||
if (auto& phy = ctx.app->GetPhysics(); phy.IsEnabled())
|
||||
{
|
||||
const uint32_t bits =
|
||||
static_cast<uint32_t>(entt::to_integral(selected));
|
||||
ImGui::Text("grounded: %s",
|
||||
phy.IsCharacterGrounded(bits) ? "yes" : "no");
|
||||
const glm::vec3 v = phy.GetCharacterVelocity(bits);
|
||||
ImGui::Text("vel: %.2f, %.2f, %.2f m/s", v.x, v.y, v.z);
|
||||
|
||||
// 跳跃调试按钮
|
||||
if (ImGui::Button("Jump"))
|
||||
{
|
||||
phy.Jump(bits, 5.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---- Animation ----
|
||||
if (auto* anim = reg.try_get<Engine::ECS::AnimationComponent>(selected))
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user