阶段性合并:动画重定向、碎裂共享库、第三人称玩法、编辑器面板与 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:
+79
-31
@@ -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,调试图)
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user