Unity中Mathf.PingPong函数的作用及正确用法问询
这问题我刚学Unity的时候也踩过坑!咱们一步步把Mathf.PingPong的底给扒清楚~
先搞懂Mathf.PingPong对
t到底做了什么? 本质上,PingPong是把t这个数值,通过取余+反转的逻辑,“折叠”到0到length的区间里实现往返循环。具体的内在逻辑可以拆解成这三步:
- 先计算一个完整往返周期的总长度:
cycle = 2 * length(从0走到length再回到0,刚好是2倍length的距离) - 算出
t在这个周期里的相对位置:remainder = t % cycle(取余操作能让t超过周期后重新从0开始计数) - 判断当前处于往返的哪个阶段:如果
remainder大于length(也就是已经走到往回走的阶段),就返回cycle - remainder;否则直接返回remainder
你用常量t的时候,比如t=1、length=1,cycle=2,remainder=1%2=1,刚好等于length,所以返回1;如果t=0,余数就是0,自然返回0。但因为t固定不变,这个结果当然也不会有波动啦!
t的实际用途是什么? t的核心作用是提供一个持续增长的“驱动源”,PingPong的往返效果完全依赖于t的不断变化——只有t一直在增加,它的余数才会在0到2*length之间循环,进而让最终结果在0到length之间来回波动。
为什么大家都用Time.time?因为它是Unity里最省心的“自动增长时间值”:从游戏启动开始,它就以每秒1的速度持续增加,完美匹配PingPong对t的要求。当然你也可以用其他持续增长的数值,比如累加Time.deltaTime的自定义计时器、动画进度值等,只要是不断变大的就行。
正确用法示例
给你几个实用的开发场景,一看就懂:
场景1:让物体在X轴往返移动
public float moveRange = 5f; // 最大移动距离 public float moveSpeed = 1f; // 往返速度(值越大越快) void Update() { // 用Time.time * moveSpeed控制往返快慢 float pingPongValue = Mathf.PingPong(Time.time * moveSpeed, moveRange); // 让物体从初始位置的-moveRange/2到moveRange/2往返,避免只往一个方向偏移 transform.position = new Vector3(pingPongValue - moveRange/2, transform.position.y, transform.position.z); }
场景2:让UI图片闪烁(透明度变化)
public Image targetImage; public float blinkSpeed = 2f; void Update() { // PingPong返回0到1之间的值,刚好对应透明度范围 float alpha = Mathf.PingPong(Time.time * blinkSpeed, 1f); targetImage.color = new Color(targetImage.color.r, targetImage.color.g, targetImage.color.b, alpha); }
场景3:自定义可控的往返计时器
如果不想用Time.time,比如做一个受玩家操作影响的往返值:
private float customTimer = 0f; public float incrementSpeed = 0.5f; void Update() { // 每帧累加自定义计时器 customTimer += Time.deltaTime * incrementSpeed; float pingPongValue = Mathf.PingPong(customTimer, 10f); Debug.Log("当前往返值:" + pingPongValue); }
内容的提问来源于stack exchange,提问作者Pipupnipup
相关产品推荐
相关产品推荐

