Unity可视化数据:创建图表
本文由Aoi翻译,转载请注明出处。文章来自于catlikecoding,原文作者介绍了Unity制作图表、可视化数据的方法。更多的名词解释内容,请点击末尾的“原文链接”查看。
介绍
这个教程里,我们在Unity 4里用C#脚本来展示日趋复杂的图表。你将学会:
- 创建图表,从简单到复杂
- 控制粒子系统
- 写各种数学函数
- 在play模式下改变行为
- 使用Unity事件函数Start 和Update
- 写循环,包括单循环和嵌套循环
- 使用数组、枚举和代表
假设你已经对Unity编辑器有了初步的了解,并且知道创建C#脚本的基本知识。如果你完成了简易时钟制作教程,那么你就可以开始这一章了。
注意我会经常省略已经讲解过的代码块。新的代码内容会继续讲解清楚。
准备
打开一个新项目, 我们将在一个单位的立方体内建立表格,放置于(0, 0, 0)和(1, 1, 1)之间。设置一下编辑器以得到更好的视觉效果。4 Split是一个方便预定义的试图布局,所以选择它。从Window / Layout / 4 Spit选择,或者在屏幕右上方的下拉菜单里。把所有的视图模式都设置为Textured,旋转透视图,这样三个轴就都指向你了。
通过GameObject / Create Other / Cube创建一个新的方块,设置位置为(0.5, 0.5, 0.5)。这为我们校准视图提供参考。现在缩放和平移视图使其聚焦于单位方块。
最后,选择Main Camera,通过GameObject / Align With View使其匹配立透视图。如果那不管用,通过单机确认正确的视图是否激活,然后再试试。
场景视图以及相机聚焦于方块
这个方块不再需要了,所以移除它。然后通过GameObject / Create Other / Particle System创建粒子系统并重置其变换。现在它能产生随机例子了,但是不是我们想要的,所以我们停用除了渲染器之外的一切东西。
取消选择Looping, Play On Awake, Emission,以及Shape.这保留了惰性粒子系统,我们可以用它实现图形数据可视化。
惰性粒子系统
创建第一个图表
创建一个Y值依赖于X值的简单图线图。我们将用粒子的位置可视化这个。
重命名粒子系统对象为Graph 1,创建C#脚本,命名为Grapher1,作为最小的GameObject类,然后将它作为组件添加到对象。
1
2
3
|
using UnityEngine; public class Grapher1 : MonoBehaviour {} |
有着空 Grapher1组件的Graph 1
首先我们的创建一些粒子作为图表的点。使用特殊的Start方法创建,这是一个在更新开始之前被调用一次的Unity事件方法。
我们应该使用多少粒子呢?粒子越多,图表的样本分辨率就越高。我们设置为默认分辨率10。
1
2
3
4
5
6
7
8
|
using UnityEngine; public class Grapher1 : MonoBehaviour { public int resolution = 10; private ParticleSystem.Particle[] points; void Start () { points = new ParticleSystem.Particle[resolution]; } } |
Grapher1配置分辨率
现在我们可以按照自己的意愿设置分辨率了。技术上至少是0,分辨率太高的话又会减慢运行。
我们可以确保初始化数组时变量在一定范围内。如果分辨率超出了范围,我们就将其重设为最小值,并且记录警告信息。让我们用一个10-100的合理范围。
1
2
3
4
5
6
7
|
void Start () { if (resolution < 10 || resolution > 100) { Debug.LogWarning( "Grapher resolution out of bounds, resetting to minimum." , this ); resolution = 10; } points = new ParticleSystem.Particle[resolution]; } |
现在该把点沿着X轴放置。第一个点应该放在0,最后一个放在1。其他的点应该在这两者之间。所以距离,或者说X增量,两点之间是1(分辨率-1)。
除了位置,我们来可以用颜色来提供相同的信息。让点的红色量等于其沿X轴的位置。
我们将使用一个for循环来遍历所有点,并设置位置和颜色,这是类型Vector3 和颜色的结构值。我们还需要设置粒子的大小,否则将不会显示。大小为0.1就可以。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
void Start () { if (resolution < 10 || resolution > 100) { Debug.LogWarning( "Grapher resolution out of bounds, resetting to minimum." , this ); resolution = 10; } points = new ParticleSystem.Particle[resolution]; float increment = 1f / (resolution - 1); for (int i = 0; i < resolution; i++) { float x = i * increment; points[i].position = new Vector3(x, 0f, 0f); points[i].color = new Color(x, 0f, 0f); points[i].size = 0.1f; } } |
到目前为止,还出不了效果。当播放的时候,什么都显示不出来。那是因为我们得把粒子添加到粒子系统。方便起见,每个组件都有一个粒子系统属性,我们可以用它来访问粒子系统(如果有的话)。我们需要做的就是调用SetParticles方法,提供粒子数组以及我们想要的粒子数量。由于我们想要使用所有的粒子,所以子要提供数组的长度就可以。我们需要给每一帧添加一个更新方法。
1
2
3
|
void Update () { particleSystem.SetParticles(points, points.Length); } |
就是这样,现在我们得到了一个沿着X轴由黑到红的点线。显示多少点取决于分辨率的值。
现在,只有在图表初始化的时候考虑分辨率。播放模式下更新值不起任何作用。现在来修改一下。
检测分辨率的一个简单方法是存储两次,然后经常检查这两个值是否仍然一样。如果在某些点不一样,我们就要重建图表。为此需要创建一个私有变量currentResolution 。
由于重建这些点适合初始化的时候是一样的,所以把代码移到名为CreatePoints的新的私有方法中。这样我们就能重新使用代码了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
using UnityEngine; public class Grapher1 : MonoBehaviour { public int resolution = 10; private int currentResolution; private ParticleSystem.Particle[] points; void Start () { CreatePoints(); } private void CreatePoints () { if (resolution < 10 || resolution > 100) { Debug.LogWarning( "Grapher resolution out of bounds, resetting to minimum." , this ); resolution = 10; } currentResolution = resolution; points = new ParticleSystem.Particle[resolution]; float increment = 1f / (resolution - 1); for (int i = 0; i < resolution; i++){ float x = i * increment; points[i].position = new Vector3(x, 0f, 0f); points[i].color = new Color(x, 0f, 0f); points[i].size = 0.1f; } } void Update () { if (currentResolution != resolution) { CreatePoints(); } particleSystem.SetParticles(points, points.Length); } } |
现在只要改变分辨率的值就能重建图表了。然而,你会注意到每当分辨率超出范围,甚至是输入的时候,控制台都会弹出警告。我们可以使用Range属性来告诉Unity编辑器使用滑块来代替数字框。
由于我们只关注有效地输入编辑,并且不会通过代码来改变分辨率,所以现在可以移除分辨率检查了,当然,也许你会决定保留它。
1
2
|
[Range(10, 100)] public int resolution = 10; |
现在该设置点在Y轴的位置了。简单一点开始吧,把Y等于X。换句话说,我们在可视化数学公式y = x,或者函数f(x) = x。为了做到这一点,我们需要循环所有的点,获取它们的位置,使用X值计算Y值,然后设置新位置。一旦我们使用for循环,就将执行每个更新。
1
2
3
4
5
6
7
8
9
10
11
|
void Update () { if (currentResolution != resolution) { CreatePoints(); } for (int i = 0; i < resolution; i++) { Vector3 p = points[i].position; p.y = p.x; points[i].position = p; } particleSystem.SetParticles(points, points.Length); } |
接下来把点的绿色分量设置的和Y位置一样。由于红加绿会得到黄,这将使得线从黑变黄。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
void Update () { if (currentResolution != resolution) { CreatePoints(); } for (int i = 0; i < resolution; i++) { Vector3 p = points[i].position; p.y = p.x; points[i].position = p; Color c = points[i].color; c.g = p.y; points[i].color = c; } particleSystem.SetParticles(points, points.Length); } |
或许你已经注意到了在播放状态下改变代码并回到Unity,你会看到NullReferenceException错误信息。这还是因为重新加载时Unity没有记录私有点变量。
要解决这个问题,除了检查分辨率,我们可以检查点是否为null。这将使我们在编写代码时始终保持在播放模式,非常方便。注意这个检查还可以消除对Start方法的需要,所以可以删除它了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
using UnityEngine; public class Grapher1 : MonoBehaviour { [Range(10, 100)] public int resolution = 10; private int currentResolution; private ParticleSystem.Particle[] points; private void CreatePoints () { currentResolution = resolution; points = new ParticleSystem.Particle[resolution]; float increment = 1f / (resolution - 1); for (int i = 0; i < resolution; i++){ float x = i * increment; points[i].position = new Vector3(x, 0f, 0f); points[i].color = new Color(x, 0f, 0f); points[i].size = 0.1f; } } void Update () { if (currentResolution != resolution || points == null ) { CreatePoints(); } for (int i = 0; i < resolution; i++) { Vector3 p = points[i].position; p.y = p.x; points[i].position = p; Color c = points[i].color; c.g = p.y; points[i].color = c; } particleSystem.SetParticles(points, points.Length); } } |
原文链接:http://catlikecoding.com/unity/tutorials/graphs/
-----------------------------------------------------------------------------------------------
不知道作者的原始意图是怎么样使用,
但是我觉得这个可以用来开发点对点一类的特效,比如闪电链,捆仙绳之类的
先用曲线计算出路径,然后依次设置特效点
Unity可视化数据:创建图表的更多相关文章
- [翻译] 使用ElasticSearch,Kibana,ASP.NET Core和Docker可视化数据
原文地址:http://www.dotnetcurry.com/aspnet/1354/elastic-search-kibana-in-docker-dotnet-core-app 想要轻松地通过许 ...
- [Python] Python 学习 - 可视化数据操作(一)
Python 学习 - 可视化数据操作(一) GitHub:https://github.com/liqingwen2015/my_data_view 目录 折线图 散点图 随机漫步 骰子点数概率 文 ...
- 【Visual Studio 扩展工具】使用 ComponentOne迷你图控件,进行可视化数据趋势分析
概述 迷你图 —— Sparklines是迷你的轻量级图表,有助于快速可视化数据. 它们是由数据可视化传奇人物Edward Tufte发明的,他将其描述为“数据密集,设计简单,字节大小的图形.”虽然迷 ...
- 【译】用 React 和 D3 创建图表
本文翻译自:https://dzone.com/articles/charts-with-modern-react-and-d3 本文将介绍如何利用 D3JS 和 ReactJS 来创建基础图表. R ...
- Kibana可视化数据(Visualize)详解
可视化 (Visualize) 功能可以为您的 Elasticsearch 数据创建可视化控件.然后,您就可以创建仪表板将这些可视化控件整合到一起展示. Kibana 可视化控件基于 Elastics ...
- Charted – 自动化的可视化数据生成工具
Charted 是一个让数据自动生成可视化图表的工具.只需要提供一个数据文件的链接,它就能返回一个美丽的,可共享的图表.Charted 不会存储任何数据.它只是获取和让链接提供的数据可视化. 在线演示 ...
- 【转】Laravel+Angularjs+D3打造可视化数据,RESTful+Ajax
http://897371388.iteye.com/blog/1975351 大致思路也就是下面,由于最近在学Laravel也在学Angularjs,加上之前做的项目用到了d3. 原来的方案如下: ...
- python使用VBA:Excel创建图表(转)
# -*- coding: utf-8 -*- """ Created on Thu Mar 06 11:22:03 2014 @author: Administrato ...
- python中用xlsxwriter创建图表
缺点:xlsxwriter不能对已存在的Excel进行编辑插入图标 生成图标需要: 1.先准备数据 2.将数据插入到excel中 3.根据插入的数据生成图表 这里的生成excel主要分为准备多维数 ...
随机推荐
- Pytorch_第五篇_深度学习 (DeepLearning) 基础 [1]---监督学习与无监督学习
深度学习 (DeepLearning) 基础 [1]---监督学习与无监督学习 Introduce 学习了Pytorch基础之后,在利用Pytorch搭建各种神经网络模型解决问题之前,我们需要了解深度 ...
- 树状图展示终端目录内容-tree
以树状图列出目录的内容,让你一目了然 执行 tree 指令,它会列出指定目录下的所有文件,包括子目录里的文件. 安装 我们通过包管理工具可以方便的安装它 mac - brew install tree ...
- python3.1for循环及应用
#给定范围,进行循环for i in range (0,5): print(i) #对序列进行遍历list1=[1,2,3,4,5]for i in list1: print(i+1) #对元组进行遍 ...
- MySQL8.0.20安装配置+用Navicat连接详细教程(win10,Navicat15)
MySQL 是最流行的关系型数据库管理系统,在 WEB 应用方面 MySQL 是最好的 RDBMS(Relational Database Management System:关系数据库管理系统)应用 ...
- Python 实现 T00ls 自动签到脚本(邮件+钉钉通知)
T00ls 每日签到是可以获取 TuBi 的,由于常常忘记签到,导致损失了很多 TuBi .于是在 T00ls 论坛搜索了一下,发现有不少大佬都写了自己的签到脚本,签到功能实现.定时任务执行以及签到提 ...
- 【av68676164(p54)】段式和段页式虚拟存储
段式存储管理 进程分段 把进程按逻辑意义划分为多个段,每段有段名,长度不定,进程由多段组成 例:一个具有代码段.数据段和堆栈段的进程 段式内存管理系统的内存分配 以段为的单位装入,每段分配连续的内存 ...
- 12、Java 正则表达式
简介 用来描述或者匹配一系列符合某个语句规则的字符串 正则表达式定义了字符串的模式. 正则表达式可以用来搜索.编辑或处理文本. 正则表达式并不仅限于某一种语言,但是在每种语言中有细微的差别. 一.正则 ...
- C++输出错误信息perror、strerror以及全局变量errno
头文件:#include<stdio.h>函数:perror.strerror,全局变量:errno.使用方法: FILE *fp; if((fp = fopen("test.t ...
- C#LeetCode刷题之#453-最小移动次数使数组元素相等(Minimum Moves to Equal Array Elements)
问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3877 访问. 给定一个长度为 n 的非空整数数组,找到让数组所有 ...
- .net Core使用sql语句实现批量修改数据状态
上图为查出的所有满足条件的数据,要选中若干条数据将其状态设置为作废 一共选中6条数据,当点击确认后修改数据状态. 前端代码 1.安装NuGet包 [Abp.Dapper]于EFCore中, 2.创建文 ...