C++更新UTextureRenderTarget2D出现Assertion Failed报错如何解决
报错原因
RenderTarget->InitCustomFormat触发的渲染资源初始化是异步操作:游戏线程调用该接口后仅会向渲染线程提交资源创建请求,不会等待渲染线程完成初始化,此时立刻在游戏线程调用GetRenderTargetTexture()大概率会拿到未完成初始化的无效RHI引用。- 跨线程捕获RHI引用存在生命周期风险:RHI资源的引用计数管理和生命周期与渲染线程强绑定,在游戏线程获取的
FTexture2DRHIRef直接捕获到渲染线程命令的lambda中时,可能出现资源被提前释放、引用失效的问题。 - 异常参数问题:如果传入的
Width/Height数值为0或负数,或者RenderTarget本身是被标记为待销毁的无效对象,也会导致获取的RHI引用为空。
修复方案
核心逻辑是将RHI资源的获取操作移到渲染线程内部执行,同时增加对象生命周期校验,避免空引用问题,修复后代码如下:
void AWorldCreator::BeginPlay() { Super::BeginPlay(); // 提前做参数合法性校验 if (RenderTarget == nullptr || Width <= 0 || Height <= 0) { return; } RenderTarget->InitCustomFormat(Width, Height, PF_B8G8R8A8, true); // 用弱指针捕获RenderTarget,避免渲染线程执行前对象被GC销毁 TWeakObjectPtr<UTextureRenderTarget2D> WeakRT = RenderTarget; const int32 RTWidth = Width; const int32 RTHeight = Height; ENQUEUE_RENDER_COMMAND(UpdateTextureRegionsData)( [WeakRT, RTWidth, RTHeight](FRHICommandListImmediate& RHICmdList) { // 渲染线程内部依次校验各资源有效性 UTextureRenderTarget2D* ValidRT = WeakRT.Get(); if (!ValidRT) { return; } FTextureRenderTargetResource* RTResource = ValidRT->GetRenderTargetResource(); if (!RTResource) { return; } FTexture2DRHIRef TextureRHI = RTResource->GetRenderTargetTexture(); check(TextureRHI.IsValid()); // 后续纹理更新逻辑可在此处编写 }); }
额外注意事项
- 如果业务逻辑允许,建议尽量提前初始化RenderTarget(比如在编辑器中预先配置好尺寸,或在构造函数、PostInitializeComponents阶段完成
InitCustomFormat调用),避免在BeginPlay中刚完成初始化就立刻操作的时序风险。 - 你当前已引入的模块依赖是齐全的,无需额外新增模块。
内容的提问来源于stack exchange,提问作者NedCrow
相关产品推荐
相关产品推荐

