在Unity中如何让3D模型呈现2D效果
2D原画转3D模型
为了不耽误游戏主程的开发进度,在早期的草图阶段,我们为每个场景创建了非常简单的灰箱模型,以便进行程序开发工作,同时美术设计也能同步开展。
虽然最终的2D原画会作为3D场景建模的参考,但需要注意的是,并非所有2D内容都能完全重现到3D场景中,我们只能让3D模型尽可能多地还原2D效果。
在3D建模方面,我们选择了Blender软件。这款软件功能强大且完全免费,能够满足项目的大部分需求。在Blender中建模时,我们会粗略设置一个光照,这样可以对整个场景的光照效果有一个初步的概念,也便于后续将资源导入Unity后进行光照设置。
光照、着色和纹理的技术细节
我们发现,最终模型在Blender中显示的颜色可能会比较奇怪,这是因为最终的着色与纹理化工作是完全在Unity中完成的。之所以选择在Unity中进行这些操作,是因为Unity是一款所见即所得的游戏引擎,其编辑器易于上手,在Unity中进行着色与纹理化是最快的方式,同时还能避免重复处理。我们可以先在Blender中设置好颜色,然后在Unity中通过不同的光照设置对颜色进行调整。
以《Agent A - 伪装游戏》为例,其艺术风格包含了大量的渐变效果。为了在Unity中高效创建这些渐变,我们需要找到一种合适的方法。如果在运行时仅使用一个着色器绘制渐变,会给每个场景带来大量的额外负担,并且我们希望这款游戏能在尽可能多的低配置设备上运行。
最终的解决方案是使用非常小的像素纹理来处理渐变。具体操作是在Photoshop中创建像素高度为1的图像,并在水平位置添加尽可能多的像素点来形成渐变。例如,从黑色到白色的灰度转变可以理解为1px黑色到1px白色。在Unity中,我们使用双线性滤镜(Bilinear Filtering)处理微小纹理,当纹理拉伸至整个网格大小时,就会生成一个平滑渐变。然后在着色器中添加一个旋转滑块,就可以将渐变进行360度任意旋转后附于其所在的表面,还可以复用2D渐变纹理。
提示:确保在检视面板中将纹理的Wrap模式设置为Clamp,以消除边缘的褪色。
该着色器基于Unity的Diffuse或Unlit着色器,添加了下述代码来创建UV旋转:
// 滑块属性 [0 to 2xPI]
_Rotation (“Rotation”, Range(0.0, 6.2831853071)) = 0.0
// 定义一个顶点着色器函数
#pragma surface surf Lambert vertex:vert
// 应用旋转变换矩阵
float _Rotation;
void vert (inout appdata_full v) {
v.texcoord.xy -= 0.5;
float s = sin( _Rotation );
float c = cos( _Rotation );
float2x2 rotationMatrix = float2x2( c, -s, s, c );
rotationMatrix *= 0.5;
rotationMatrix += 0.5;
rotationMatrix = rotationMatrix * 2 - 1;
v.texcoord.xy = mul ( v.texcoord.xy, rotationMatrix );
v.texcoord.xy += 0.5;
}
不同寻常的UV贴图
为了使上述旋转滑块正常工作,我们需要采用一种稍微不同的方式来展开UV。物体(Object)的每一面都需要平铺展开并填充至整个UV贴图。这意味着,如果处理正确,选择所有平面后同时查看UV,它们将被依次重叠放置。
我们想要的效果并非传统的UV贴图(选中控制面板的所有面),而是重叠放置的混乱效果(选中控制面板的所有面)。当选中每个单独的表面时,它看起来会更清晰一些(仅选中控制面板的正面)。
使用此方法,模型中每个需要进行控制的面都需要一个单独的材质。这样一来,在Unity中选中对象时,就可以使用多个材质来控制每一面的颜色、渐变和纹理。
添加光照
我们发现,在每个场景都有一束方向光的情况下,额外添加哪怕一个点光源,都会触及不影响移动设备运行帧率的极限。所以,我们尝试尽可能多地使用Diffuse着色器而非Unlit着色器,因为当场景中的道具四处移动时,使用Diffuse着色器可以看到来自方向光的实时阴影,例如下面这幅画移开后露出的秘密间谍控制台。
场景环境光通常设置为中性灰,但偶尔会加入一点其它颜色来调节气氛,比如让场景感觉更加温馨的黄色。
纹理
纹理对《Agent A - 伪装游戏》的艺术风格起着至关重要的作用。所有纹理都是通过真实摄影、在Photoshop中从零开始绘制或混合(PhotoChopped)制作而成,然后利用着色器中的通道将纹理应用到对象。
我们有两种选择可以应用到各种不同的着色器中,如Diffuse、Unlit等,这两种纹理的混合方式分别是“Multiply”和“Additive”。我们可以根据想要实现的特殊效果在它们之间进行选择,将纹理放入对应的栏位,使用该栏位的360度旋转滑块和用于控制纹理混合强度的滑块进行纹理效果的调整,它们也可以与渐变纹理一起使用。渐变纹理将覆盖在base栏位中的基本纹理上方。
下面是着色器中另一个代码段,为Multiply和Additive添加额外的纹理栏位:
void surf (Input IN, inout SurfaceOutput o) {
// 注意:我们在组合一个表面纹理材质
half4 c = _Color * tex2D (_MainTex, IN.uv_MainTex); // base texture & colour
// 后续代码可能未完整给出
}
下面是一些在门厅场景中使用着色器的示例。