阶段性合并:动画重定向、碎裂共享库、第三人称玩法、编辑器面板与 vendored ufbx

- 动画:HumanoidRig 三层架构(standard 标准槽 / dialects 方言映射 / mapper 配对),
  指/趾统一走世界增量两遍式烘焙;AnimationAttach 拆为纯算法 + facade;修正 HumanoidBasis
  行走基朝向与跨骨架去重、根运动通道
- 物理:CharacterController 角色互碰撞 / shapeOffset / 接触事件;PhysicsWorld 接触合成与
  字符冲量判定
- 渲染与材质:Model 多材质按材质拆子 mesh 与贴图路径解析、DDS 直传、GLB 内嵌纹理落盘、
  不透明通道 alpha 固定 1.0、glTF FlipUVs 对齐;SceneSerializer 支持 meshIndex 与材质覆盖
- 脚本:FractureLib 抽为共享库(HostView 桥接)、WallFracture 参数直绑、新增
  ThirdPersonCamera / Follower / WASDMove 玩法;移除 GameDirector / PlayerController / Target
- 编辑器:新增 GamepadPanel、LogPanel(LogRing),改进 Inspector / 材质 / 统计 / 视口面板
- 依赖:vendored ufbx(FBX 5.x/6.x/7.x 全版本解析,替代 assimp 对 FBX 6.1 的拒读)
This commit is contained in:
2026-10-11 22:22:19 +08:00
parent 334819bf97
commit beba491bcb
57 changed files with 43200 additions and 1378 deletions
+79 -31
View File
@@ -1,5 +1,9 @@
//
// WASDMove.cpp:WASD 控制实体移动(相机水平朝向参考,UE gameplay 语义)。
// WASDMove.cpp:第三人称移动(WASD/手柄摇杆,相机朝向参考,UE gameplay 语义)。
//
// 输入走引擎具名动作层(Move/Jump/Run 默认绑定):WASD + 方向键 +
// 手柄左摇杆移动(引擎径向死区),Space/手柄 A 跳;跑 = Run 动作
//(Shift / 手柄 L3 按下左摇杆)。摇杆模拟量直接驱动动量整形(轻推慢走)。
//
// 移动语义分派(按实体配置自动选择,优先级从上到下):
// - CharacterControllerComponent → 角色控制器路径(扫掠运动学:
@@ -19,6 +23,7 @@
#include <Engine/Core/Input.h>
#include <Engine/Debug/DebugDraw.h>
#include "ScriptDebug.h"
#include "ScriptLog.h"
#include <Engine/Renderer/Renderer.h>
#include <Engine/Renderer/EditorCamera.h>
@@ -49,37 +54,68 @@ namespace {
pb.Field("RunClip", &m_RunClip, std::string("run"));
}
void OnStart() override {
SLOG_TRACE("hello");
SLOG_INFO("hello");
SLOG_DEBUG("hello");
SLOG_WARN("hello");
SLOG_ERROR("hello");
SLOG_INFO("[WASDMove] 就绪:走 {:.1f} m/s / 跑 {:.1f} m/s / 跳 {:.1f} m/s",
m_Speed, m_RunSpeed, m_JumpSpeed);
}
void OnUpdate(float dt) override {
// 位移方向 = 视线水平投影(W 前进 / A 左 / D 右),UE Scene
// view 移动惯例;Y 锁 0(升降/跳跃归物理或将来扩展)。
// 输入直读按键(Unity Input.GetKey(KeyCode.W) 同形);UI 捕获
// 键盘时门面静默。要手柄/运行时改键再换动作层
//(Input::ActionValue2("Move")——Unity6 新 Input System /
// UE5 Enhanced Input 对应物),本示例保持最简
const glm::quat cq = App().GetRenderer()
.GetEditorCamera()
.GetTransform()
.GetRotationQuat();
// 输入 = 具名动作层(Unity6 Input System / UE5 Enhanced Input
// 同位):Move 默认混绑 WASD/方向键/左摇杆(引擎做径向死区 +
// 单位圆钳制,斜向不超速),Jump 混绑 Space/手柄 A——键盘
// 手柄一套代码,将来改键/加绑定不进脚本
// 移动参考 = 场景 primary 相机(第三人称相机脚本每帧写它
// 的朝向——玩家看到的视角就是移动参考);无相机实体时
//(纯独立形态)回退编辑器相机
glm::quat cq;
bool refCam = false;
auto camView = App().GetScene()
.GetRegistry()
.view<Engine::ECS::CameraComponent>();
for (auto e : camView) {
const auto& cam =
camView.get<Engine::ECS::CameraComponent>(e);
if (cam.primary && cam.active) {
cq = App().GetScene()
.GetRegistry()
.get<Engine::ECS::TransformComponent>(e)
.GetRotationQuat();
refCam = true;
break;
}
}
if (!refCam) {
cq = App().GetRenderer()
.GetEditorCamera()
.GetTransform()
.GetRotationQuat();
}
const glm::vec3 fwd = cq * glm::vec3(0.0f, 0.0f, -1.0f);
const glm::vec3 right = cq * glm::vec3(1.0f, 0.0f, 0.0f);
// 约定:X+ = 右(D),Y- = 前(W);方向合成 = fwd*(-Y) + right*(+X)
glm::vec2 mv(0.0f);
if (Input::IsKeyDown(Input::Key::W)) mv.y -= 1.0f;
if (Input::IsKeyDown(Input::Key::S)) mv.y += 1.0f;
if (Input::IsKeyDown(Input::Key::A)) mv.x -= 1.0f;
if (Input::IsKeyDown(Input::Key::D)) mv.x += 1.0f;
const glm::vec2 mvRaw = Input::ActionValue2("Move");
glm::vec2 mv = mvRaw;
if (glm::length(mv) > 1.0f) mv = glm::normalize(mv);
glm::vec3 move = fwd * (-mv.y) + right * mv.x;
move.y = 0.0f;
if (glm::length(move) > 1e-4f) {
// 只钳超速,不放大——摇杆模拟量(幅度 <1)保留进速度:
// 轻推慢走、推满全速(归一化会把幅度吃掉,一动就满速)
if (glm::length(move) > 1.0f) {
move = glm::normalize(move);
}
// 走/跑
const bool moving = glm::length(mv) > 0.1f;
const bool running =
moving && Input::IsKeyDown(Input::Key::LeftShift);
// 走/跑:Run 动作(默认绑 Shift + 手柄 L3,按下左摇杆冲刺
// 的 Xbox 惯例)。不判"摇杆推满"——键盘 WASD 幅度恒 1.0,
// 那样判会把走路误判成跑
const bool running = Input::ActionDown("Run");
const float speed = running ? m_RunSpeed : m_Speed;
const glm::vec3 desired = move * speed; // 期望速度(输入意图)
@@ -95,6 +131,7 @@ namespace {
// 松手滑行刹车。加速/转向用 AccelResponse,松手用更硬的
// StopResponse(角色要"想停就停");空中操纵性降到 1/4
//(起跳后不宜急转弯)。指数逼近,帧率无关
const bool moving = glm::length(mvRaw) > 0.1f;
float response = moving ? m_AccelResponse : m_StopResponse;
if (!grounded) {
response *= 0.25f;
@@ -113,15 +150,14 @@ namespace {
phy.SetCharacterVelocity(
EntityBits(), {m_PlanarVel.x, cur.y, m_PlanarVel.z});
// 跳跃:着地 + 上升沿触发。IsKeyDown 是电平量(按住
// 每帧都真),不设边沿会变成贴地火箭;IsGrounded 防
// 空中连跳
const bool jumpDown = Input::IsKeyDown(Input::Key::Space);
if (jumpDown && !m_JumpWasDown &&
// 跳跃:动作层边沿(Pressed = prev 0 → cur 非 0,键盘
// Space / 手柄 A 都产生一次上升沿)。IsGrounded 防空中连跳
if (Input::ActionPressed("Jump") &&
phy.IsCharacterGrounded(EntityBits())) {
phy.Jump(EntityBits(), m_JumpSpeed);
SLOG_INFO("[WASDMove] jump(着地起跳 {:.1f} m/s)",
m_JumpSpeed);
}
m_JumpWasDown = jumpDown;
} else if (auto* rb =
TryGetComponent<Engine::ECS::RigidBodyComponent>();
rb != nullptr && rb->bodyValid &&
@@ -155,11 +191,24 @@ namespace {
glm::angleAxis(curYaw + dyaw * k, glm::vec3(0, 1, 0)));
}
// ---- 动画:idle/walk/run 三态切换(Direct 模式 crossfade)----
// 目标 clip 是"电平量":Shift 中途按下/松开都要能换,所以
// 每帧重算目标,只在目标与上帧不同才 Play(边沿)。每帧无
// 条件 Play 会不停重置播放头,动画永远播不完
const std::string& target = !moving ? m_IdleClip : (running ? m_RunClip : m_WalkClip);
// ---- 动画:按真实速度分档(迟滞防临界抖)----
// 判据 = 动量整形后的真实水平速度,不是输入原始值:起步
// 滑行期已是 walk,松手刹车期保持 walk 直到真停——动画与
// 位移观感一致,按键瞬通瞬断不再瞬间换挡。run 双阈值迟滞
//(进 0.9×RunSpeed / 退 0.7×RunSpeed):摇杆在阈值附近晃
// 不抖档。引擎 Play(名) 自带相位对齐 + crossfade,切档
// 突兀感只剩判据本身的问题
const float planarSpeed = glm::length(m_PlanarVel);
std::string target;
if (planarSpeed < 0.15f) {
target = m_IdleClip;
} else if (m_CurClip == m_RunClip) {
target = (planarSpeed >= m_RunSpeed * 0.7f) ? m_RunClip
: m_WalkClip;
} else {
target = (planarSpeed >= m_RunSpeed * 0.9f) ? m_RunClip
: m_WalkClip;
}
if (target != m_CurClip) {
if (auto* anim = TryGetComponent<Engine::ECS::AnimationComponent>();
anim != nullptr && anim->Play(target, 0.35f)) {
@@ -221,7 +270,6 @@ namespace {
std::string m_WalkClip = "walk";
std::string m_RunClip = "run";
std::string m_CurClip = "idle"; // 当前目标 clip(边沿检测基准)
bool m_JumpWasDown = false; // 上帧跳跃键(上升沿检测)
glm::vec3 m_PrevVel{0.0f}; // 上帧测量速度(加速度差分基准)
glm::vec3 m_AccelS{0.0f}; // 平滑测量加速度(EMA 0.35,调试图)
};