一、前言

UnityiPad
文章末尾

我把自己画成一个孩子,我希望每个人心中都有一个小孩子,不忘本心,永远清澈明朗,无忧亦无惧。
好了,扯远了,回归本文主题,六一儿童节,我们一起来当小朋友吧。

二、一起来画猫猫

UnityDemoAIShiftC3yyq
DemoCodeChinaUnityUnity 2020.2.7f1c1 (64-bit)
Demo

三、爬虫,无穷只猫

画不好,没关系,多看些猫图,给你准备了爬虫,无穷只猫~

爬虫python代码

import requests
import os
import urllib

# 百度图片爬虫
class Spider_baidu_image():
    def __init__(self):
        self.url = 'http://image.baidu.com/search/acjson?'
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.\
            3497.81 Safari/537.36'}
        self.headers_image = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.\
            3497.81 Safari/537.36','Referer':'http://image.baidu.com/search/index?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=-1&st=-1&fm=result&fr=&sf=1&fmq=1557124645631_R&pv=&ic=&nc=1&z=&hd=1&latest=0&copyright=0&se=1&showtab=0&fb=0&width=&height=&face=0&istype=2&ie=utf-8&sid=&word=%E8%83%A1%E6%AD%8C'}

    # 构造参数数组
    def get_param(self):
        keyword = urllib.parse.quote(self.keyword)
        params = []
        for i in range(1,self.paginator+1):
            params.append('tn=resultjson_com&ipn=rj&ct=201326592&is=&fp=result&queryWord={}&cl=2&lm=-1&ie=utf-8&oe=utf-8&adpicid=&st=-1&z=&ic=&hd=1&latest=0&copyright=0&word={}&s=&se=&tab=&width=&height=&face=0&istype=2&qc=&nc=1&fr=&expermode=&force=&cg=star&pn={}&rn=30&gsm=78&1557125391211='.format(keyword,keyword,30*i))
        return params

    # 构造url数组
    def get_urls(self, params):
        urls = []
        for i in params:
            urls.append(self.url+i)
        return urls

    # 遍历请求url并下载图片
    def get_image(self, urls):
        cwd = os.getcwd()
        file_name = os.path.join(cwd,self.keyword)
        if not os.path.exists(self.keyword):
            os.mkdir(file_name)
        index = 0
        for url in urls:
            json_data = requests.get(url,headers = self.headers).json()
            json_data = json_data.get('data')
            for i in json_data:
                if i:
                    image_url = i.get('thumbURL')
                    index += 1
                    with open(file_name+'\\{}.jpg'.format(index),'wb') as f:
                        f.write(requests.get(image_url, headers = self.headers_image).content)
                        print('下载: ' + image_url)
    def __call__(self, *args, **kwargs):
        # 构造参数
        params = self.get_param()
        # 构造url数组
        urls = self.get_urls(params)
        # 请求
        self.get_image(urls)
 
if __name__ == '__main__':
    spider = Spider_baidu_image()
    # 关键字
    spider.keyword = '可爱的猫'
    # 页数,每页30张图
    spider.paginator = 100
    # 开始执行
    spider()

四、猫猫作品展

给大家看看我画的几幅,大家可以大胆发挥想象力,考验一下人工智能~


五、Unity制作讲解

Demo
1、界面素材

首先,在网上找一些素材图,

UnitySprite (2D and UI)
2、UGUI制作界面
UGUIUIImageTextOutlineUIRawImage
3、分辨率适配
UIAnchortop - stretchUIAnchor
4、如何检测鼠标事件
Event TriggerUIEvent TriggerAdd New EventTypeDragSketchPadOnDragSketchPadOnDrag
// 拖拽事件响应函数
public void OnDrag(BaseEventData baseData)
{
	PointerEventData data = (PointerEventData)baseData;
	// 鼠标当前的坐标
	Vector2 pos = data.position;
	// 拖拽的变化向量
	Vector2 delta = data.delta;
	// ...
}
【游戏开发创新】Unity+人工智能,让小朋友的画成真,六一儿童节一起来画猫猫吧(Unity | 人工智能 | 绘图 | 爬虫 | 猫妖)
positiondelta
5、世界坐标转局部坐标
OnDragpositionTransformInverseTransformPointTransform
var area = data.pointerDrag.GetComponent<RectTransform>();
// 起始点局部坐标
var p0 = area.InverseTransformPoint(data.position - data.delta);
// 终止点局部坐标
var p1 = area.InverseTransformPoint(data.position);
InverseTransformPointTransformPoint
6、画线原理
RenderTexture.activeRenderTexture.activeRenderTexture
// 备份
var prevRT = RenderTexture.active;
// 把画图的的RenderTexture对象_sourceTexture赋值给active
RenderTexture.active = _sourceTexture;
// 执行绘图,所有的绘图会渲染到_sourceTexture对象上
// ...
// 还原
RenderTexture.active = prevRT;
GraphicsDrawMeshNowDrawMeshNowMeshMeshMesh
Mesh _lineMesh = new Mesh();
_lineMesh.MarkDynamic();
_lineMesh.vertices = new Vector3[2];
_lineMesh.SetIndices(new[] { 0, 1 }, MeshTopology.Lines, 0);
Mesh
List<Vector3> _vertexList = new List<Vector3>(4);
_vertexList.Clear();
_vertexList.Add(p0);
_vertexList.Add(p1);
_lineMesh.SetVertices(_vertexList);
MeshMesh
Material _lineMaterial = new Material(_drawShader);
// 黑色
_lineMaterial.color = Color.black;
Graphics.DrawMeshNow
_lineMaterial.SetPass(0);
Graphics.DrawMeshNow(_lineMesh, Matrix4x4.identity);
Mesh_sourceTexture
7、橡皮擦原理
ShiftMesh
SetIndicesMeshshader
Mesh _eraserMesh = new Mesh();
_eraserMesh.MarkDynamic();
_eraserMesh.vertices = new Vector3[4];
_eraserMesh.SetIndices(new[] { 0, 1, 2, 1, 3, 2 }, MeshTopology.Triangles, 0);

