type
status
date
slug
summary
tags
category
icon
password
fullWidth
fullWidth
【C++】代码设置TriggerVolume后视窗内未更新
问题描述
用代码设置了TriggerVolume的变换之后,视窗内Actor的形状和碰撞都没有更新,需要去面板上“点”一下才行(点哪都行);而面板上的数据已更新和代码设置的一致,由此判断是面板数据不回传导致。
问题分析
改动面板数据后,视窗内物体的属性发生变化,是由于调用了
PostEditChangeProperty
这个回调函数,在这里用Brush->BuildBound
重建形状并用GEditor->RebuildAlteredBSP()
更新碰撞。参考
Brush
类的PostEditChangeProperty
的实现:解决方法
在
BrushBuilder
类重写的PostEditChangeProperty
的方法里,仿照上述方法,调用BuildBound
以重新构建TriggerVolume的形状,调用RebuildAlteredBSP
以重新构建碰撞数据:- BuildBound:
- 用来重建Brush的边界(Bounding Box)的函数。
- 当Brush的形状或位置发生变化时,需要重新计算它的包围盒。
- RebuildAlteredBSP:
- 用来重建BSP(二叉空间分割)树的函数,BSP是UE用于空间分割和碰撞检测的数据结构。
- 当Brush的形状、位置或属性改变时,需要重建BSP以保证碰撞和渲染正确。
接口封装:
【C++】得到鼠标射线向量的接口
需求描述
编辑时用鼠标射线绘制地形、样条是非常实用的功能,考虑封装一个接口。
已有实现
UEditorLevelLibrary
类的GetLevelViewportCameraInfo
方法可以获取当前关卡编辑器的视口摄像机位置和旋转,但这不太有参考价值,这个需求要的是把鼠标的屏幕坐标映射成世界坐标和方位射线。解决方法
从别的模块抄(复制)一个DeprojectScreenToWorld方法来,把鼠标的屏幕坐标映射到世界坐标,并得到鼠标射线方向向量。
方法实现:
接口封装:
【C++】根据端口号获取运行中进程的exe路径
需求描述
起服之前要查询服务器端口是否被引用进程占用,若被占用则杀死引用进程;因此需要一个接口,根据指定的端口号查找所有占用该端口的进程的可执行文件路径。
解决方法
- 调用
GetTcpTable2
函数获取当前系统的TCP连接表(第一次调用获取所需缓冲区大小,分配足够内存后再次调用获取实际数据)。
- 查找本地端口等于目标端口的连接(注意要将本地端口号从网络字节序转换为主机字节序),通过进程ID打开进程句柄,用
GetModuleFileNameEx
获取可执行文件路径。
MIB_TCPTABLE2
结构体仅包含dwOwningPid
(进程ID),没有直接存储进程的可执行文件路径,必须用 OpenProcess
打开进程,才能进一步查询其路径。- 关闭进程句柄,释放TCP表内存。
- 使用
TSet
自动去重后转为TArray
返回。
【Python】Tkinter线程通信解决UI卡顿
问题描述
信息的获取要请求服务器,此过程耗时,会阻塞线程导致UI卡顿。而获取信息后要呈现在面板上,因此需要有一个回调到主线程的机制(Tkinter是单线程GUI工具包,所有GUI操作,包括更新界面、处理事件,必须在主线程中执行)。
解决方法
把耗时的信息获取操作做成异步,放在子线程中处理;得到的信息通过
Tkinter
的after
方法回到主线程,并呈现在UI上。after()
的工作原理——通过事件队列实现跨线程通信- 事件队列机制
Tkinter 的主线程运行一个事件循环(
mainloop()
),不断检查事件队列(如按钮点击、窗口重绘等)。after()
的作用是向这个队列插入一个自定义事件。
- 线程安全的通信
当其他线程调用
after(0, callback)
时,Tkinter会将callback
封装成一个事件,安全地插入主线程的事件队列。主线程在下次处理事件时,会执行这个回调。
- 主线程启动异步任务
__async_fetch_and_log
- 异步任务
__async_fetch_and_log
中获取版本信息
__log_results_on_main_thread
中log信息通过Tkinter
的after
方法回到主线程
【Python】使用watchdog库监听文件内容变化
问题描述
有一个业务场景:UE编辑器抛异常时会把异常信息写入到
error.txt
中,使用 Python 开发的工作小助手如果处于后台运行模式,需要监听 error.txt
文件的变化,若发生变化则弹出报错弹窗提示用户联系专人处理。解决方法
使用第三方库
watchdog
。watchdog
是一个 Python 库,用于监听文件系统事件(如创建、修改、删除、移动等),内部实现基于操作系统提供的底层文件监控机制:- Windows:
ReadDirectoryChangesW
- Linux:
inotify
- macOS:
FSEvents
以Window平台为例,WindowsApiEmitter将更底层的系统 API 封装其中:
watchdog
的核心组成:Observer
:启动监听线程,管理事件调度- 在后台运行,监听文件系统变化
- 使用
schedule()
方法注册要监听的目录和事件处理器 - 调用
start()
启动监听线程,stop()
停止监听
FileSystemEventHandler
:处理文件系统事件的基类,可以自定义回调方法on_modified(event)
→ 文件被修改on_created(event)
→ 文件被创建on_deleted(event)
→ 文件被删除on_moved(event)
→ 文件被移动/重命名on_any_event(event)
→ 所有事件都会触发
observer
监听文件变化并处理事件,调试面板新增两个子线程:- 主监控线程(
observer.start()
):由observer.start()
直接创建,管理文件系统事件的监听
- 事件分发线程(
emitter.start()
):watchdog
内部自动创建,用于解耦事件捕获和事件处理,将文件系统事件从内核传递到Python回调
BaseObserver.start()
内部实现:最小化到托盘后启动
observer
:从托盘恢复窗口后关闭
observer
:【网络】本地回环地址和通配地址端口占用问题
问题描述
最近在调试一个本地游戏服务器时,发现一个有趣的现象:
- 先用 Python 启动一个 Socket 监听
127.0.0.1:9500
。
- 然后启动游戏服务器,默认监听
0.0.0.0:9500
。
- 结果发现两个服务都能正常运行,没有端口冲突。
控制台显示:
通配地址
0.0.0.0
和回环地址127.0.0.1
地址 | 0.0.0.0 | 127.0.0.1 (localhost) |
作用 | 监听所有网络接口(本机+外部) | 仅监听本地回环(本机内部通信) |
可访问性 | 外部设备可以访问(如手机、其他电脑) | 仅本机可以访问 |
典型用途 | Web 服务器、游戏服务器、数据库 | 本地开发调试、内部进程通信 |
原因分析
TCP套接字由
(IP, Port)
唯一标识,而不是单纯靠端口号。因此Python程序监听的127.0.0.1:9500
和游戏服务器监听的 0.0.0.0:9500
是两个不同的监听端点,不会冲突。让Python程序的套接字绑定到
0.0.0.0:9500
再启动服务器,发现发生端口冲突,服务器无法启动。- Author:Yuki
- URL:http://shirakoko.xyz/article/work-note
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!
Relate Posts