From 6d9b688f0fdbae0a679f9d85f7522aa071c7bcd9 Mon Sep 17 00:00:00 2001 From: BlueRose <378100977@qq.com> Date: Mon, 14 Jul 2025 15:06:59 +0800 Subject: [PATCH] vault backup: 2025-07-14 15:06:59 --- .../ShaderWorldPlugin/ShaderWorld.md | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/03-UnrealEngine/Rendering/RenderFeature/ShaderWorldPlugin/ShaderWorld.md b/03-UnrealEngine/Rendering/RenderFeature/ShaderWorldPlugin/ShaderWorld.md index 446f8ce..a646555 100644 --- a/03-UnrealEngine/Rendering/RenderFeature/ShaderWorldPlugin/ShaderWorld.md +++ b/03-UnrealEngine/Rendering/RenderFeature/ShaderWorldPlugin/ShaderWorld.md @@ -1069,3 +1069,101 @@ OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZEZ"), 1); # 植被生成逻辑 Tick() => TerrainAndSpawnablesManagement() => UpdateSpawnables() => UpdateSpawnable() + + +# 碰撞Python逻辑 + +```python +def TickCheckWorldReady(self, dt: float) -> bool: + is_shader_world_ready = self.ShaderWorldActor.WorldAndCollisionGeneratedReady() + if not is_shader_world_ready: + return True + is_ready = self.ShaderWorldActor.CheckCollisionGeneratedReady(self.AvatarBornPosition) + print("LBK -------- TickCheckWorldReady", self.FailedCheckCnt, is_ready) + if is_ready: + self.OnWorldMeshReady() + ue.RemoveTicker(self.worldTickHander) + # 等待地形物理加载完毕 + if self.OtherLoadFinshed: + GlobalData.TimerSystem.AddTimer(1, self.ReallyStartDriving) + else: + self.OtherLoadFinshed = True + print('LBK -------------- DrivingModeSystem: TickCheckWorldReady', GlobalData.p.pos, self.AvatarBornPosition) + return False + self.FailedCheckCnt += 1 + if self.FailedCheckCnt > self.FailedAttemptCnt: #self.FailedAttemptCnt为40 + self.ShaderWorldActor.RebuildWorld() + self.FailedCheckCnt = 0 + return True + +# 通过LineTraceSingleForObjects检测碰撞高度是否超过5,来判断碰撞是否生成。 +def CheckCollisionGeneratedReady(self, checkPosition: ue.Vector) -> bool: + HitStartLocation = checkPosition + ue.Vector(0, 0, 50000.0) + HitEndLocation = checkPosition + ue.Vector(0, 0, -50000.0) + hitState, hitResult = ue.KismetSystemLibrary.LineTraceSingleForObjects( + self.GetWorld(), + HitStartLocation, + HitEndLocation, + [ue.EObjectTypeQuery.ObjectTypeQuery1, ue.EObjectTypeQuery.ObjectTypeQuery13], # Ground + False, # 是否追踪复杂碰撞 + [], + ue.EDrawDebugTrace.ForDuration if GlobalData.IsDebugMode else ue.EDrawDebugTrace.NONE, # 调试可视化 + True, # 忽略自身 + ue.LinearColor(1.0, 0.0, 0.0, 1.0), # 红色 + ue.LinearColor(0.0, 1.0, 0.0, 1.0), # 绿色 + 20.0 # 调试线条持续时间 + ) + if not hitState: + return False + # TODO LBK 这个射线检测的方式不太准确,那个物理生成,会从平面开始 + return hitResult.Location.Z > 5.0 +``` + +```c++ +bool AShaderWorldActor::WorldAndCollisionGeneratedReady() +{ + if (!WorldGeneratedAndReady()) + return false; + if (!CollisionShareable.IsValid()) + return false; + + FScopeLock CollisionMeshArrayAccess(CollisionMeshAccessLock.Get()); + + // 1. 必须有碰撞布局 + if (CollisionShareable->GroundCollisionLayout.Num() == 0) + return false; + + // 2. 检查所有Patch都ready + for (const auto& Pair : CollisionShareable->GroundCollisionLayout) + { + const FIntVector& Loc = Pair.Key; + const FName& CollisionName = Pair.Value; + + // Patch必须存在 + if (!CollisionMesh.Contains(CollisionName)) + return false; + + // Patch必须在已用集合 + if (!CollisionShareable->UsedCollisionMesh.Contains(CollisionName)) + return false; + + // Patch必须ReadBack完成 + const FCollisionMeshElement& CollisionElement = *CollisionMesh.Find(CollisionName); + if (!CollisionElement.ReadBackCompletion.IsValid() || !(*CollisionElement.ReadBackCompletion.Get())) + return false; + + // Patch不能在待处理队列 + if (CollisionReadToProcess.Contains(CollisionName)) + return false; + if (!UsedCollisionMesh.Contains(CollisionName)) + return false; + + // Patch不能在工作队列 + for (const auto& WQ : CollisionWorkQueue) + if (WQ.MeshID == CollisionName) + return false; + } + + return true; +} +``` \ No newline at end of file