今日学习: Unity画符

在实体中,我们可以在纸上进行涂鸦;而在一些软件中,我们可以使用手指进行涂鸦,或者用手绘板、鼠标进行画图;游戏《阴阳师》中也有画符。我今天学习的内容,就是在unity中进行画符(实际上就是模仿阴阳师的画符)。

想要在unity中进行画符,首先要知道,怎么才能画出来。鼠标(或者手指)在屏幕上移动,然后走过的地方,就留下了痕迹,这就成了画符。提取关键部分:鼠标移动,走过的地方,痕迹。再简化些,就是鼠标经过的位置,以及屏幕上画图。

鼠标移动

我们先来看第一个部分:鼠标经过的位置。我们需要知道鼠标经过的位置,才能画出来图像。

有没有一种方法,将鼠标经过的位置记录下来呢?当然,我学到了一种方法:将鼠标经过的位置都记录下来,存在一个List中,当鼠标移动时,对链表的内容实时更新,这样,鼠标经过的位置就全部被记录下来了。

//创建一个List链表
private List<Vector3> allPoints;private void Start()
{allPoints = allPoints = new List<Vector3>();
}private void Update()
{if(Input.GetMouseButton(0)){//创建一个Vector3类型的临时变量,用于存放视图坐标。Vector3 tmpView = Camera.main.ScreenToViewportPoint(Input.mousePosition);allPoints.Add(tmpView);}
}

复习一下unity中的几种坐标系:

  • 世界坐标系:(0,0,0)为坐标原点;
  • 局部坐标系:以物体本身的位置为原点;
  • 相机坐标系:以相机位置为原点;
  • 屏幕坐标系:以屏幕左下角为原点(0,0),右上角是屏幕的宽和高。例如,如果屏幕为1280*720,那么,屏幕右上角就是(1280,720);
  • 视口坐标系:左下角为(0,0)点,右上角为(1,1)点;
  • 绘制UI的坐标系:与屏幕坐标系不同,是以左上角为原点,右下角是屏幕的宽高。

当然还有其他坐标系,例如我刚刚查到的惯性坐标系,嵌套坐标系等,这些坐标系在今天的复习回顾中用不到,暂且搁置。

着重介绍一下视口坐标系。跟前几天绘制小地图一样,绘制画符也会用到比例,视口坐标系有一个好处,可以当比例使用。当一个物体位于屏幕正中心时,它的视口坐标系下的坐标就是就(0.5, 0.5),当把这个物体映射到一张300*270的图片(图片左下角为原点)上时,它在图片上的坐标就是(150,135)。
Camera.main.ScreenToViewportPoint()这个方法就是将屏幕坐标系转换为视口坐标系。

记录鼠标位置部分已完成,接下来就是在屏幕上画图。

屏幕上画图

这部分内容在之前的学习中没有接触过,用到了一个对我来说是一个全新知识点的东西:GL。

GL在之前我是完全不了解的,而且我对OpenGL也不了解。因此关于GL的代码,我没有理解透彻,只能看着代码然后将自己的理解写成注释。跟着课程学的时候,这段的代码也是跟着课程一样,直接从API中复制粘贴过来的。

具体的东西,直接在代码里面写吧,这样也方便以后查看。尽管这不符合我心中对于代码注释的规范。
这部分代码改动过,具体原本的代码,请查看API:GL

    //定义一个材质,这个材质是画出的线的材质。static Material lineMaterial;/// <summary>/// 创建线的材质。/// </summary>static void CreateLineMaterial(){if (!lineMaterial){// Unity has a built-in shader that is useful for drawing// simple colored things.Shader shader = Shader.Find("Hidden/Internal-Colored");lineMaterial = new Material(shader);#region 以下代码我看不懂lineMaterial.hideFlags = HideFlags.HideAndDontSave;// Turn on alpha blendinglineMaterial.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);lineMaterial.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);// Turn backface culling offlineMaterial.SetInt("_Cull", (int)UnityEngine.Rendering.CullMode.Off);// Turn off depth writeslineMaterial.SetInt("_ZWrite", 0);#endregion}}// Will be called after all regular rendering is donepublic void OnRenderObject(){CreateLineMaterial();// Apply the line materiallineMaterial.SetPass(0);//变成正交投影GL.LoadOrtho();GL.Begin(GL.LINES);//换颜色GL.Color(Color.red);for (int i = 1; i < allPoints.Count; i++){//创建两个临时变量,用于存放前一个点的位置和当下这一个点的位置。Vector3 tmpFront = allPoints[i - 1];Vector3 tmpBack = allPoints[i];//将这两个点提交上去。这关于GL.Vertex()这个方法,我还没有理解。GL.Vertex3(tmpFront.x, tmpFront.y, tmpFront.z);GL.Vertex3(tmpBack.x, tmpBack.y, tmpBack.z);}GL.End();}

这段代码,我基本属于不理解的状态。Unity的GL这一块儿同样暂且搁置。

将画出来的画符映射到一个画板上:

    public void GenerateTexture(){paintTexture = new Texture2D(300, 400);for (int i = 1; i < allPoints.Count; i++){Vector3 tmpFront = allPoints[i - 1];Vector3 tmpBack = allPoints[i];//将图片的宽和高乘上一个比例,得到相对于图片(0,0)坐标的位置。//上一个鼠标位置点的X,Y的值float paintFrontX = paintTexture.width * tmpFront.x;float paintFrontY = paintTexture.height * tmpFront.y;//当前鼠标位置点的X,Y值float paintBackX = paintTexture.width * tmpBack.x;float paintBackY = paintTexture.height * tmpBack.y;//用于插值运算int tmpCount = 50;for (int j = 0; j < tmpCount; j++){//插值:a*t+1-tb//参数:需要渐进变换的参数,峰顶值,变化速率 int tmpX = (int)Mathf.Lerp(paintFrontX, paintBackX, j / (float)tmpCount);//像素点需要一个整型参数int tmpY = (int)Mathf.Lerp(paintFrontY, paintBackY, j / (float)tmpCount);//设置图片像素点的颜色。paintTexture.SetPixel(tmpX, tmpY, Color.red);}}//paintTexture.SetPixel(paintX, paintY, Color.red);paintTexture.Apply();//将物体材质更换为当前代码创建的这个纹理。transform.GetComponent<Renderer>().material.mainTexture = paintTexture;}

接收画符的纹理创建好之后,在Update里面引用它。当我们松开鼠标的时候,屏幕上的画符就消失,然后画符呈现在画板上。

private void Update(){if (Input.GetMouseButton(0)){//得到点Vector3 tmpView = Camera.main.ScreenToViewportPoint(Input.mousePosition);allPoints.Add(tmpView);}if (Input.GetMouseButtonUp(0)){GenerateTexture();allPoints.Clear();}}

完整代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class PointerUI : MonoBehaviour
{List<Vector3> allPoints;Texture2D paintTexture;private void Start(){allPoints = new List<Vector3>();}private void Update(){if (Input.GetMouseButton(0)){//得到点Vector3 tmpView = Camera.main.ScreenToViewportPoint(Input.mousePosition);allPoints.Add(tmpView);}if (Input.GetMouseButtonUp(0)){GenerateTexture();allPoints.Clear();}}public void GenerateTexture(){paintTexture = new Texture2D(300, 400);for (int i = 1; i < allPoints.Count; i++){Vector3 tmpFront = allPoints[i - 1];Vector3 tmpBack = allPoints[i];//将图片的宽和高乘上一个比例,得到相对于图片(0,0)坐标的位置。//上一个鼠标位置点的X,Y的值float paintFrontX = paintTexture.width * tmpFront.x;float paintFrontY = paintTexture.height * tmpFront.y;//当前鼠标位置点的X,Y值float paintBackX = paintTexture.width * tmpBack.x;float paintBackY = paintTexture.height * tmpBack.y;//用于插值运算int tmpCount = 50;for (int j = 0; j < tmpCount; j++){//插值:a*t+1-tb//参数:需要渐进变换的参数,峰顶值,变化速率 int tmpX = (int)Mathf.Lerp(paintFrontX, paintBackX, j / (float)tmpCount);//像素点需要一个整型参数int tmpY = (int)Mathf.Lerp(paintFrontY, paintBackY, j / (float)tmpCount);//设置图片像素点的颜色。paintTexture.SetPixel(tmpX, tmpY, Color.red);}}//paintTexture.SetPixel(paintX, paintY, Color.red);paintTexture.Apply();//将物体材质更换为当前代码创建的这个纹理。transform.GetComponent<Renderer>().material.mainTexture = paintTexture;}//定义一个材质,这个材质是画出的线的材质。static Material lineMaterial;/// <summary>/// 创建线的材质。/// </summary>static void CreateLineMaterial(){if (!lineMaterial){// Unity has a built-in shader that is useful for drawing// simple colored things.Shader shader = Shader.Find("Hidden/Internal-Colored");lineMaterial = new Material(shader);#region 以下代码我看不懂lineMaterial.hideFlags = HideFlags.HideAndDontSave;// Turn on alpha blendinglineMaterial.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);lineMaterial.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);// Turn backface culling offlineMaterial.SetInt("_Cull", (int)UnityEngine.Rendering.CullMode.Off);// Turn off depth writeslineMaterial.SetInt("_ZWrite", 0);#endregion}}// Will be called after all regular rendering is donepublic void OnRenderObject(){CreateLineMaterial();// Apply the line materiallineMaterial.SetPass(0);//变成正交投影GL.LoadOrtho();GL.Begin(GL.LINES);//换颜色GL.Color(Color.red);for (int i = 1; i < allPoints.Count; i++){//创建两个临时变量,用于存放前一个点的位置和当下这一个点的位置。Vector3 tmpFront = allPoints[i - 1];Vector3 tmpBack = allPoints[i];//将这两个点提交上去。这关于GL.Vertex()这个方法,我还没有理解。GL.Vertex3(tmpFront.x, tmpFront.y, tmpFront.z);GL.Vertex3(tmpBack.x, tmpBack.y, tmpBack.z);}GL.End();}
}

在Unity场景中创建一个Quad物体,将脚本挂载到它身上。然后运行。下面是效果:


这部分内容,学得不够透彻。理解得也不够深入。
关于unity中GL这部分,暂时不打算学。过段时间,可能是一两年,两三年,再去学习,学习GL,OpenGL,Shader,等到那时候再去整理思路。
目前我能保持每天花最多一小时学习Unity,这已经是最好的状态了,因为我有比这更重要的事情去做,而Unity被我当做了业余时间一件能放松的事情。毕竟经常看手机刷短视频也不好,浪费时间不说,更不能提升自己。这就作为一个爱好发展下去吧。希望这个爱好能坚持一个月。先一个月吧,我也不是个能有长久爱好的人。
至于昨天和前天为什么没有写日记,请你——未来的我——听我解(jie)释(kou)。
是这样的,前天学的东西,GL这块没跟上,又不想返回去再看一遍,网又差,API加载不出来,我就放弃了,所以前天没写。昨天为啥没写呢,因为昨天我又把前天学的课返了一遍,又学了昨天应该学的新课。学完之后,已经十一点多快十二点了,我就去睡觉了。
其实吧,就是懒,拖延症犯了。
请你放心,我……我不一定会改啊。太难了。比跑步还难。

20220326-代码日记-Unity画符相关推荐

  1. Unity画线(Vectrosity5.6.1插件)

    一个好的插件,会让你事半功倍,在Unity这个如此成熟的生态圈里,几乎常用的功能,都会有对应的插件帮助速简化开发工作,以最低的时间成本达到目的.接下来要介绍的是Unity的一款功能强大的画线插件:Ve ...

  2. 基于UGUI的Unity画线工具

    基于UGUI的Unity画线工具 最近项目里需要做一个画线的小游戏,LineRenderer不是很好用,自己撸了一个小工具,效果如下 下面上代码 using System.Collections.Ge ...

  3. 代码 控制unity 暂停 编辑器_Unity3D 报错解决方案及常用功能收集

    1.在Dictionary迭代器进行修改: var _key = index2factionDic.Keys.GetEnumerator(); stringitem; while(_key.MoveN ...

  4. html简单边框制作--特效文字制作及代码,HTML音画介绍之一--基本原理和边框的制作...

    谨以此系列篇献给需要学习HTML代码音画的紫雨朋友们. 晕,写这篇教程,熬了几个深夜.欣慰的是,紫雨的教程 是自己用心写出来的,绝不雷同.这是紫雨对朋友的负 责. HTML音画最大的好处是简便易学,效 ...

  5. 用python画苹果的logo_简单几步,100行代码用Python画一个蝙蝠侠的logo

    转自:菜鸟学Python 简单几步,100行代码用Python画一个蝙蝠侠的logo-1.jpg (35.33 KB, 下载次数: 0) 2020-7-30 12:04 上传 蝙蝠侠作为DC漫画的核心 ...

  6. 图画日记怎么画_图画日记怎么画_二年级下册绘画日记图片

    图画日记怎么画都好,重要是坚持,看你情况不错,相信你坚持也可以的,日记也是个有温度的内容,多记录美好,不急不躁,清静无为,即使他人不理解,不赞同,也可以,好好坚持你的日记,会慢慢有你要的,加油! 练习 ...

  7. 通过unity画弧线

    using UnityEngine; using System.Collections;public class Test : MonoBehaviour {public int a;//a>0 ...

  8. 代码专栏——如何画黑体辐射能量密度随频率和温度的三维变化图

    导语: 上篇文章我们利用matlab画出了黑体辐射能量密度随频率变化的二维变化图,代码专栏--如何画黑体辐射能量密度随频率的变化图.这个图有一个缺陷,能量密度仅仅随着变量频率改变,而另外一个变量黑体辐 ...

  9. python画画100行代码_简单几步,100行代码用Python画一个蝙蝠侠的logo

    原标题:简单几步,100行代码用Python画一个蝙蝠侠的logo 转自:菜鸟学Python 蝙蝠侠作为DC漫画的核心人物之一,一直都受到广大粉丝的喜爱,而笔者作为DC的铁杆粉丝,自然也是老爷(粉丝对 ...

  10. mysql 5.5.48源码安装_centos5.5+apache2.2.15+mysql5.1.48+php5.2.13 编译安装 --by 画符抓鬼撰聊斋.doc...

    centos5.5+apache2.2.15+mysql5.1.48+php5.2.13 编译安装 --by 画符抓鬼撰聊斋.doc 还剩 5页未读, 继续阅读 下载文档到电脑,马上远离加班熬夜! 亲 ...

最新文章

  1. sqlserver清除日志
  2. groovy定义变量获取当前时间_IDEA不愧为神器,结合Groovy脚本,简直无敌!
  3. java aes密钥生成_如何在Java(Android)中生成与.Net中相同的AES密钥?
  4. Scala元组数据的遍历
  5. animate中使用HTML5,animate.css怎么使用?
  6. ByteBuffer常用方法详解
  7. FPGA设计中遇到的奇葩问题之“芯片也要看出身”
  8. pcl使用通道滤波器来滤波
  9. Python基础(while循环/赋值运算符)
  10. sql server 2012中red gate的sql source control消失
  11. python中包引入遇到的问题
  12. 编译Libgdiplus遇到的问题
  13. 测试计划、用例、测试报告、缺陷报告总结
  14. 软考中级软件设计师备考详细资料
  15. ApacheCN 活动汇总 2019.7.19
  16. java两个日期相减_java将两个日期相减得到天数
  17. 51单片机之定时器/计数器0中断程序
  18. Xshell复制粘贴快捷键设置
  19. CSS盒模型的应用--个人名片的制作
  20. 【技术人快报】摩拜单车多地区现Bug+iCloud完成中国本土化落地

热门文章

  1. 5分钟搭建3D场景 3D可视化搭建平台WebGLHTML5
  2. 辣妈直升机视频号值得学习吗
  3. 微信小程序中 scroll-view滚动条始终在最底部
  4. 微信平台开发获取微信用户的OPENID
  5. FA_MASS_ADDITIONS Interface Table 资产成批增加
  6. 我过去的那些编程思想
  7. 《Multi-Stream Gated and Pyramidal Temporal Convolutional Neural Networksfor Audio-Visual Speech Se》
  8. ecshop 模版写php,ecshop 模板直接使用运算符
  9. 7-7 浪漫的表白 (10 分) 计算生日差据天数
  10. 【ParaView教程】2.13 保存截图和保存动画