Unity C# Tutorials - Building a Graph Visualizing Math

Unity入门系列

目标: 创建图形, 可视化数学函数

1 用立方体cube组成线

依赖数学函数, 计算出一系列的坐标对, 然后组成一条线

1.1 Prefabs 预制件

创建一个cube

删除 collider component

拉到Assets中, 这样就形成了一个prefabs

删除场景中的cube


1.2 Graph component

建一个脚本Graph

新建一个C# script, 命名为Graph

添加变量 public Transform pointPrefab;

新建一个Game Object

Create Empty, 命名为Graph

把上面的脚本Graph添加为component

再把上面的预制件cube设置到point prefab字段

1.3 实例化预制件

通过Instatiate方法实例化

public class Graph : MonoBehaviour {

    public Transform pointPrefab;

    void Awake () {

        Instantiate(pointPrefab);

    }

}

通过 Transform point = Instantiate(pointPrefab); 获得对象的引用

通过对象的localPosition属性设置位置

位置参数使用 3D vector.

        Transform point = Instantiate(pointPrefab);

        point.localPosition = Vector3.right;

试运行, 可以看到位置略有变化的立方体.

下面添加多一个对象

        Transform point = Instantiate(pointPrefab);

        point.localPosition = Vector3.right;

        point = Instantiate(pointPrefab);

        point.localPosition = Vector3.right * 2;

两个立方体,x坐标风别是1和2

1.4 循环代码

        int i = 0;

        while (i < 10)

        {

            Transform point = Instantiate(pointPrefab);

            point.localPosition = Vector3.right * i;

            i = i + 1;

        }

1.5 简化代码

        for (int i = 0; i < 10; i++)

        {

            Transform point = Instantiate(pointPrefab);

            point.localPosition = Vector3.right * i;

        }

效果是一样的.

1.6 改变范围

为函数表达方便, x的范围一般在0-1, 或者-1 ~ 1

相应的, 立方体也需要缩小

        for (int i = 0; i < 10; i++)

        {

            Transform point = Instantiate(pointPrefab);

            point.localPosition = Vector3.right * i;

            point.localScale = Vector3.one / 5f;

        }

调整x的范围到 -1 ~ 1

point.localPosition = Vector3.right * ((i + 0.5f) / 5f - 1f);

重新排成一条直线.

1.7 优化一下代码

        Vector3 scale = Vector3.one / 5f;

        Vector3 position;

        position.y = 0f;

        position.z = 0f;

        for (int i = 0; i < 10; i++)

        {

            Transform point = Instantiate(pointPrefab);

            position.x = (i + 0.5f) / 5f - 1f;

            point.localPosition = position;

            point.localScale = scale;

        }

1.8 通过函数, 用x计算出y

f(x)=x

        Vector3 scale = Vector3.one / 5f;

        Vector3 position;

        //position.y = 0f;

        position.z = 0f;

        for (int i = 0; i < 10; i++)

        {

            Transform point = Instantiate(pointPrefab);

            position.x = (i + 0.5f) / 5f - 1f;

            position.y = position.x;

            point.localPosition = position;

            point.localScale = scale;

        }


f(x)=x2

position.y = position.x * position.x;


2 创建更多的立方体

2.1 可变数量

添加变量

public int resolution = 10;

指定范围

    [Range(10, 100)]

    public int resolution = 10;

2.2 使用这个变量

        float step = 2f / resolution;

        Vector3 scale = Vector3.one * step;

        Vector3 position;

        position.z = 0f;

        for (int i = 0; i < resolution; i++)

        {

            Transform point = Instantiate(pointPrefab);

            position.x = (i + 0.5f) * step - 1f;

            position.y = position.x * position.x;

            point.localPosition = position;

            point.localScale = scale;

        }

2.3 设置层次, 方便管理

现在生成的立方体都是在根节点上面

方便管理, 给他们设置一个父亲

point.SetParent(transform, false);

3, 设置颜色

3.1 定义着色器 Shader

Assets / Create / Shader / Standard Surface Shader

命名为ColoredPoint.

着色器是用脚本定义的, 但语法不同于C#, 双击可以看到脚本:

Shader "Custom/ColoredPoint" {

Properties {

_Color ("Color", Color) = (1,1,1,1)

_MainTex ("Albedo (RGB)", 2D) = "white" {}

_Glossiness ("Smoothness", Range(0,1)) = 0.5

_Metallic ("Metallic", Range(0,1)) = 0.0

}

SubShader {

Tags { "RenderType"="Opaque" }

LOD 200

CGPROGRAM

#pragma surface surf Standard fullforwardshadows

#pragma target 3.0

sampler2D _MainTex;

struct Input {

float2 uv_MainTex;

};

half _Glossiness;

half _Metallic;

fixed4 _Color;

UNITY_INSTANCING_CBUFFER_START(Props)

UNITY_INSTANCING_CBUFFER_END

void surf (Input IN, inout SurfaceOutputStandard o) {

fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;

o.Albedo = c.rgb;

o.Metallic = _Metallic;

o.Smoothness = _Glossiness;

o.Alpha = c.a;

}

ENDCG

}

FallBack "Diffuse"

}