橡皮擦的材质球颜色为白色,

Material _eraserMaterial = new Material(_drawShader);
// 白色
_eraserMaterial.color = Color.white;
4
// 半边长
const float d = 0.05f;

_vertexList.Clear();
_vertexList.Add(p0 + new Vector3(-d, -d, 0));
_vertexList.Add(p0 + new Vector3(+d, -d, 0));
_vertexList.Add(p0 + new Vector3(-d, +d, 0));
_vertexList.Add(p0 + new Vector3(+d, +d, 0));
_eraserMesh.SetVertices(_vertexList);

检测是否橡皮擦的逻辑:

public void OnDrag(BaseEventData baseData)
{
    var data = (PointerEventData)baseData;
    // ...
	bool eraser = (data.button == PointerEventData.InputButton.Right);
	eraser |= Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift);
	// ...
}
8、重置图片
CGraphicsBlit
if (Input.GetKeyDown(KeyCode.C))
{
    Graphics.Blit(_defaultTexture, _sourceTexture);
    Graphics.Blit(_defaultTexture, _resultTexture);
}
9、训练模型下载
StreamingAssets
var filePath = Path.Combine(Application.streamingAssetsPath, "edges2cats_AtoB.pict");
Dictionary<string, Pix2Pix.Tensor> _weightTable = Pix2Pix.WeightReader.ReadFromFile(filePath);
Pix2Pix.Generator _generator = new Pix2Pix.Generator(_weightTable);
_generator
10、通过生成器得到图像
StartGetResult
// Generator.cs 生成器

public void Start(Texture input)
{
	Image.ConvertToTensor(input, _temp1);
	_progress = 0;
}

public void GetResult(RenderTexture output)
{
	Image.ConvertFromTensor(_temp1, output);
}
ImageGpuBackendpix2pix

六、结束语

UnityUnity

推荐阅读:
《[Unity 3D] 权游红袍女在火中看到了什么,我看到了…(粒子系统 | 火焰特效 | ParticleSystem | 手把手制作)》
《[Unity 2D] 重温红白机经典FC游戏,顺便教你快速搭建2D游戏关卡(Tilemap | 场景 | 地图)》
《520程序员的浪漫,给CSDN近两万的粉丝比心心(python爬虫 | Unity循环复用列表 | 头像加载与缓存)》
《ShaderGraph使用教程与各种特效案例:Unity2020(持续更新)》
《Unity使用ShaderGraph配合粒子系统,制作子弹拖尾特效(Fate/stay night金闪闪的大招效果)》
《使用Unity ShaderGraph实现在模型上涂鸦的效果,那么,纹个手吧》
《学Unity的猫——第十五章:Unity粒子系统ParticleSystem,下雪啦下雪啦》
《Unity实现水果忍者切水果的刀痕效果教程(两种实现方式:TrailRenderer、LineRenderer)》
《Unity流体模拟,支持粒子系统,支持流体碰撞交互(Obi Fluid插件使用教程)》
《玩转贝塞尔曲线,教你在Unity中画Bezier贝塞尔曲线(二阶、三阶),手把手教你推导公式》
《Unity UGUI制作雷达图/天赋图/属性图/能力图,因为太怕痛就全点了防御力》
《使用Unity ShaderGraph实现刮刮乐的刮卡剔除效果,感受一下刮中500万的时刻》
《Unity后处理(图像优化特效技术),实现影视级别的镜头效果,辅助标签:PostProcessing》

七、附录,《睡吧孩子》画画过程记录

1、线稿过程
2、成稿