目录
- Time时间体系
- timeScale
- maximumDeltaTime
- fixedDeltaTime
- captureDeltaTime
- deltaTime
- 整体展示
- Random随机数
- Mathf数学运算I
- Mathf.Round()
- Mathf.Ceil() Mathf.CeilToInt()
- Mathf.Sign
- Mathf.Clamp
- Mathf数学运算II-曲线变换
- Lerp 线性插值
- LerpAngle
- SmoothDamp
- 疑问:
- SmoothStep
- MoveTowards()
- MoveTowardsAngle()
- 波形比较
- 其他曲线
Time时间体系
(红色旗帜:只读静态变量,绿色:可修改静态变量)
通过edit>project settings>time
可修改的参数:
fixedDeltaTime、maximumDeltaTime、timeScale
timeScale
timeScale:The scale at which time passes.
可修改面板参数Time Scale
:The speed at which time progresses . Change this value to simulate bullet-time effects . A value of 1 means real-time . A value of .5 means half speed;a value of 2 is double speed.
可模拟子弹时间,跳跃时慢动作
maximumDeltaTime
maximumDeltaTime:The maximum value of Time.deltaTime in any given frame. This is a time in seconds that limits the increase of Time.time between two frames.
可通过面板修改Maximum Allowed Timestep
:A framerate-independent interval that caps the worst-case scenario when framerate is low.Physics calculations and Fixedupdate() eventswill not be performed for longer time than specified. 一种与帧速率无关的间隔,当帧速率较低时,它会限制最坏的情况。物理计算和Fixedupdate() 事件的执行时间不会超过指定时间。
fixedDeltaTime
fixedDeltaTime :执行物理和其他固定帧率更新(如 MonoBehaviour 的 FixedUpdate)的时间间隔(以秒为单位)。
可通过面板修改Fixed Timestep
值进行修改。Fixed Timestep
:A framerate-independent interval that dictates when physics calculations and Fixedupdate() events are performed
一个与帧速率无关的间隔,用于指定何时执行物理计算和Fixedupdate()事件
修改这个值的直观感受:对帧率产生影响
好吧,也不知道为啥有这么大区别…(注意拉成1其实跟10帧率差不多)
captureDeltaTime
captureDeltaTime:Slows your application’s playback time to allow Unity to save screenshots in between frames.
减缓应用程序的播放时间,使Unity可以在两帧之间保存屏幕截图。
如果此属性具有非零值,则无论实时时间和帧的持续时间如何,Time.Time都会以captureDeltaTime(按Time.timeScale缩放)的间隔增加。如果你想拍摄一部需要恒定帧速率的电影,并且想在两帧之间留出足够的时间来保存屏幕图像,这一点很有用。
【好吧,没听懂,以后再说吧】
下面是只读变量
deltaTime
乘以deltaTime可以达到平滑的效果
整体展示
public int framerate;
// Start is called before the first frame update
void Start()
{
framerate = Time.captureFramerate;
}
// Update is called once per frame
void Update()
{
Time.captureFramerate = framerate;
if(Input.GetKeyDown(KeyCode.Space)){
Time.timeScale = 0.2f;
Time.fixedDeltaTime = 0.005f;
}
if(Input.GetKeyUp(KeyCode.Space)){
Time.timeScale = 1f;
Time.fixedDeltaTime = 0.02f;
}
}
private void OnGUI() {
GUILayout.TextArea("Game Time:" + Time.time.ToString());
GUILayout.TextArea("Game timeSinceLevelLoad:" + Time.timeSinceLevelLoad.ToString());
GUILayout.TextArea("deltaTime:" + Time.deltaTime.ToString());
GUILayout.TextArea("fixedTime:" + Time.fixedTime.ToString());
GUILayout.TextArea("smoothDeltaTime:" + Time.smoothDeltaTime.ToString());
GUILayout.TextArea("frameCount:" + Time.frameCount.ToString());
GUILayout.TextArea("realtimeSinceStartup:" + Time.realtimeSinceStartup.ToString());
GUILayout.TextArea("unscaledDeltaTime:" + Time.unscaledDeltaTime.ToString());
GUILayout.TextArea("unscaledTime:" + Time.unscaledTime.ToString());
}
按空格和松开空格实现的效果如下:
【哇!顺便学习了输入和GUI,哈哈哈哈我好厉害~】
Random随机数
Mathf数学运算I
Mathf.Round()
整数部分为偶数小数为5也舍,整数部分为奇数,小数为5则进。注意unity的不同之处
Debug.Log("Mathf.Round(10.5f)=" + Mathf.Round(10.5f));//10
Debug.Log("Mathf.Round(11.5f)=" + Mathf.Round(11.5f));//12
Debug.Log("Mathf.Round(-10.5f)=" + Mathf.Round(-10.5f));//-10
Debug.Log("Mathf.Round(-11.5f)=" + Mathf.Round(-11.5f));//-12
Mathf.Ceil() Mathf.CeilToInt()
注意两个打印结果相同,但返回类型不同,其他ToInt方法也类似。
// float Ceil(float f);
Debug.Log(Mathf.Ceil(10.5f));// 11
// int CeilToInt(float f)
Debug.Log(Mathf.CeilToInt(10.5f));// 11
Mathf.Sign
public static float Sign (float f);
返回 f 的符号。
当 f 为正数或零时,返回值为 1,当 f 为负数时,返回值为 -1。
Debug.Log(Mathf.Sign(-10));//-1
Debug.Log(Mathf.Sign(10));//1
Mathf.Clamp
public static float Clamp (float value, float min, float max);
The float result between the minimum and maximum values.
限位函数,value在最大最小值之间,返回原value,否则取最大或者最小值。Note: if the minimum value is is greater than the maximum value, the method returns the minimum value.
Mathf数学运算II-曲线变换
他们都有一个相似的功能:给定一个初始点,一个target终点,要我们输出的函数从起始点到target点移动,只不过他们实现方法是不同的,效果也有很大的不一样。在我们以后的项目中,利用好这些函数会非常方便且自由地控制例如物体的位移、旋转等。
Lerp 线性插值
public static float Lerp (float a, float b, float t);
在 a 与 b 之间按 t 进行线性插值。参数 t 限制在范围 [0, 1] 内。
当 t = 0 时,返回 a 。
当 t = 1 时,返回 b 。
当 t = 0.5 时,返回 a 和 b 的中点。
public float minX = 0f;
public float maxX = 20f;
float startTime = 2f;
void Start()
{
// t不在[0,1]范围会被clamp限位
Debug.Log("Mathf.Lerp(0,5,200)="+Mathf.Lerp(0,5,-1));//0
Debug.Log("Mathf.Lerp(0,5,200)="+Mathf.Lerp(0,5,200));//5
}
// Update is called once per frame
void Update()
{
// 从第2秒开始沿x方向从0匀速移动到5,速度为(maxX-minX)/1
transform.position = new Vector3(
Mathf.Lerp(minX,maxX,Time.time-startTime),
transform.position.y,
transform.position.z
);
}
LerpAngle
public static float LerpAngle (float a, float b, float t);
与 Lerp 相同,但是在值环绕 360 度时确保值正确插入。
参数 t 限制在范围 [0, 1] 内。假设变量 a 和 b 以度为单位。
public float start = 0f;
public float end = 90f;
float startTime = 2f;
void Update()
{
float currentAngle = Mathf.Lerp(start,end,Time.time-startTime);
transform.eulerAngles = new Vector3(
transform.eulerAngles.x,
currentAngle,
transform.eulerAngles.z
);
}
lerp插值可以也通过类似current = Mathf.Lerp(current,end,Time.deltaTime)
方法刷新初始值,实现非线性运动
public float current = 0f;
public float end = 5f;
float startTime = 2f;
// Update is called once per frame
void Update()
{
if(end - current <0.01f)
current = end;
else
current = Mathf.Lerp(current,end,Time.deltaTime);
// 从第2秒开始沿x方向从0匀速移动到5,速度为(maxX-minX)/1
transform.position = new Vector3(
current,
transform.position.y,
transform.position.z
);
}
但可以明显看出移动很不平滑,且代码不简洁,接下来将介绍两个函数能方便实现非线性平滑变换
SmoothDamp
public static float SmoothDamp (float current, float target, ref float currentVelocity, float smoothTime, float maxSpeed= Mathf.Infinity, float deltaTime= Time.deltaTime);
- current 当前位置。(下面代码用
transform.position.x
,注意和lerp smoothStep区别) - currentVelocity 当前速度,此值由函数在每次调用时进行修改。(这个值初始值为0即可,不需要管)
- smoothTime 达到目标所需的近似时间。值越小,达到目标的速度越快。
public float target = 5f;
float velocity = 0f;
public float maxSpeed;
// Update is called once per frame
void Update()
{
transform.position = new Vector3(
Mathf.SmoothDamp(transform.position.x,target,ref velocity,5f,maxSpeed),
transform.position.y,
transform.position.z);
}
疑问:
- smoothTime 非常不准确
参考:🔗Mathf.SmoothDamp takes longer than it should inside a coroutine
SmoothStep
public static float SmoothStep (float from, float to, float t);
在 min 与 max 之间进行插值,在限制处进行平滑。
此函数采用与 Lerp 相似的方式在 min 与 max 之间进行插值。 但是,插值会从起点逐渐加速,然后朝着终点减慢。 这可用于创建表现十分自然的动画、淡化和其他过渡。
public float target = 5f;
float velocity = 0f;
public float maxSpeed;
// Update is called once per frame
void Update()
{
transform.position = new Vector3(
Mathf.SmoothStep(0,target,Time.time/5),
transform.position.y,
transform.position.z);
}
三者比较
MoveTowards()
public static float MoveTowards (float current, float target, float maxDelta);
将值 current 向 target 靠近。
这本质上与 Mathf.Lerp 相同,但是该函数确保速度不超过 maxDelta。 maxDelta 为负值时将值推离 /target/。
public float target = 5f;
float speed = 1f;
// Update is called once per frame
void Update()
{
transform.position = new Vector3(
Mathf.MoveTowards(transform.position.x,target,Time.deltaTime*speed),
transform.position.y,
transform.position.z);
}
MoveTowardsAngle()
与 MoveTowards 相同,但是在值环绕 360 度时确保值正确插入。
波形比较
lerp是定义好时间,moveTowards是定义好速度
脚本中加入变量public AnimationCurve a;
即可调出曲线
其他曲线
InverseLerp:Determines where a value lies between two points.
Repeat 对值 t 进行循环,使它不会大于长度,并且不会小于 0。(AnimationCurve 中就是Loop)
public static float Repeat (float t, float length);
这类似于取模运算符,但是它适用于浮点数。例如,将 3.0 用于 t 并将 2.5 用于 length,结果是 0.5。而当 t = 5 并且 length = 2.5 时,结果是 0.0。但是请注意,与取模运算符一样,没有为负数定义行为。
PingPong PingPong 返回一个值,该值将在值 0 与 length 之间递增和递减。
要想实现往复运动,比如对前面的Time.time取repeat 或者pingpong就能实现往复运动
transform.position = new Vector3(
Mathf.Lerp(minX,maxX,Mathf.PingPong(Time.time,1)),
transform.position.y,
transform.position.z
);
LinearToGammaSpace 将给定值从线性转换为伽马 (sRGB) 颜色空间。
GammaToLinearSpace 将给定值从伽马 (sRGB) 转换为线性颜色空间。
大概意思就是伽马图视觉效果比线性的好,但不好计算,所以一般转换成linear计算完在转回gamma值。
PerlinNoise 生成 2D 柏林噪声。
柏林噪声是在 2D 平面上生成的浮点值的伪随机图案(虽然 该方法普及到三维或更高维,不过未在 Unity 中实现)。 该噪声不包含每个点处的完全随机值,而是由 “波”组成,其值在图案中逐渐增大和减小。该噪声可以 用作纹理特效的基础,以及用于动画、生成地形高度贴图 和许多其他内容。
作用:
- 随机颜色过渡