物理修复与相机防穿墙:Jolt Trace 接管(缺省 DummyTrace 带 JPH_ASSERT(false),调试版一被调用即断;同文去重防多线程刷屏);MeshShape 三角索引补基址(此前把 materialIndex/userData 当顶点偏移传 → 每个 mesh 三角全指向前一 mesh 顶点区,碰撞形状错位 + AABBTree 随机分割告警);调试绘制巨型网格三角预算(>5 万三角退化为包围盒线框,避免百万级 DrawLine 打到个位数帧率);角色 mEnhancedInternalEdgeRemoval 消网格地面 ghost contact 顶起/抖动;新增 RayCastStatic(只命中非移动层,碎块/动态物不当遮挡)→ ThirdPersonCamera 防穿墙拉近(瞬时拉近、平滑回弹、贴墙最小距离与回退余量可配)
This commit is contained in:
@@ -11,6 +11,9 @@
|
||||
// OnStart 从编辑器摆的机位反推 yaw/pitch/dist:编辑器摆哪,游戏就
|
||||
// 从哪个角度开场。Esc 释放光标(调参),左键重捕继续玩。
|
||||
//
|
||||
// 防穿墙:枢轴→期望机位做静态几何射线(UE SpringArm 同位),命中则拉近;
|
||||
// 拉近瞬时、拉远平滑,贴墙最小距离可配。
|
||||
//
|
||||
|
||||
#include <Engine/Scripting/Script.h>
|
||||
#include <Engine/Core/Application.h>
|
||||
@@ -18,17 +21,24 @@
|
||||
#include <Engine/Core/Log.h>
|
||||
#include <Engine/ECS/Components.h>
|
||||
#include <Engine/ECS/Scene.h>
|
||||
#include <Engine/Physics/PhysicsRay.h> // RayHit(防穿墙射线结果)
|
||||
#include <Engine/Physics/PhysicsWorld.h> // App().GetPhysics().RayCastStatic 门面
|
||||
|
||||
#include <entt/entt.hpp>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
using namespace Engine;
|
||||
|
||||
namespace {
|
||||
|
||||
// 拉远回弹响应(1/s,指数逼近):离开墙角后镜头平滑归位。
|
||||
// 拉近是瞬时的(见 OnUpdate)——遮挡晚一帧就会穿墙,不能平滑
|
||||
constexpr float kCameraReturnResponse = 8.0f;
|
||||
|
||||
class ThirdPersonCamera final : public Engine::Scripting::ScriptBehavior {
|
||||
public:
|
||||
const char* Name() const override { return "ThirdPersonCamera"; }
|
||||
@@ -50,6 +60,13 @@ namespace {
|
||||
pb.Field("FollowResponse", &m_FollowResponse, 12.0f);
|
||||
// 目标 Y 瞬移超过该距离(PIE 传送/回合复位)→ 直接吸附
|
||||
pb.Field("SnapDistance", &m_SnapDistance, 3.0f);
|
||||
// 相机防穿墙(UE SpringArm 同位):枢轴→期望机位之间若有静态
|
||||
// 几何,把相机拉到命中点前。关掉 = 旧行为(可穿墙)
|
||||
pb.Field("CameraCollision", &m_Collision, true);
|
||||
// 贴墙时相机离枢轴的最小距离(再近会切进角色/近平面)
|
||||
pb.Field("MinDistance", &m_MinDistance, 0.35f);
|
||||
// 命中点回退余量(防止相机面贴墙 → z-fighting/切面)
|
||||
pb.Field("CollisionSkin", &m_CollisionSkin, 0.25f);
|
||||
}
|
||||
|
||||
void OnStart() override {
|
||||
@@ -154,8 +171,31 @@ namespace {
|
||||
std::sin(yawR) * std::cos(pitchR),
|
||||
std::sin(pitchR),
|
||||
std::cos(yawR) * std::cos(pitchR));
|
||||
// ---- 相机防穿墙:枢轴 → 期望机位射线拉近 ----
|
||||
// 只打静态几何(碎块/动态物不当遮挡,避免镜头被飘过的碎片
|
||||
// 乱拉);枢轴在角色胶囊内,角色是 CharacterVirtual 不进射线,
|
||||
// 不会自己挡自己。拉近瞬时(遮挡晚一帧就穿墙),拉远平滑
|
||||
float wantDist = m_Distance;
|
||||
if (m_Collision) {
|
||||
RayHit hit;
|
||||
if (App().GetPhysics().RayCastStatic(
|
||||
pivot, dir, m_Distance + m_CollisionSkin, hit)) {
|
||||
wantDist = std::max(hit.distance - m_CollisionSkin,
|
||||
m_MinDistance);
|
||||
}
|
||||
}
|
||||
if (!m_DistInit) { // 首帧吸附(无回弹动画)
|
||||
m_CurDist = wantDist;
|
||||
m_DistInit = true;
|
||||
} else if (wantDist < m_CurDist) {
|
||||
m_CurDist = wantDist; // 拉近:瞬时
|
||||
} else {
|
||||
m_CurDist += (wantDist - m_CurDist) *
|
||||
(1.0f - std::exp(-kCameraReturnResponse * dt));
|
||||
}
|
||||
|
||||
auto& camT = Transform();
|
||||
camT.SetPosition(pivot + dir * m_Distance);
|
||||
camT.SetPosition(pivot + dir * m_CurDist);
|
||||
|
||||
// ---- 朝向锁定目标 ----
|
||||
// 引擎 YXZ 序(R = Ry·Rx)视向 = (-cosP sinY, sinP, -cosP cosY)
|
||||
@@ -178,6 +218,11 @@ namespace {
|
||||
float m_SnapDistance = 3.0f; // Y 瞬移吸附阈值 m
|
||||
float m_FollowPivotY = 0.0f; // 阻尼后的枢轴高度(XZ 硬跟)
|
||||
bool m_FollowInit = false; // 首帧吸附基准
|
||||
bool m_Collision = true; // 相机防穿墙开关
|
||||
float m_MinDistance = 0.35f; // 贴墙最小距离
|
||||
float m_CollisionSkin = 0.25f; // 命中点回退余量
|
||||
float m_CurDist = 0.0f; // 防穿墙后的当前距离(拉近平滑态)
|
||||
bool m_DistInit = false; // 距离首帧吸附基准
|
||||
float m_Yaw = 0.0f;
|
||||
float m_Pitch = 20.0f;
|
||||
entt::entity m_Target = entt::null;
|
||||
|
||||
Reference in New Issue
Block a user