// // Target.cpp:打靶场玻璃靶子脚本(侧线"玩法原型验证")。 // // 职责(挂靶子实体:MeshRenderer 玻璃立方 + RigidBody Static Box + // 本脚本;通常由 GameDirector 运行时成批 spawn,也可编辑器手动摆): // OnCollisionEnter → 玻璃外观套用(半透明 + 靶色自发光)→ // Fracture::Burst::TryFire(一次性保护 + Dynamic 速度校验 + // 藏靶 + Voronoi 切分 + spawn 玻璃碎片群,共享库内完成) // ReportScore:向 Director 实体的 GameDirector 脚本报分(Score +1, // 写穿 Item.params,PIE Inspector 实时反映);Director=0 表示 // 独立靶不计分;导演 AcceptHits=false(回合已结束)不报 // OnUpdate/OnDestroy → Burst::Tick/Shutdown(碎片施速/寿命/回收) // // 覆盖的引擎设施:跨脚本参数访问(ScriptRuntime::GetParam/SetParam, // GameDirector ↔ Target 的计分通道)、共享碎裂库(FractureLib.h, // 与 WallFracture 同一条碎片路径)、玻璃材质(透明队列 + 自发光)。 // // 演示步骤:任意实体挂 GameDirector → Play → 左键射击靶阵: // 靶子玻璃式碎裂 + 计分,60 秒倒计时,时间到结算,R 重开。 // #include #include // GetScripts() 跨脚本参数访问 #include #include "FractureLib.h" using namespace Engine; // i32/f32/u32 基础类型(同 WallFracture) namespace { // ---- 玻璃靶子 ---- class Target final : public Engine::Scripting::ScriptBehavior { public: const char* Name() const override { return "Target"; } void DeclareParams(Engine::Scripting::ParamBuilder& pb) override { // 击碎报分去向:Director 实体 bits(0 = 独立靶不计分); // GameDirector spawn 时写进脚本项参数 pb.Field("Director", &m_Director, 0); // 靶色(玻璃染色 + 自发光基色;碎片同色系) pb.Field("Color", &m_Color, glm::vec3{1.0f, 0.3f, 0.25f}); // 碎裂参数(同 WallFracture 语义;靶面小 → 种子更密) pb.Field("Count", &m_Burst.p.count, 22); pb.Field("SeedRadius", &m_Burst.p.seedRadius, 0.35f); pb.Field("MinSeedDist", &m_Burst.p.minSeedDist, 0.07f); pb.Field("BurstSpeed", &m_Burst.p.burstSpeed, 1.6f); pb.Field("Falloff", &m_Burst.p.falloff, 2.0f); pb.Field("NormalPop", &m_Burst.p.normalPop, 0.6f); pb.Field("UpBias", &m_Burst.p.upBias, 0.4f); pb.Field("Lifetime", &m_Burst.p.lifetime, 6.0f); pb.Field("MaxFragments", &m_Burst.p.maxFragments, 96); pb.Field("MinImpactSpeed", &m_Burst.p.minImpactSpeed, 2.0f); } void OnCollisionEnter(u32 other, const glm::vec3& point, const glm::vec3& normal) override { // 玻璃外观:半透明 + 靶色自发光(Fire 前套用,碎片沿用; // 每次覆写代价可忽略,且吃 Inspector 实时改色)。 // alpha 0.85(与靶体 BuildGlassCube 同步:0.45 时代碎片 // 在亮背景里几乎隐形) m_Burst.look.baseColor = glm::vec4{m_Color, 0.85f}; m_Burst.look.transparent = true; m_Burst.look.emissive = m_Color * 0.7f; m_Burst.look.emissiveStrength = 3.0f; if (m_Burst.TryFire(HV(), other, point, normal)) { ReportScore(); } } 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); }}; } // 击碎报分:读导演 AcceptHits 门(回合结束不报)→ Score +1。 // 参数层 = 跨脚本通信协议(与序列化同一条路,C# 反射缺失下 // 的按名消息);导演实例未建(罕见:同帧开局碰撞)时忽略 void ReportScore() { if (m_Director == 0) return; auto& scripts = App().GetScripts(); const u32 director = static_cast(m_Director); // 参数层按名访问(ScriptRuntime 只认 ParamValue 变体, // 取值自行 std::get_if 校型) using Engine::Scripting::ParamValue; ParamValue v{true}; if (scripts.GetParam(director, "GameDirector", "AcceptHits", v)) { if (const auto* b = std::get_if(&v.v); b && !*b) { return; // 回合已结束(Director 收靶前的漏网命中) } } i32 score = 0; if (scripts.GetParam(director, "GameDirector", "Score", v)) { if (const auto* s = std::get_if(&v.v)) { score = *s; } } scripts.SetParam(director, "GameDirector", "Score", ParamValue{static_cast(score + 1)}); } i32 m_Director = 0; // 导演实体 bits(0 = 独立靶) glm::vec3 m_Color{1.0f, 0.3f, 0.25f}; Engine::Fracture::Burst m_Burst; // 碎片簿记(look 每次命中前套) }; } // namespace ENGINE_REGISTER_SCRIPT(Target)