本篇主要用于记录自己的实战操作,以及一些碎碎念(观后感),如果有什么好想法或者本篇出现什么错误,请多指教~

本篇的内容参考视频:庄懂的技术美术入门课(美术向) 使用软件:Unity 2019 3.6f1 ,ShaderForge

本篇内容主要包括:钟表小人的制作;


1.准备工作

  • 模型
  • unity制作美术字_unity制作美术字

  • SD处理贴图
    为什么不用PS用SD,一个是批量处理,一个是PS的涂抹可能会导致某些效果出错;

NoFace节点创建:

  • 首先为了了解效果先用单张贴图做处理,通过Transform节点放大贴图额头局部,再做tilling,然后底下通过SVG去绘制遮罩(记得将颜色设置为GrayScale)然后与Bevel节点相连做柔和处理;
  • unity制作美术字_unity制作美术字_02

  • 为了批量处理,再将贴图和输出结果都替换成可选择的;

unity制作美术字_批量处理_03


unity制作美术字_贴图_04


unity制作美术字_贴图_05

  • 最后在总节点里,分别处理各贴图;

unity制作美术字_System_06

clock节点创建:

  • 首先利用Text节点制作数字,然后在Patterns里找到一个圆形分布的节点,并分别连接六个数字(自定义最大六个),然后用blendMax方式混合取亮度区域;

unity制作美术字_System_07

unity制作美术字_System_08

  • 接下来用bevel对数字柔化,并添加一个图形作为中间的装饰,将两者混合输出;

unity制作美术字_批量处理_09

  • 最后在总节点里,导入并调整大小使其与表盘相当,并根据调整后的图,制作法线贴图,AO贴图,增强对比度的操作,根据法线贴图制作曲率图;

总节点操作:

  • 利用上面的遮罩,在相应位置取色并混合乱成麻花了…
  • unity制作美术字_贴图_10

  • 法线贴图的处理仅需将表盘与原法线贴图的结合在一起;

表针的SD处理:

  • 首先先导入模型并烘焙得到物体的世界空间下的法线贴图;
  • unity制作美术字_贴图_11

  • 用烘焙出的贴图求得曲率图和AO图

unity制作美术字_批量处理_12

  • 利用Shape节点结合放缩节点制作三个指针的大致遮罩,以便后面进行加工处理;
  • 划痕取自SD中内置的噪波图,并取反,获得遮罩图,然后再引入一个边缘破损的图对指针进行混合处理,再与之前的指针遮罩混合得到划痕效果;
  • 我们从颜色贴图里引出一个HSL节点用于调色相饱和度亮度,再与其本身使用Blend混合,遮罩取自时针的遮罩图,同样的操作处理分针秒针进行基础色上色;
  • 再跟据之前处理表盘的掉漆处理,处理针的掉漆,法线贴图则取自于掉漆遮罩的节点,最后将处理好的图该合并的合并然后输出;

2.代码

  • 我们以之前的oldschoolpro为基础,添加时分秒针的相关参数以及偏移量用于校正旋转中心,然后和上一篇里说的旋转一样,声明函数;
  • 接下来我们要使小人时间和系统时间一致,编写C#脚本,就先声明几个变量,Material一个,然后三个针的ID各一个,Unity中对于材质的寻找并不像是场景中 的物体以名字找,而是在游戏开始之初根据ID寻找,再声明一个valid布尔类型变量以判断是否有效,当无效时省的让其脚本继续运行徒增负荷;
  • 然后就是在update函数里进行获取当前时间和给材质中参数赋值的操作;

最终效果:

unity制作美术字_贴图_13

c#代码如下:

using System.Collections;
using System;
using System.Collections.Generic;
using UnityEngine;

public class clock : MonoBehaviour
{
    // Start is called before the first frame update
    public Material clockmat;
    private bool valid;
    private int hourAnglePropID;
    private int minuteAnglePropID;
    private int secondAnglePropID;

    void Start()
    {
        if (clockmat != null)
        {
            hourAnglePropID   = Shader.PropertyToID("_HourHandAngle");//获取属性名的ID值
            minuteAnglePropID = Shader.PropertyToID("_MinuteHandAngle");
            secondAnglePropID = Shader.PropertyToID("_SecondHandAngle");
            if (clockmat.HasProperty(hourAnglePropID) && clockmat.HasProperty(minuteAnglePropID) && clockmat.HasProperty(secondAnglePropID))
             valid = true;
        }

       
    }

    // Update is called once per frame
    void Update()
    {
        if (!valid) return;
        int second = DateTime.Now.Second;//获取本电脑上的时间;
        float secondAngle = second / 60.0f * 360.0f;//获取转动值
        int minute = DateTime.Now.Minute;
        float minuteAngle = minute / 60.0f * 360.0f;
        int hour = DateTime.Now.Hour;
        float hourAngle = (hour % 12) / 12.0f * 360.0f + minuteAngle / 360.0f * 30.0f;//映射下,一分钟跳一小小格
        clockmat.SetFloat(secondAnglePropID, secondAngle);//设定Material中的转动值
        clockmat.SetFloat(minuteAnglePropID, minuteAngle);
        clockmat.SetFloat(hourAnglePropID, hourAngle);
    }
}

Shader关键代码如下:

void clockrotate(inout float3 vertex,float angle,float offset,float mask){
			    vertex.y -=offset*mask;
				float radZ=radians(angle*mask);
				float sinz,cosz=0.0;
				sincos(radZ,sinz,cosz);
				vertex.xy=float2(
				vertex.x*cosz-vertex.y*sinz,
				vertex.x*sinz+vertex.y*cosz
				);
			    vertex.y+=offset*mask;
			}
			void ClockAnime(float3 color,inout float3 vertex){
			    clockrotate(vertex,_HourHandAngle,_RotateOffset,color.r);
			    clockrotate(vertex,_MinuteHandAngle,_RotateOffset,color.g);
			    clockrotate(vertex,_SecondHandAngle,_RotateOffset,color.b);
			}