zoukankan      html  css  js  c++  java
  • 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 AwakeEmission,以及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);
        }
     
    10粒子组成的线

    就是这样,现在我们得到了一个沿着X轴由黑到红的点线。显示多少点取决于分辨率的值。

     
    分辨率为10、100的线

    现在,只有在图表初始化的时候考虑分辨率。播放模式下更新值不起任何作用。现在来修改一下。

    检测分辨率的一个简单方法是存储两次,然后经常检查这两个值是否仍然一样。如果在某些点不一样,我们就要重建图表。为此需要创建一个私有变量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;

     

    有着分辨率范围滑块的Grapher1

    现在该设置点在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);
        }
     
    函数 f(x) = x.

    接下来把点的绿色分量设置的和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/

    -----------------------------------------------------------------------------------------------

    不知道作者的原始意图是怎么样使用,

    但是我觉得这个可以用来开发点对点一类的特效,比如闪电链,捆仙绳之类的

    先用曲线计算出路径,然后依次设置特效点

  • 相关阅读:
    array_flip
    qy Undefied index报错
    strip_tag
    query使用
    tp5 sql 大于小于
    OfficeTools.OnlineEditWord
    OCX控件打包成CAB并实现数字签名过程
    使用css技术代替传统的frame技术
    delphi常用函数和方法
    js正则表达使用实例
  • 原文地址:https://www.cnblogs.com/forlove/p/3801471.html
Copyright © 2011-2022 走看看