fix(physics): editor drag teleports dynamic bodies
SyncScene only reconciled static/kinematic transforms into Jolt bodies; dragging a dynamic entity (esp. while paused, where Writeback never runs) moved the visual but left the body -- and the collider debug wireframe -- at the old pose. Dynamic bodies now get the same drag reconciliation (teleport + zero velocity + activate), and Writeback syncs lastPos/lastRot to the body pose so physics motion is never misread as editor dragging (which would teleport the body back).
This commit is contained in:
@@ -119,7 +119,7 @@ namespace Engine {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void SyncScene(); // 对账:孤儿清理 / 创建 / 参数同步
|
void SyncScene(); // 对账:孤儿清理 / 创建 / 参数同步
|
||||||
void Writeback() const; // 动态体 → TransformComponent(标脏)
|
void Writeback(); // 动态体 → TransformComponent(标脏)+ lastPos/lastRot 对账基线
|
||||||
void UpdateAccels(f32 dt); // 速度差分 → BodyRecord.lastAccel(step 率)
|
void UpdateAccels(f32 dt); // 速度差分 → BodyRecord.lastAccel(step 率)
|
||||||
void CollectDebugData(); // 按 m_DebugBits 收集调试图元(渲染帧率)
|
void CollectDebugData(); // 按 m_DebugBits 收集调试图元(渲染帧率)
|
||||||
void CreateBody(u32 entityBits, ECS::RigidBodyComponent& rb,
|
void CreateBody(u32 entityBits, ECS::RigidBodyComponent& rb,
|
||||||
|
|||||||
@@ -393,6 +393,22 @@ namespace Engine {
|
|||||||
bi.SetRestitution(id, rb.restitution);
|
bi.SetRestitution(id, rb.restitution);
|
||||||
if (rb.type == ECS::RigidBodyComponent::BodyType::Dynamic) {
|
if (rb.type == ECS::RigidBodyComponent::BodyType::Dynamic) {
|
||||||
bi.SetGravityFactor(id, rb.gravityScale);
|
bi.SetGravityFactor(id, rb.gravityScale);
|
||||||
|
// 编辑器拖动 Dynamic 体(暂停期/物理未步进的帧)→ 传送 +
|
||||||
|
// 清速度(UE 编辑器语义:编辑器操作权威于物理 body,拖动 =
|
||||||
|
// 重新放置)。物理模拟中 Writeback 每步同步 lastPos/lastRot
|
||||||
|
// → 本比对只在真正拖动帧为真,不会打断自由模拟
|
||||||
|
if (rec.lastPos != tr.GetPosition() ||
|
||||||
|
rec.lastRot != tr.GetRotationQuat()) {
|
||||||
|
bi.SetPositionAndRotation(
|
||||||
|
id,
|
||||||
|
JPH::RVec3(tr.GetPosition().x, tr.GetPosition().y, tr.GetPosition().z),
|
||||||
|
ToJolt(tr.GetRotationQuat()),
|
||||||
|
JPH::EActivation::Activate);
|
||||||
|
bi.SetLinearVelocity(id, JPH::Vec3(0.0f, 0.0f, 0.0f));
|
||||||
|
bi.SetAngularVelocity(id, JPH::Vec3(0.0f, 0.0f, 0.0f));
|
||||||
|
rec.lastPos = tr.GetPosition();
|
||||||
|
rec.lastRot = tr.GetRotationQuat();
|
||||||
|
}
|
||||||
} else if (rec.lastPos != tr.GetPosition() ||
|
} else if (rec.lastPos != tr.GetPosition() ||
|
||||||
rec.lastRot != tr.GetRotationQuat()) {
|
rec.lastRot != tr.GetRotationQuat()) {
|
||||||
// 编辑器拖动静态/运动学体 → 传送 body
|
// 编辑器拖动静态/运动学体 → 传送 body
|
||||||
@@ -994,7 +1010,7 @@ namespace Engine {
|
|||||||
|
|
||||||
// ---- 写回:动态体姿态 → Transform(标脏,帧循环统一 Compose)----
|
// ---- 写回:动态体姿态 → Transform(标脏,帧循环统一 Compose)----
|
||||||
|
|
||||||
void PhysicsWorld::Writeback() const {
|
void PhysicsWorld::Writeback() {
|
||||||
auto ® = m_Scene.GetRegistry();
|
auto ® = m_Scene.GetRegistry();
|
||||||
const auto &bi = m_System->GetBodyInterface();
|
const auto &bi = m_System->GetBodyInterface();
|
||||||
|
|
||||||
@@ -1012,6 +1028,14 @@ namespace Engine {
|
|||||||
|
|
||||||
const JPH::Vec3 vel = bi.GetLinearVelocity(id);
|
const JPH::Vec3 vel = bi.GetLinearVelocity(id);
|
||||||
rb.velocity = glm::vec3(vel.GetX(), vel.GetY(), vel.GetZ());
|
rb.velocity = glm::vec3(vel.GetX(), vel.GetY(), vel.GetZ());
|
||||||
|
|
||||||
|
// lastPos/lastRot 同步到 body 姿态:否则下帧 SyncScene 把物理
|
||||||
|
// 位移误判为编辑器拖动 → teleport 回旧位置死循环
|
||||||
|
const u32 bits = static_cast<u32>(entt::to_integral(e));
|
||||||
|
if (auto it = m_Bodies.find(bits); it != m_Bodies.end()) {
|
||||||
|
it->second.lastPos = tr.GetPosition();
|
||||||
|
it->second.lastRot = tr.GetRotationQuat();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace Engine
|
} // namespace Engine
|
||||||
|
|||||||
Reference in New Issue
Block a user