Catlike系列教程』第二篇来了今天周六,早上~(上午11点)醒来去超市买了一周的零食回来以后就玩了一整天游戏非常有负罪感。现在晚上九点天还亮着感觉像下午7点左右的样子好像还不是很晚。。。所以就写一点东西吧。这一篇是「Building a Graph」挑战一下试试吧。

PART 1 概述

那么大概文章看下来我们预计要做以下事情。

  • 使用一定数量的小方块表达函数图像
  • 做一个 Shader 给图像上色使其更好看
  • 给图像传入时间参数使其动起来

PART 2 画函数图像

首先我们确认一下要支持的功能细节,根据默认摄像机的位置和视野我们就暂定需要画出函数[-1. 1]之间的图像,同时可以通过一个条拖动来修改函数的解析度,假设解析度可以是[10,100],那么我们需要在x=[-1, 1]之间生成[10,100]个方块。同时动态的调整方块的大小使其完美衔接。代码如下:

  1. public class GraphController : MonoBehaviour
  2. {
  3. [Range(10, 100), SerializeField] private int _resolution;
  4. [SerializeField] private GameObject _cube;
  5. // Use this for initialization
  6. private void Start ()
  7. {
  8. _cube.SetActive(false);
  9. var step = 2f / _resolution;
  10. var startPosX = -1f;
  11. var scale = Vector3.one * step;
  12. for (int i = 0; i < _resolution; i++)
  13. {
  14. var pos = new Vector3(startPosX + i * step, Calc(startPosX + i * step), 0);
  15. var point = Instantiate(_cube, transform);
  16. point.transform.localPosition = pos;
  17. point.transform.localScale = scale;
  18. point.SetActive(true);
  19. }
  20. }
  21. private float Calc(float x)
  22. {
  23. return Mathf.Pow(x, 2);
  24. }
  25. }

根据Calc(float)可以看出我们画出来曲线是如下函数的图像。 $y=x^2$ $f(x)=ax+b$

PART 3 给曲线上色

首先我们创建一个 Surface Shader,通过Assets / Create / Standard Surface Shader创建一个新的 Shader。修改代码如下:

  1. Shader "Custom/ColoredPoint" {
  2. Properties {
  3. _Glossiness ("Smoothness", Range(0,1)) = 0.5
  4. _Metallic ("Metallic", Range(0,1)) = 0.0
  5. }
  6. SubShader {
  7. Tags { "RenderType"="Opaque" }
  8. LOD 200
  9. CGPROGRAM
  10. // Physically based Standard lighting model, and enable shadows on all light types
  11. #pragma surface surf Standard fullforwardshadows
  12. // Use shader model 3.0 target, to get nicer looking lighting
  13. #pragma target 3.0
  14. // 此处将世界坐标传入IN
  15. struct Input {
  16. float3 worldPos;
  17. };
  18. half _Glossiness;
  19. half _Metallic;
  20. // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
  21. // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
  22. // #pragma instancing_options assumeuniformscaling
  23. UNITY_INSTANCING_BUFFER_START(Props)
  24. // put more per-instance properties here
  25. UNITY_INSTANCING_BUFFER_END(Props)
  26. void surf (Input IN, inout SurfaceOutputStandard o) {
  27. // 在这里根据世界坐标将方块染上不同的颜色
  28. o.Albedo.rgb = IN.worldPos.xyz * 0.5 + 0.5;
  29. // Metallic and smoothness come from slider variables
  30. o.Metallic = _Metallic;
  31. o.Smoothness = _Glossiness;
  32. o.Alpha = 1;
  33. }
  34. ENDCG
  35. }
  36. FallBack "Diffuse"
  37. }

运行效果如下~

PART 4 让曲线动起来

首先曲线之所以会动当然是因为我们将时间作为参数同时传进去导致的~所以我们首先稍微改一下Calc(float)这个函数让时间参数也生效~这里用到Mathf.PI是为了图像从[-1, 1]之间完整的显示一个周期,大家可以随便改改试试。

  1. private float Calc(float x)
  2. {
  3. return Mathf.Sin(Mathf.PI * (x + Time.time));
  4. }

然后直接运行肯定是不行的,我们需要把计算y和设置每个小方块的位置的代码移到Update()中去。最终代码如下:

  1. public class GraphController : MonoBehaviour
  2. {
  3. [Range(10, 100), SerializeField] private int _resolution;
  4. [SerializeField] private GameObject _cube;
  5. private List<Transform> _points;
  6. private float _step;
  7. private float _startX;
  8. // Use this for initialization
  9. private void Start ()
  10. {
  11. _cube.SetActive(false);
  12. _points = new List<Transform>();
  13. _step = 2f / _resolution;
  14. _startX = -1f;
  15. var scale = Vector3.one * _step;
  16. for (int i = 0; i < _resolution; i++)
  17. {
  18. var point = Instantiate(_cube, transform);
  19. _points.Add(point.transform);
  20. point.transform.localScale = scale;
  21. point.SetActive(true);
  22. }
  23. }
  24. private void Update()
  25. {
  26. for (int i = 0; i < _resolution; i++)
  27. {
  28. var x = _startX + i * _step;
  29. var pos = new Vector3(x, Calc(x), 0);
  30. var point = _points[i];
  31. point.transform.localPosition = pos;
  32. }
  33. }
  34. private float Calc(float x)
  35. {
  36. return Mathf.Sin(Mathf.PI * (x + Time.time));
  37. }
  38. }

运行效果如图:

PART 5 总结

这一篇也很简单啊一边做一边写再随便划划水很快就完成了~最后大家可以下载「Github Repo」查看运行结果和全部代码~或者到「原文地址」查看更加详细的过程和思路。


原文链接:https://snatix.com/2018/06/09/020-building-a-grap/

