技术背景
在游戏开发中,角色或物体被道具击中时产生临时的印记效果,能够大大增强游戏的反馈感和真实感。本文将解析一个基于Unity3D实现的动态贴花系统,该系统允许在物体表面实时绘制并渐隐各种类型的印记。
系统架构概览
该系统由三个核心部分组成:
-
SplatManager – 全局贴花管理器(单例)
-
SplatableObject – 可贴花物体组件
-
SplatMaskTex Shader – 贴花渲染着色器
核心实现原理
1. 贴图集(Atlas)管理策略
系统采用了一种高效的UV重映射技术,将所有可贴花物体的渲染区域整合到一张大纹理中:
// 计算网格布局 gridSize = Mathf.CeilToInt(Mathf.Sqrt(count)); float cellSize = 1.0f / gridSize; // 为每个物体分配独立的UV区域 int x = index % gridSize; int y = index / gridSize; Vector4 atlasOffsetScale = new Vector4( cellSize, cellSize, // UV缩放 x * cellSize, y * cellSize // UV偏移 );
技术要点:
-
动态计算网格布局,自动适应物体数量
-
为每个物体分配专属的UV子区域
-
通过
_AtlasOffsetScale参数在着色器中重映射UV坐标
2. 三通道RenderTexture设计
系统使用三个RenderTexture协同工作:
public RenderTexture splatTexture; // 主贴花纹理 (RGB) public RenderTexture splatTextureFade; // 渐隐纹理 (用于显示) public RenderTexture splatTextureStartTime; // 时间戳纹理 (R通道)
各通道职责:
-
splatTexture:存储所有贴花的颜色和alpha信息
-
splatTextureStartTime:存储每个像素的绘制时间戳(归一化到0-1)
-
splatTextureFade:实时计算后的渐隐结果,供物体材质采样
3. 绘制流程实现
步骤1:定位绘制区域
public void DrawSplat(Vector2 uvPos, Renderer rend, Vector4 atlasOffsetScale, float splatScale, int drawType)
通过物理射线检测获取点击点的UV坐标,结合物体的Atlas偏移,计算出在全局贴图中的实际绘制位置。
步骤2:CommandBuffer渲染
cmd.Blit(null, splatTexture, splatMaterial, 0); // 绘制颜色 cmd.Blit(null, splatTextureStartTime, splatMaterial, 1); // 记录时间戳
使用CommandBuffer执行两次渲染:
-
Pass 0:将图案绘制到splatTexture
-
Pass 1:将当前时间写入splatTextureStartTime的R通道
步骤3:时间戳编码技巧
float normalizedTimeStart = elapsedTime/1000; // 将时间写入颜色的Alpha通道 return half4(lerp(0, _InkColor.a, splatMask), 0, 0, splatMask);
巧妙之处:将时间戳归一化后存储在Alpha通道,解决了需要额外存储空间的问题。
4. 渐隐机制实现
在Update中持续计算渐隐效果:
// 读取存储的绘制时间 float storedTime = splatColorStartTime * 1000; // 还原回实际时间 // 计算时间差 float timeDiff = currentTime - storedTime; // 渐隐算法 if (timeDiff >= 12.0) fadeFactor = 0.0; else if (timeDiff > 10.0) fadeFactor = 1.0 - (timeDiff - 10.0) / 2.0;
渐隐策略:
-
前10秒保持完全可见
-
最后2秒线性淡出
-
12秒后完全消失
5. 着色器核心逻辑
顶点着色器中的UV变换
// 将物体UV映射到Atlas区域 uv.xy = v.uv1 * _AtlasOffsetScale.xy + _AtlasOffsetScale.zw; // 计算相对于点击位置的绘制UV float2 splatUV = ((v.uv1 * _AtlasOffsetScale.xy + _AtlasOffsetScale.zw) - (_SplatPos.xy * _AtlasOffsetScale.xy + _AtlasOffsetScale.zw)) / _SplatScale + 0.5;
片段着色器的多pass设计
-
Pass 0 (SplatRenderPass):绘制图案颜色
-
Pass 1 (SplatStart&MaskRenderPass):记录时间戳
-
Pass 2 (SplatFadeRenderPass):计算渐隐效果
6. 多种图案支持
系统支持四种不同类型的贴花效果:
[Header("0=EggTex,1=SplatTex,2=SnowTex,3=InkTex")] public Texture2D[] splatPattern = new Texture2D[4];
通过_drawType参数在着色器中切换不同的混合模式。
使用示例
// 在物体被击中时调用 public void ApplySplat(Vector2 hitUV, int type) { SplatManager.Instance.DrawSplat( hitUV, rend, atlasOffsetScale, splatScale, type ); }
总结
这个贴花系统通过巧妙地组合RenderTexture、UV重映射和时间戳技术,实现了一个高效且灵活的实时绘制系统。其核心优势在于:
-
高效率:通过Atlas技术减少了Draw Call
-
灵活性:支持多种图案类型
-
精准控制:可独立控制每个贴花的生命周期
-
扩展性:易于添加新的图案和效果
移动端可以使用大量胶囊碰撞体组件放入骨骼中(为了性能稍微影响一点效果),PC端直接使用Mesh碰撞体(无性能压力,效果更好)。




-DrawMe.png)



暂无评论内容