本文共 4360 字,大约阅读时间需要 14 分钟。
一.Transform
1.transform.Translate
不会考虑到碰撞。transform.Translate(Vector3 targetPos,指定参照坐标系(默认为Space.Self))
2.transform.position
我认为Transform严谨来说并不能称作移动,而是直接改变物体的坐标。transform.position(vector3 targetPos) targetPos是指定的坐标位置。
二.刚体
1.MovePosition()
2.velocity 使物体忽略静摩擦力,从静止状态快速进入运动状态。
3.AddForce() 给物体添加一个方向力。
三.角色控制器
1.SimpleMove() 模拟重力,返回值表示当前角色是否着地。
2.Move() 不模拟重力,返回值表示角色于周围的碰撞信息。
四.平滑
1.Lerp()——线性插值移动(Vector2.Lerp,Vector3.Lerp,Mathf.Lerp,Quaternion.Lerp,Color.Lerp,Material.Lerp)
在Mathf中,Lerp函数是这样的:Lerp(float a,float b,float t)。a是起始位置,b是结束位置,t是一个比例因数,t可以用作为时间单位,但并不能理解为时间,是一个[0,1]的值,t=0时返回a,t=1时返回b。
首先说明一下Lerp函数的计算公式是如何推导出来的:t(b-a)+a。 假如从起始点a点到目标点b点,当前运动到的点为c点,需要求出已经运动的距离占总距离的多少,也就是a和c的距离占a和b的距离的比例。 那么t=(c-a)/(b-a),解出tb-ta=c-a,所以t(b-a)=c-a,则c=t(b-a)+a。
之后看一下Lerp的内部实现:用Clamp01函数去限制t的范围,之后再用计算公式:a+(b-a)*t计算每帧到达的位置。
对于Lerp之前一直有一个误区就是认为它是减速运动,其实它的运动类型是由参数决定的。 我测试出来了用它可以实现减速运动,先加速后减速,匀速运动。 其实都是利用公式a+(b-a)*t变换的。 1.如果想实现减速运动,代码如下图。 观察Cube的运动或者观察Inspector面板中X的值,发现变化的越来越慢,而且x的值永远不等于目标值只能无限接近目标值,最大为7.999999。 因为Time.deltaTime每帧是一样的,例如0.1。所以用公式a+(b-a)*t计算可知。 第一帧:0+(8-0)*0.1=0+0.8=0.8 比上一帧多移动了0.8 第二帧:0.8+(8-0.8)*0.1=0.8+0.72=1.52 比上一帧多移动了0.72 第三帧:1.52+(8-1.52)*0.1=1.52+0.648=2.168 比上一帧多移动了0.648 第四帧:以此类推。 发现每帧移动的距离都在减少,这是由于起始点位置是变化的所导致的。
2.如果想实现先加速后减速运动,代码如下图。Time.time只能用于程序一开始就运动的物体,如果在程序中再使用Time.time将会一帧直接到达目标值,因为Time.time早已经大于1。 观察Cube的运动或者观察Inspector面板中X的值,发现变化的越来越快,X坐标的值是可以到达目标值的。 例如每帧Time.time增加0.1秒,用公式a+(b-a)*t计算可知。 第一帧:0+(8-0)*0.1=0+0.8=0.8 比上一帧多移动了0.8 第二帧:0.8+(8-0.8)*0.2=0.8+1.44=2.52 比上一帧多移动了1.44 第三帧:2.52+(8-2.52)*0.3=2.52+1.644=4.164 比上一帧多移动了1.644 第四帧:以此类推。 发现每帧移动的距离先增加后减少,这是由于起始点的位置和比例因数一直变化所导致的。 当Time.time=1时也就是游戏运行一秒钟时,Cube到达目标值。这段代码的含义就是让Cube在一秒钟内从起始点到达目标点。
3.如果想实现匀速运动,代码如下图 观察Cube的运动或者观察Inspector面板中X的值,发现变化的非常匀速,X坐标的值是可以到达目标值的。 例如每帧Time.time增加0.1秒,用公式a+(b-a)*t计算可知。 第一帧:0+(8-0)*0.1=0+0.8=0.8 比上一帧多移动了0.8 第二帧:0+(8-0)*0.2=0+1.6=1.6 比上一帧多移动了0.8 第三帧:0+(8-0)*0.3=0+2.4=2.4 比上一帧多移动了0.8 第四帧:以此类推。 发现每帧移动的距离都是不变的,这是由于起始点和目标点的位置是不变的,只由比例因数决定。 当Time.time=1时也就是游戏运行一秒钟时,Cube到达目标值。这段代码的含义就是让Cube在一秒钟内从起始点到达目标点。
如果想让物体在time秒后到达目标点呢?
1.改变Time.deltaTime 首先我们不设置到达目标点的时间,如下图代码所示:
比例因数t每帧加上Time.deltaTime则游戏运动一秒钟后到达目标位置,因为Time.deltaTime的值是1/帧率,假如每秒50帧那么一秒后t的值将会变为1。 如果需要设置到达目标点的时间,如下图代码所示:因为Time.deltaTime的值是1/帧率,所以可以列一个等式。 也就是说乘以1/time后t值的增长速度变慢了,需要之前time倍的时间才可以到达1。 2.改变Time.time(不推荐)Time.time只适用于游戏一开始时运动的情况。如果在游戏过程中运动则Time.time有可能早已大于0。
2.SmoothDamp()——平滑阻尼移动(Vector2.SmoothDamp,Vector3.SmoothDamp,Mathf.SmoothDamp) 由Damp可知是一个阻尼移动所以会受到阻力而减速,也就是越来越慢。
在Mathf中,SmoothDamp是这样的:Mathf.SmoothDamp(float current, float target, ref float currentVelocity, float smoothTime, float maxSpeed)。 current是当前位置,target是目标位置,currentVelocity是当前速度(必须是一个全局变量),smoothTime是到达目标位置的时间,maxSpeed是最大速度(默认为无穷大)。
首先看一下SmoothDamp是如何实现的: 因为它不像Lerp那么简单它的内部参数经过了很多次的调整所以效果会更加平滑,常用于相机跟随操作。 3.MoveTowards()——平滑移动(Vector2.MoveTowards,Vector3.MoveTowards,,Mathf.MoveTowards)
Math.MoveTowards(float a,float b,float maxDelta) a是起始位置,b是结束位置,maxDelta是每次向目标点移动的距离,maxDelta是一个[-∞,b]的值。 如果maxDelta大于0则物体逼近目标点移动,如果maxDelta小于0则物体远离目标点移动。
注意maxDelta是每次向目标点移动的距离。
1.物体放在原点,x值从0运动到10,maxDelta是一个正值。运行后发现物体朝目标点的正方向移动。2.物体放在原点,x值从0运动到10,maxDelta是一个负值。运行后发现物体朝目标点的负方向移动。 3.物体放在x为10的位置,x值从10运动到0,maxDelta是一个正值。运行后发现物体朝目标点的正方向移动。 4.物体放在x为10的位置,x值从10运动到0,maxDelta是一个负值。运行后发现物体朝目标点的负方向移动。
下面都是各种不同的测试: 首先是一种没什么使用价值的做法。 设置a,b,maxDelta的值都是定值,代码如下图。 运行后发现物体停在x为1的位置永远不发生运动。 其次还是一种没什么使用价值的做法。 设置a,maxDelta是定值,b为变化的,代码如下图。 运行后发现物体从0缓慢运动到1之后不再运动。其实MoveTowards函数的参数a一般是当前物体的自身位置,是一个变化的值,而b和maxDelta为定值。 既然maxDelta是一个(-∞,b]的定值,那么当它的值属于不同区间时是如何变化的呢?
例如a=当前的a,b=5时。 当maxDelta为负数时,物体向目标点的相反方向运动。 当maxDelta为0时,物体原地不动。 当maxDelta为5时,物体一帧就会移动到目标位置。 当maxDelta为5.1时,物体一帧就会移动到目标位置,并不会超过b的值。 所以maxDelta是代表了每次朝目标点移动的距离,最大只能是目标位置的值。
那如果想让物体在time秒后到达目标点呢?
4.Slerp()——球形插值(Vector3.Slerp,Quaternion.Slerp)
五.特殊
1.Mathf.PingPong(float t,float length)——乒乓运动
Mathf.PingPong(float t,float length)t是一个[0,length]的值,是一个需要变化的值。
官方的实例用法(不推荐):Time.time只适用于游戏一开始时运动的情况。如果在游戏过程中运动则Time.time并不是从0开始计算的。
运行后发现物体的x坐标在0到4之前来回运动。
那如果想让物体在time秒后到达目标点再回到起始点来回运动呢?
首先如果不设置时间,代码如下图所示:
运行后发现物体的x坐标在0到10之间来回运动,一去一回的时间分别都是10秒。 如果需要设置到达目标点的时间,代码如下图所示:运行后发现物体的x坐标在0到10来回运动,一去一回的时间分别都是5秒。如果想让物体不从0开始运动,而是指定的位置,代码如下图所示:因为sum的值是在0到target之间运动,那么加上指定开始位置的值,就实现了功能。 运行后发现物体的x坐标在5到15来回运动,一去一回的时间分别都是10秒。
注意PingPang的内部实现中,length会作为分子出现,如果length为0时会报NaN(Not a Number)的错误。
Unity中关于NaN的问题:3.Math.Repeat(float t,float length) 返回一个[t,length)的值,t是一个变化的值。
转载地址:https://liuhaowen.blog.csdn.net/article/details/88392679 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!