本文由Aoi翻译,转载请注明出处。文章来自于catlikecoding,原文做者介绍了Unity制做图表、可视化数据的方法。更多的名词解释内容,请点击末尾的“原文连接”查看。html
介绍数组
这个教程里,咱们在Unity 4里用C#脚原本展现日趋复杂的图表。你将学会:编辑器
假设你已经对Unity编辑器有了初步的了解,而且知道建立C#脚本的基本知识。若是你完成了简易时钟制做教程,那么你就能够开始这一章了。函数
注意我会常常省略已经讲解过的代码块。新的代码内容会继续讲解清楚。
oop
准备布局
打开一个新项目, 咱们将在一个单位的立方体内创建表格,放置于(0, 0, 0)和(1, 1, 1)之间。设置一下编辑器以获得更好的视觉效果。4 Split是一个方便预约义的试图布局,因此选择它。从Window / Layout / 4 Spit选择,或者在屏幕右上方的下拉菜单里。把全部的视图模式都设置为Textured,旋转透视图,这样三个轴就都指向你了。this
经过GameObject / Create Other / Cube建立一个新的方块,设置位置为(0.5, 0.5, 0.5)。这为咱们校准视图提供参考。如今缩放和平移视图使其聚焦于单位方块。spa
最后,选择Main Camera,经过GameObject / Align With View使其匹配立透视图。若是那无论用,经过单机确认正确的视图是否激活,而后再试试。翻译
场景视图以及相机聚焦于方块3d
这个方块再也不须要了,因此移除它。而后经过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/
-----------------------------------------------------------------------------------------------
不知道做者的原始意图是怎么样使用,
可是我以为这个能够用来开发点对点一类的特效,好比闪电链,捆仙绳之类的
先用曲线计算出路径,而后依次设置特效点