- 动画: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 的拒读)
88 lines
4.6 KiB
C++
88 lines
4.6 KiB
C++
//
|
||
// WallFracture.cpp:可碎墙脚本——碎裂逻辑已提取至 FractureLib.h
|
||
//(打靶场 Target 复用同一条路径),本文件只剩宿主职责:
|
||
// DeclareParams 直绑 Burst::p 各字段(参数名/默认值与历史档位
|
||
// 逐一同名同值,旧场景不受影响)
|
||
// OnCollisionEnter → Burst::TryFire(一次性保护 + 对方撞击来源
|
||
// 与速度校验 + 藏墙 + Voronoi 切分 + spawn 碎片群,库内完成)。
|
||
// 撞击来源 = 动态刚体(子弹/抛体)或角色(玩家撞墙)——角色是
|
||
// CharacterVirtual,其碰撞事件由 PhysicsWorld 从角色接触合成
|
||
// (Jolt 的 ContactListener 只回调刚体,不覆盖角色)
|
||
// OnUpdate → Burst::Tick(施速待办 / 寿命清理 / 模型回收)
|
||
// OnDestroy → Burst::Shutdown(独占碎片模型批量停飞卸载)
|
||
//
|
||
// 外观默认继承墙的生效材质(底色/贴图/透明),碎块与墙面观感一致;
|
||
// 要独立外观(玻璃/发光碎片)置 Burst::look.inheritFromHost = false
|
||
// 再用 baseColor/emissive 显式指定。
|
||
//
|
||
// 验收步骤:编辑器摆一堵墙(MeshRenderer = procedural://cube +
|
||
// RigidBody Static Box + 挂 WallFracture,缩放即墙尺寸)→ 场景里
|
||
// 任意实体挂 TestShoot → Play → RMB 飞行瞄准墙体 → 左键射击:
|
||
// 墙沿裂纹碎成不规则碎片,孔洞周边碎块小、飞散明显,边缘大块
|
||
// 塌落堆积在墙脚,若干秒后清空。
|
||
//
|
||
|
||
#include <Engine/Scripting/Script.h>
|
||
#include <Engine/Core/Types.h>
|
||
|
||
#include "FractureLib.h"
|
||
|
||
using namespace Engine; // u32/f32/i32 基础类型(历史脚本同款)
|
||
|
||
namespace {
|
||
|
||
// ---- 可碎墙(挂墙实体;触发后由 Burst 管一整批碎片)----
|
||
class WallFracture final : public Engine::Scripting::ScriptBehavior {
|
||
public:
|
||
const char* Name() const override { return "WallFracture"; }
|
||
|
||
void DeclareParams(Engine::Scripting::ParamBuilder& pb) override {
|
||
// Voronoi 种子数 = 碎片数(40% 在命中点半径内加密 → 孔洞
|
||
// 周边碎块小、边缘大块的玻璃碎分布;最小间距防碎片退化)
|
||
// 直绑 Burst::p:碎裂逻辑只读 Burst::p,绑到别处(曾经的
|
||
// 独立 m_P)会让计数器/寿命等全部失效
|
||
pb.Field("Count", &m_Burst.p.count, 30);
|
||
pb.Field("SeedRadius", &m_Burst.p.seedRadius, 0.9f); // 加密半径 m
|
||
pb.Field("MinSeedDist", &m_Burst.p.minSeedDist, 0.12f); // 种子最小间距 m
|
||
// 玻璃/陶瓷式碎裂(裂纹分离 + 重力塌落),非爆炸飞散:
|
||
// 初速 = 命中点径向 × 距离指数衰减(近动远不动)+ 法线
|
||
// 轻微外推(剥落)+ 微弱上抛;重力是塌落的主导
|
||
pb.Field("BurstSpeed", &m_Burst.p.burstSpeed, 1.2f); // 近点径向初速 m/s
|
||
pb.Field("Falloff", &m_Burst.p.falloff, 1.0f); // 距离衰减率 1/m
|
||
pb.Field("NormalPop", &m_Burst.p.normalPop, 0.4f); // 法线外推 m/s
|
||
pb.Field("UpBias", &m_Burst.p.upBias, 0.3f); // 上抛偏置 m/s
|
||
pb.Field("Lifetime", &m_Burst.p.lifetime, 6.0f); // 碎片寿命(秒)
|
||
pb.Field("MaxFragments", &m_Burst.p.maxFragments, 128); // 活碎片上限
|
||
pb.Field("MinImpactSpeed", &m_Burst.p.minImpactSpeed, 2.0f); // 触发阈值
|
||
}
|
||
|
||
void OnCollisionEnter(u32 other, const glm::vec3& point,
|
||
const glm::vec3& normal) override {
|
||
// 触发条件在库内:对方须是够快的撞击来源——动态刚体
|
||
//(子弹/抛体)或角色(玩家撞墙);速度阈值过滤静止贴靠
|
||
m_Burst.TryFire(HV(), other, point, normal);
|
||
}
|
||
|
||
void OnUpdate(f32 dt) override { m_Burst.Tick(HV(), dt); }
|
||
|
||
// 墙销毁(PIE stop 换血 / 手动删除):碎片实体由场景清亡处理,
|
||
// 独占碎片模型统一批量回收
|
||
void OnDestroy() override { m_Burst.Shutdown(HV()); }
|
||
|
||
private:
|
||
// 库桥接:本成员函数内可访问 protected 基类设施(App/Spawn/
|
||
// Destroy),库内只走公共 API——见 FractureLib.h HostView 注
|
||
Engine::Fracture::HostView HV() {
|
||
return {App(), EntityBits(),
|
||
[this](const std::string& n) { return Spawn(n); },
|
||
[this](Engine::ECS::Entity e) { Destroy(e); }};
|
||
}
|
||
|
||
// 碎片簿记 + 生命周期;参数即 m_Burst.p(DeclareParams 直绑其字段)
|
||
Engine::Fracture::Burst m_Burst;
|
||
};
|
||
|
||
} // namespace
|
||
|
||
ENGINE_REGISTER_SCRIPT(WallFracture)
|