修改成我们需要的, 留意 struct Input 部分

Shader "Custom/ColoredPoint" {

Properties {

// _Color ("Color", Color) = (1,1,1,1)

// _MainTex ("Albedo (RGB)", 2D) = "white" {}

_Glossiness ("Smoothness", Range(0,1)) = 0.5

_Metallic ("Metallic", Range(0,1)) = 0.0

}

SubShader {

Tags { "RenderType"="Opaque" }

LOD 200

CGPROGRAM

#pragma surface surf Standard fullforwardshadows

#pragma target 3.0

// sampler2D _MainTex;

struct Input {

// float2 uv_MainTex;

            float3 worldPos;

};

half _Glossiness;

half _Metallic;

// fixed4 _Color;

UNITY_INSTANCING_CBUFFER_START(Props)

UNITY_INSTANCING_CBUFFER_END

void surf (Input IN, inout SurfaceOutputStandard o) {

// fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;

// o.Albedo = c.rgb;

o.Metallic = _Metallic;

o.Smoothness = _Glossiness;

// o.Alpha = c.a;

o.Alpha = 1;

}

ENDCG

}

FallBack "Diffuse"

}

现在我们已经有了一个可编程的shader

创建一个material, 命名为Colored Point, 采用上面的shader

给cube设置material为ColoredPoint

3.2 用坐标定义颜色

现在进入play模式, cube都是黑色的,

修改shader的surf函数:

// o.Albedo = 0;

o.Albedo.r = IN.worldPos.x * 0.5 + 0.5;

用y赋值给绿色:

o.Albedo.r = IN.worldPos.x * 0.5 + 0.5;

o.Albedo.g = IN.worldPos.y * 0.5 + 0.5;

可合并成一行:(红色 + 绿色 = 黄色)

o.Albedo.rg = IN.worldPos.xy * 0.5 + 0.5;

改一个函数玩玩: position.y = position.x * position.x* position.x;


4 让图像动起来,

要让图像动起来, 必须增加一个时间参数: f(x,t)取代f(x),

4.1 追踪这些点

为了让这些点动起来, 我们先建一个数组, 保存这些点, 以便可以控制他们, 改变他们的位置

points = new Transform[resolution];

for (int i = 0; i < resolution; i++) {

points[i] = point;

}

4.2 改变点的坐标

为了动态,y值的计算移到了update函数:

public class Graph : MonoBehaviour

{

    public Transform pointPrefab;

    [Range(10, 100)]

    public int resolution = 10;

    public Transform[] points;

    void Awake()

    {

        float step = 2f / resolution;

        Vector3 scale = Vector3.one * step;

        Vector3 position;

        position.z = 0f;

        position.y = 0f;

        points = new Transform[resolution];

        for (int i = 0; i < resolution; i++)

        {

            Transform point = Instantiate(pointPrefab);

            position.x = (i + 0.5f) * step - 1f;

            //不在这里计算y值了

            point.localPosition = position;

            point.localScale = scale;

            point.SetParent(transform, false);

            points[i] = point;

        }

    }

    void Update()

    {

        for (int i = 0; i < points.Length; i++)

        {

            Transform point = points[i];

            Vector3 position = point.localPosition;

            position.y = position.x * position.x * position.x;

            point.localPosition = position;

        }

    }

}

4.3 显示正弦波

现在进入play模式, 点坐标是一直值更新的, 只是一直一样, 所以我们看不出, 为了看效果, 采用正弦函数 + 时间变量

position.y =Mathf.Sin(Mathf.PI *(position.x+Time.time));

这样就可以看到动态效果了


原文: http://catlikecoding.com/unity/tutorials/basics/building-a-graph/

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容

  • 这是今天的成果吧,虽然还是没有全部完成,但是大致的功能已经实现,飞机的移动,限制移动范围,子弹的发射,消灭敌人,敌...
    Unity学习的路上阅读 2,827评论 1 2
  • setTimeout setTimeout(function(){},1000)//隔一秒后执行函数;类似闹钟;广...
    overisover阅读 198评论 0 0
  • Kontlin日常 数值类型 Double 64 Float 32 Long 64 Int 32 Short 16...
    李汪汪汪侠阅读 185评论 0 0
  • 因寒冷而打颤的人,最能体会到阳光的温暖。经历了人生烦恼的人,最懂得生命的可贵。—— 惠特曼《草叶集》 一、爱生活 ...
    思维导图培训师陈苏娟阅读 189评论 0 0
  • 小熊帕德和女孩维纳的故事 1.等候(1) 每当我放学后, 你都在那儿静静地...
    轻雨烟阅读 258评论 0 3