本文由 sNatic 发布于『大喵的新窝』 转载请保留本申明

Catlike学习笔记(1.2)-使用Unity画函数图像的更多相关文章

  1. Catlike学习笔记(1.3)-使用Unity画更复杂的3D函数图像

    第三篇来了-今天去参加了 Unite 2018 Berlin,感觉就是....非常困...回来以后稍微睡了下清醒了觉得是时候认真学习下了,不过讲的很多东西都是还没有发布或者只有 Preview 的版本 ...

  2. Catlike学习笔记(1.4)-使用Unity构建分形

    又两个星期没写文章了,主要是沉迷 Screeps 这个游戏,真的是太好玩了导致我这两个礼拜 Github 小绿点几乎天天刷.其实想开一个新坑大概把自己写 AI 的心路历程记录下,不过觉得因为要消耗太多 ...

  3. Catlike学习笔记(1.1)-使用Unity实现一个钟表

    最近发现『Catlike系列教程』觉得内容真的很赞,感觉有很多地方涉及到了我的知识盲点,如果真的可以照着做下来一遍的话应该收获颇丰.因为教程很长所以逐字翻译不太可能了(主要是翻译的太差).基本上就是把 ...

  4. MYSQL学习笔记三:日期和时间函数

    MYSQL学习笔记三:日期和时间函数 1. 获取当前日期的函数和获取当前时间的函数 /*获取当前日期的函数和获取当前时间的函数.将日期以'YYYY-MM-DD'或者'YYYYMMDD'格式返回 */ ...

  5. JavaScript学习笔记(十)——高阶函数之map,reduce,filter,sort

    在学习廖雪峰前辈的JavaScript教程中,遇到了一些需要注意的点,因此作为学习笔记列出来,提醒自己注意! 如果大家有需要,欢迎访问前辈的博客https://www.liaoxuefeng.com/ ...

  6. JavaScript学习笔记(十二)——箭头函数(Arrow Function)

    在学习廖雪峰前辈的JavaScript教程中,遇到了一些需要注意的点,因此作为学习笔记列出来,提醒自己注意! 如果大家有需要,欢迎访问前辈的博客https://www.liaoxuefeng.com/ ...

  7. C++ Primer学习笔记(三) C++中函数是一种类型!!!

    C++中函数是一种类型!C++中函数是一种类型!C++中函数是一种类型! 函数名就是变量!函数名就是变量!函数名就是变量! (---20160618最新消息,函数名不是变量名...囧) (---201 ...

  8. 【opencv学习笔记五】一个简单程序:图像读取与显示

    今天我们来学习一个最简单的程序,即从文件读取图像并且创建窗口显示该图像. 目录 [imread]图像读取 [namedWindow]创建window窗口 [imshow]图像显示 [imwrite]图 ...

  9. hive学习笔记之十:用户自定义聚合函数(UDAF)

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 本文是<hive学习笔记>的第十 ...

随机推荐

  1. 【转】基于easyui开发Web版Activiti流程定制器详解(一)——目录结构

    题外话(可略过): 前一段时间(要是没记错的话应该是3个月以前)发布了一个更新版本,很多人说没有文档看着比较困难,所以打算拿点时间出来详细给大家讲解一下,由于本人平时要工作还要陪老婆和孩子而且还经营着 ...

  2. Python中的赋值和拷贝

    赋值 在python中,赋值就是建立一个对象的引用,而不是将对象存储为另一个副本.比如: >>> a=[1,2,3] >>> b=a >>> c= ...

  3. 基于jquery分页插件

    今天终于完成了基于jquery的分页插件的代码编写,也通过了功能测试,实现了分页功能:由于刚开始写jquery的插件,所以梳理逻辑的时间也很长,整个过程整整一周时间,今天终于搞完了,先将整个分页插件的 ...

  4. 第一章 进入java的世界

    一.你要做的事情: 1.  编写源代码:xxx.java 2. 编译器编译:检测代码错误 3. 输出:编译器输出xxx.class 4. 运行:java虚拟机运行xxx.class

  5. Java基础加强之并发(一)基本概念介绍

    基本概念介绍 进程:它是内存中的一段独立的空间,可以负责当前应用程序的运行.当前这个进程负责调度当前程序中的所有运行细节. 线程:它是位于进程中,负责当前进程中的某个具备独立运行资格的空间. 进程是负 ...

  6. [luogu1080] 国王游戏

    题面 ​ 这是一个比较经典(害人不浅)的题目啊, 很早就听说过这个题目的大名, 今日得见, 果然非凡题所可以比拟的啊, 行了, 瞎扯就先扯到这里, 题目大意应该是很好解释的, 我就不解释了, 要使得最 ...

  7. 节点和Topic通信

    1.简介 对于实时性. 周期性的消息, 使用topic来传输是最佳的选择. topic是一种点对点的单向通信方式, 这里的“点”指的是node, 也就是说node之间可以通过topic方式来传递信息. ...

  8. 澄清以及半AOer的日常

    我是不是应该澄清什么事情-- 首先--我这个傻狗退役了--指的是退本赛季而不是本奥赛-- 其次--我喜欢天文是真的喜欢--但是至于为什么又滚回来OI了--大概是因为本校只对所谓"五大学科奥赛 ...

  9. BUAA_OO第一单元总结性博客作业——表达式求导

    一.程序设计思路 在我的三次作业中都采用了类的分层结构,采用逐项匹配,分层求导的思路. (一). 第一次作业中构建了Polynimial(多项式)类,在类的构造器中就完成了对非法空格的判断并对合法表达 ...

  10. Scala中的类学习

    Scala中的类学习 从java了解类的情况下,了解Scala的类并不难.Scala类中的字段自动带getter和setter方法,用@BeanProperty注解生成javaBean对象的getXX ...