新增脚本实体底座与碰撞事件:Spawn/Destroy + OnCollisionEnter/Exit + TestShoot 验收脚本
- ScriptBehavior::Spawn/Destroy:Scene::CreateEntity / 延迟销毁队列直达(实现下沉 ScriptRuntime.cpp,避 Application 不完整类型) - ScriptRuntime::DispatchCollisions:帧首把 PhysicsWorld::GetEvents 派发到涉事实例(Persisted 跳过、禁用不收;回调内 spawn/destroy 安全) - TestShoot:左键 spawn 动态球刚体子弹,OnCollisionEnter 命中点生成 ImpactFx 特效实体并自毁,超时防泄漏
This commit is contained in:
@@ -28,6 +28,7 @@
|
||||
#include <Engine/Core/Types.h>
|
||||
#include <Engine/ECS/Components.h>
|
||||
#include <Engine/ECS/Scene.h>
|
||||
#include <Engine/ECS/EntityHandle.h> // 须在 Scene.h 之后(内联方法需完整 Scene)
|
||||
#include <Engine/Scripting/ScriptParam.h>
|
||||
|
||||
#include <string>
|
||||
@@ -69,6 +70,22 @@ namespace Engine {
|
||||
// 在此按名取值)
|
||||
virtual void OnParamsApplied() {}
|
||||
|
||||
// ---- 碰撞回调(PhysicsWorld::GetEvents 帧首派发,ScriptRuntime
|
||||
// 转发;事件语义 = 最近一次物理步进)----
|
||||
// Enter/Exit 由 Jolt Added/Removed 转发;Persisted 不回调
|
||||
//(最小 API,接触持续期无每帧噪音)。对方是触发器(sensor)
|
||||
// 时同样触发——后续按需拆 OnTriggerEnter/Exit。
|
||||
// other = 对方实体位模式(还原:static_cast<entt::entity>(other),
|
||||
// 回调时对方可能已销毁,用前自行 Scene::IsAlive 校验)。
|
||||
// 派发在 Sync/OnUpdate 之前:回调里 spawn/destroy 安全
|
||||
//(destroy 入延迟队列,spawn 由下一帧对账消化)
|
||||
virtual void OnCollisionEnter(u32 other,
|
||||
const glm::vec3& point,
|
||||
const glm::vec3& normal) {
|
||||
(void)other; (void)point; (void)normal;
|
||||
}
|
||||
virtual void OnCollisionExit(u32 other) { (void)other; }
|
||||
|
||||
protected:
|
||||
// 便捷访问:绑定实体的 TransformComponent
|
||||
ECS::TransformComponent& Transform() {
|
||||
@@ -96,6 +113,16 @@ namespace Engine {
|
||||
|
||||
bool Valid() const { return m_Scene != nullptr && m_Entity != entt::null; }
|
||||
|
||||
// ---- 场景实体 spawn/destroy 底座(Unity Instantiate/Destroy
|
||||
// 同位)----
|
||||
// spawn:帧内即时创建(UUID + Transform + Name 出生即有),
|
||||
// 组件由脚本自行 AddComponent 装配;RigidBody/ScriptComponent
|
||||
// 分别由 PhysicsWorld/ScriptRuntime 下一帧对账消化
|
||||
ECS::EntityHandle Spawn(const std::string& name);
|
||||
// destroy:延迟——入队,帧尾 FlushDestroyQueue 统一执行
|
||||
//(遍历安全);调用方持有的句柄此后悬空
|
||||
void Destroy(ECS::Entity e);
|
||||
|
||||
// ---- 组件启停(Unity SetActive / Behaviour.enabled 语义)----
|
||||
// 自身组件总开关(整个脚本组件停 tick,实例保留)
|
||||
void SetActive(bool on) {
|
||||
|
||||
@@ -66,6 +66,10 @@ namespace Engine {
|
||||
|
||||
private:
|
||||
void Sync();
|
||||
// 碰撞事件派发(Update 开头、Sync 之前):PhysicsWorld 最近
|
||||
// 一次步进的事件转发到涉事实例的 OnCollisionEnter/Exit。
|
||||
// Persisted 跳过;实例未建/已禁用不收
|
||||
void DispatchCollisions();
|
||||
|
||||
ECS::Scene& m_Scene;
|
||||
Application* m_App; // 注入脚本上下文
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
#include <Engine/Core/Application.h>
|
||||
#include <Engine/Core/Log.h>
|
||||
#include <Engine/ECS/Components.h>
|
||||
#include <Engine/ECS/EntityHandle.h>
|
||||
#include <Engine/Physics/PhysicsEvents.h>
|
||||
#include <Engine/Physics/PhysicsWorld.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@@ -19,6 +22,16 @@ namespace Engine {
|
||||
return *m_App;
|
||||
}
|
||||
|
||||
// ---- 场景实体 spawn/destroy 底座(声明在 Script.h,实现下沉
|
||||
// 此处——Application 完整类型只在 cpp 可见)----
|
||||
ECS::EntityHandle ScriptBehavior::Spawn(const std::string& name) {
|
||||
return App().GetScene().CreateEntity(name);
|
||||
}
|
||||
|
||||
void ScriptBehavior::Destroy(ECS::Entity e) {
|
||||
App().GetScene().DestroyEntity(e);
|
||||
}
|
||||
|
||||
// ---- 参数按名读写(ScriptBehavior 声明,经绑定表;写穿
|
||||
// Item.params 由运行时 SetParam 完成)----
|
||||
bool ScriptBehavior::WriteParam(const std::string& name,
|
||||
@@ -41,7 +54,47 @@ namespace Engine {
|
||||
return false;
|
||||
}
|
||||
|
||||
// ---- 碰撞事件派发(Update 开头、Sync 之前):PhysicsWorld 最近
|
||||
// 一次步进收集的事件转发到涉事实例。时序保证:Step 先于
|
||||
// Update(帧循环序)→ 此处读到的是本帧物理结果;回调里
|
||||
// spawn/destroy 安全——destroy 入延迟队列(帧尾 flush),
|
||||
// spawn 不改 m_Instances(下一帧 Sync 对账建实例)。禁用
|
||||
// 实例不收(Unity enabled 语义对齐);Persisted 每步都来,
|
||||
// 直接跳过(Enter/Exit 已够 gameplay 用)
|
||||
void ScriptRuntime::DispatchCollisions() {
|
||||
if (!m_App) {
|
||||
return;
|
||||
}
|
||||
const std::vector<CollisionEvent>& events =
|
||||
m_App->GetPhysics().GetEvents();
|
||||
for (const auto& ev : events) {
|
||||
if (ev.kind == CollisionEvent::Kind::Persisted) {
|
||||
continue;
|
||||
}
|
||||
const bool enter = ev.kind == CollisionEvent::Kind::Added;
|
||||
for (const u32 self : {ev.a, ev.b}) {
|
||||
const u32 other = (self == ev.a) ? ev.b : ev.a;
|
||||
const auto it = m_Instances.find(self);
|
||||
if (it == m_Instances.end()) {
|
||||
continue;
|
||||
}
|
||||
for (auto& inst : it->second) {
|
||||
if (!inst.behavior || !inst.enabled) {
|
||||
continue;
|
||||
}
|
||||
if (enter) {
|
||||
inst.behavior->OnCollisionEnter(
|
||||
other, ev.point, ev.normal);
|
||||
} else {
|
||||
inst.behavior->OnCollisionExit(other);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptRuntime::Update(f32 dt) {
|
||||
DispatchCollisions();
|
||||
Sync();
|
||||
|
||||
auto& reg = m_Scene.GetRegistry();
|
||||
|
||||
Reference in New Issue
Block a user