栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 游戏开发 > 其他

Mathf知识点

其他 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Mathf知识点

Mathf与C# 中的Math几乎一样,Math是C#自带的工具类,主要就提供一些数学相关计算方法,Mathf是Unity专门封装的,不仅包含Math中的方法,还多了一些适用于游戏开发的方法

常用方法——一般计算一次

1、圆周率——Mathf.PI

2、取绝对值——Mathf.Abs

3、向上取整——Mathf.CeilToInt

4、向下取整——Mathf.FloorToInt

5、钳制函数——Mathf.Clamp(value, min, max),判断一个数的范围,在[min,max]区间内返回value,超过范围分别返回最大或者最小值

6、获取最大值——Mathf.Max

7、获取最小值——Mathf.Min

8、一个数的n次幂——Mathf.Pow

9、四舍五入——Mathf.RoundToInt

10、返回一个数的平方根——Mathf.Sqrt

11、判断一个数是否是2的n次方——Mathf.IsPowerTwo

12、判断正负数——Mathf.Sign(返回±1,其中0返回正数)

常用方法——一般不停计算

1、插值运算——Lerp

// Lerp函数公式

// t为插值系数,取值范围为0~1

result = Mathf.Lerp(start, end, t) =>

result = Mathf.Lerp(start, 10, Time.deltaTime)

计算公式为:result = start + (end - start) * t;

(1)插值运算用法一:每帧改变start的值,变化速度先快后慢,位置无限接近,但是不会得到end位置

start = Mathf.Lerp(start, 10, Time.deltaTime)

(2)插值运算用法二:每帧改变t的值,变化速度匀速,位置每帧接近,当t>=1时,得到结果:

time += Time.deltaTime(time初始为0)

result = Mathf.Lerp(start, 10, time) ;

实际应用:一个对象跟随另一个对象

练习:使用线性插值实现一个方块跟随另一个方块移动

其中一个方块的移动脚本:

public class move : MonoBehaviour {
    public float speed = 5;

    // Update is called once per frame
    void Update() {
        float h = Input.GetAxis("Horizontal");
        float v = Input.GetAxis("Vertical");
        transform.Translate(new Vector3(h, 0, v) * speed * Time.deltaTime);
    }
}

另一个方块的跟随脚本:

public class follow : MonoBehaviour {
    public GameObject followObj;

    // Update is called once per frame
    void Update() {
        Vector3 start = transform.position;
        Vector3 end = followObj.transform.position;
        start.x = Mathf.Lerp(start.x, end.x, Time.deltaTime);
        start.z = Mathf.Lerp(start.z, end.z, Time.deltaTime);
        transform.position = start;
    }
}

但其实在Vector3中有直接的插值方法:Vector3.Lerp,因此以上代码可以直接简化为:

 transform.position = Vector3.Lerp(transform.position, followObj.transform.position, Time.deltaTime);

 匀速运动相对复杂一点,首先起始点A、目标点B是不变的,两点的距离是 ,需要改变【t】,那么该参数应该如何改变是匀速运动的关键, 既要匀速运动,那么【t】也一定是匀速改变

我们需要清楚插值函数第三个参数【t】的意义,要注意该参数并不表示时间,只是在实际应用中这个参数的量化通常与时间有关,为了便于区分,将实际移动时间标注为【T】,可以得到经历时间【T】后走过的路径长度  为:。那么该值与的比值一定是在【0,1】之间的,这个比值就可以作为第三个参数

举个例子:假设A(0,0,0),B(10,0,0),speed = 1f,那么distance = 10

当T=0时:dist = 0, t = 0,由插值计算公式:res = start + (end - start) * t得到,res=0

当T=1时,dist = 1,t = 0.1,res = 1,那么这时物体移动到(1,0,0)

当T=2时,dist = 2,t = 0.2,res = 2,那么这时物体移动到(2,0,0)

..........以次类推

可以看出,匀速移动时间与speed有关,而Unity中将【T】拆分为每一帧运行,实际的移动距离是(Time.time - startTime) * speed, 但实际上,在FixedUpdate中才能保证准确的匀速。

最终代码:

public class follow : MonoBehaviour {
    public GameObject followObj;
    public float speed = 0.01f;            // 以速度2f匀速跟随

    private Transform preStart, preEnd;
    private float cTime;                // 当前时间
    private float disPerFrame;          // 每一帧移动的距离
    private float distance;             // 两点距离

    private void Start() {
        preStart = gameObject.transform;
        preEnd = followObj.transform;
        distance = Vector3.Distance(preStart.position, preEnd.position);
        cTime = Time.time;
    }

    // Update is called once per frame
    
    void Update() {
        Vector3 start = transform.position;
        Vector3 end = followObj.transform.position;

        // 如果目标地点的位置改变,那么重新开始计时,并且重新记录起始点
        if (end != preEnd.position) {
            preStart = gameObject.transform;
            preEnd = followObj.transform;
            distance = Vector3.Distance(preStart.position, preEnd.position);
            cTime = Time.time;
        }
        
        float distCovered = (Time.time - cTime) * speed;    // 当前已经走过的路程
        float percPath = distCovered / distance;            // 走过路程的百分比
        transform.position = Vector3.Lerp(preStart.position, preEnd.position, percPath);
    }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/902330.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号