pic

技术背景

在游戏开发中,角色或物体被道具击中时产生临时的印记效果,能够大大增强游戏的反馈感和真实感。本文将解析一个基于Unity3D实现的动态贴花系统,该系统允许在物体表面实时绘制并渐隐各种类型的印记。

系统架构概览

该系统由三个核心部分组成:

  1. SplatManager – 全局贴花管理器(单例)

  2. SplatableObject – 可贴花物体组件

  3. SplatMaskTex Shader – 贴花渲染着色器

核心实现原理

1. 贴图集(Atlas)管理策略

系统采用了一种高效的UV重映射技术,将所有可贴花物体的渲染区域整合到一张大纹理中:

csharp
// 计算网格布局
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协同工作:

csharp
public RenderTexture splatTexture;      // 主贴花纹理 (RGB)
public RenderTexture splatTextureFade;   // 渐隐纹理 (用于显示)
public RenderTexture splatTextureStartTime; // 时间戳纹理 (R通道)

各通道职责

  • splatTexture:存储所有贴花的颜色和alpha信息

  • splatTextureStartTime:存储每个像素的绘制时间戳(归一化到0-1)

  • splatTextureFade:实时计算后的渐隐结果,供物体材质采样

3. 绘制流程实现

步骤1:定位绘制区域

csharp
public void DrawSplat(Vector2 uvPos, Renderer rend, Vector4 atlasOffsetScale, float splatScale, int drawType)

通过物理射线检测获取点击点的UV坐标,结合物体的Atlas偏移,计算出在全局贴图中的实际绘制位置。

步骤2:CommandBuffer渲染

csharp
cmd.Blit(null, splatTexture, splatMaterial, 0);  // 绘制颜色
cmd.Blit(null, splatTextureStartTime, splatMaterial, 1); // 记录时间戳

使用CommandBuffer执行两次渲染:

  • Pass 0:将图案绘制到splatTexture

  • Pass 1:将当前时间写入splatTextureStartTime的R通道

步骤3:时间戳编码技巧

csharp
float normalizedTimeStart = elapsedTime/1000;
// 将时间写入颜色的Alpha通道
return half4(lerp(0, _InkColor.a, splatMask), 0, 0, splatMask);

巧妙之处:将时间戳归一化后存储在Alpha通道,解决了需要额外存储空间的问题。

4. 渐隐机制实现

在Update中持续计算渐隐效果:

csharp
// 读取存储的绘制时间
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变换

csharp
// 将物体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. 多种图案支持

系统支持四种不同类型的贴花效果:

csharp
[Header("0=EggTex,1=SplatTex,2=SnowTex,3=InkTex")]
public Texture2D[] splatPattern = new Texture2D[4];

通过_drawType参数在着色器中切换不同的混合模式。

 

使用示例

csharp
// 在物体被击中时调用
public void ApplySplat(Vector2 hitUV, int type)
{
    SplatManager.Instance.DrawSplat(
        hitUV, 
        rend, 
        atlasOffsetScale, 
        splatScale, 
        type
    );
}

总结

这个贴花系统通过巧妙地组合RenderTexture、UV重映射和时间戳技术,实现了一个高效且灵活的实时绘制系统。其核心优势在于:

  • 高效率:通过Atlas技术减少了Draw Call

  • 灵活性:支持多种图案类型

  • 精准控制:可独立控制每个贴花的生命周期

  • 扩展性:易于添加新的图案和效果

移动端可以使用大量胶囊碰撞体组件放入骨骼中(为了性能稍微影响一点效果),PC端直接使用Mesh碰撞体(无性能压力,效果更好)。

© 版权声明
THE END
喜欢就支持一下吧
点赞14 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容