【Unity基础练习 数字表面(函数雕刻)】

今天的基础练习来源教程如下:
Unity数字表面
另外,本次基础练习使用的是上次视图基础练习的场景继续开发,所以请先看看之前的练习。
创建一个委托C#脚本GraphFunction以及枚举脚本GraphFunctionName
在这里插入图片描述
为的是之后更方便存储不同的函数,实现不同函数之间的切换。
Graph脚本代码:

using UnityEngine;

public class Graph : MonoBehaviour
{
    const float pi = Mathf.PI;//使用局部常量获取PI值
    public Transform pointPrefab;
    static GraphFunction[] functions = {//创建索引数组
        //因为这个数组不论在哪总是相同的,所以没有必要为每个视图实例创建一个
        SineFunction,Sine2DFunction,MultiSineFunction,MultiSine2DFunction,
        Ripple,Cylinder,Sphere,Torus
    };
    Transform[] points;

    [Range(10,100)]
    public int resolution = 50;//使用Range控制立方体数量

    public GraphFunctionName function;//枚举类型
    void Awake() {
        float step = 2f/resolution;//调整步长
        Vector3 scale = Vector3.one*step;
        points = new Transform[resolution*resolution];//新的函数生成方式不再依赖于原始位置,所以重写生成函数
        for(int i=0;i<points.Length;i++){
            Transform point = Instantiate(pointPrefab);
            point.localScale = scale;
            point.SetParent(transform,false);
            points[i] = point;
        }
    }

    void Update() {//实现动态效果
        float t = Time.time;//缓存以节约性能空间
        GraphFunction f = functions[(int)function];//使用委托类型获取值
        float step = 2f/resolution;
        for(int i=0,z=0;z<resolution;z++){
            float v = (z+0.5f)*step -1f;
            for(int x=0;x<resolution;x++,i++){
                float u = (x+0.5f)*step -1f;
                points[i].localPosition = f(u,v,t);//使用此种方式代替原来的赋值方法
            }
        }
    }

    static Vector3 SineFunction(float x,float z,float t){//用static让方法和实例脱离联系,让别的脚本也可以直接调用
        Vector3 p;
        p.x = x;
        p.y = Mathf.Sin(pi * (x+t));
        p.z = z;
        return p;
    }
    
    static Vector3 MultiSineFunction(float x,float z,float t){
        Vector3 p;
        p.x = x;
        p.y = Mathf.Sin(pi*(x+t));
        p.y +=Mathf.Sin(2f*pi*(x+2f*t))/2f;
        p.y *=2f/3f;
        p.z= z;
        return p;
    }
    
    static Vector3 Sine2DFunction(float x,float z,float t){
        Vector3 p;
        p.x = x;
        p.y = Mathf.Sin(pi*(x+t));
        p.y += Mathf.Sin(pi*(z+t));
        p.y *=0.5f;
        p.z = z;
        return p;
    }
    
    static Vector3 MultiSine2DFunction(float x,float z,float t){
        Vector3 p;
        p.x = x;
        p.y = 4f*Mathf.Sin(pi*(x+z+t/2f));
        p.y += Mathf.Sin(pi*(x+t));
        p.y += Mathf.Sin(2f*pi*(z+2f*t))*0.5f;
        p.y *=1f/5.5f;
        p.z = z;
        return p;
    }

    static Vector3 Ripple(float x,float z,float t){//涟漪函数
        Vector3 p;
        float d = Mathf.Sqrt(x*x+z*z);
        p.x = x;
        p.y = Mathf.Sin(pi*(4f*d-t));
        p.y /=1f+10f*d;
        p.z = z;
        return p;
    }

    static Vector3 Cylinder(float u,float v,float t){//圆柱体函数
        Vector3 p;
        float r = 0.8f + Mathf.Sin(pi*(6f*u+2f*v+t))*0.2f;
        p.x = r*Mathf.Sin(pi*u);
        p.y = v;
        p.z = r*Mathf.Cos(pi*u);
        return p;
    }

    static Vector3 Sphere(float u,float v,float t){
        Vector3 p;
        float r = 0.8f+ Mathf.Sin(pi*(6f*u+t))*0.1f;
        r += Mathf.Sin(pi*(4f*v+t))*0.1f;
        float s = r*Mathf.Cos(pi*0.5f*v);
        p.x = s*Mathf.Sin(pi*u);
        p.y = r*Mathf.Sin(pi*0.5f*v);
        p.z = s*Mathf.Cos(pi*u);
        return p;
    }

    static Vector3 Torus(float u,float v,float t){
        Vector3 p;
        float r1 = 0.65f + Mathf.Sin(pi*(6f*u+t))*0.1f;
        float r2 = 0.2f + Mathf.Sin(pi*(4f*v+t))*0.05f;
        float s =r2*Mathf.Cos(pi*v)+r1;
        p.x = s*Mathf.Sin(pi*u);
        p.y = r2*Mathf.Sin(pi*v);
        p.z = s*Mathf.Cos(pi*u);
        return p;
    }

}

委托脚本GraphFunction
在这里插入图片描述
枚举类脚本
在这里插入图片描述
实现效果比较复杂,这里就不贴出了。

今天的练习需要大量的数学知识,但是除去这些数学知识,我们还能学到哪些东西呢?

首先就是委托类:
委托类获取实际函数的实现:
在这里插入图片描述
这里的functions是从静态数组function中获取的
在这里插入图片描述
而索引数是从枚举类中获得的
在这里插入图片描述
这种方法在加载数目大的函数或者资源时十分好用。我记得我上半年做的一个JAVA游戏坦克大战中,也是使用类似的方式去加载敌人,主角,子弹等不同的类装载到游戏中。
在这里我们创建了一个委托类GraphFunction,使用索引+枚举+委托这种方式加载函数,去定向获取不同的函数。这样写可以使得我们的脚本更加简洁,而且更不容易出错。

其它的?
其它的就是这次使用这些数学函数去生成方块的动态位置让我思路开阔了很多。比如说我觉得这种方法可以用来动态控制场景的变换,或者是编程化实现不同的场景。(因为这次练习的场景生成没有创建任何一个立方体,都是由脚本控制生成的)

还有吗?
数学真是太重要了!!!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值