前言:遇到个听起来挺简单的需求,就是实现一个传输带,传输物品。但细想发现如果是直接设置物品的速度,或者通过设置父物体的方式带动物品,都挺不好,关联性太强。最后选择用到一个很实用的API, Rigidbody.MovePosition。
public void MovePosition (Vector3 position);
移动刚体并遵守插值设置。启用刚体插值时,Rigidbody.MovePosition可在帧之间创建平滑过渡。Unity在每个FixedUpdate调用中移动一个刚体。
我发现这个API可以实现放置一个物品在平台上,平台移动,物品也可以跟着移动,非常的实用。
接着就是思考无限运输物品的传输带怎么去做,这个可以参考循环滚动背景的思路,直接看视频。
这里是有效传输的部分
我们看一下传输效果:
我们在Scene窗口隐藏平台的Mesh,看一下核心的运作原理,
我们在移动平台的过程中,要动态更改两个BoxCollider的大小,这样就能保证传输平台一直有效。
场景布局:
代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Test : MonoBehaviour
{[Header("速度")]public float speed;private int currDir=1;private Transform[] beltsTrans;private BoxCollider[] beltsCollis;private Rigidbody[] beltsRbs;private Vector3 forwardRunBehindPos;private Vector3 behindPos;private float length;private float length2;protected bool init = false;protected void Awake(){beltsTrans = new Transform[2];beltsCollis = new BoxCollider[2];beltsRbs = new Rigidbody[2];//实例化新传送带beltsTrans[0] = transform.Find("传送带");beltsTrans[1] = Instantiate(beltsTrans[0].gameObject, transform).transform;//获取组件for (int i = 0; i < beltsTrans.Length; i++){beltsCollis[i] = beltsTrans[i].GetComponent<BoxCollider>();beltsRbs[i] = beltsTrans[i].GetComponent<Rigidbody>();}//计算长度length = beltsCollis[0].size.z * beltsTrans[0].localScale.z * transform.localScale.z;length2 = length * 2;//偏移第二个传送带beltsTrans[1].position = beltsTrans[1].position - beltsTrans[1].forward * length;//起点位置forwardRunBehindPos = beltsTrans[1].position;behindPos = forwardRunBehindPos;init = true;}protected void FixedUpdate(){if (!init) return;Move();}float dis;public void Move(){for (int i = 0; i < beltsTrans.Length; i++){//移动beltsRbs[i].MovePosition(beltsTrans[i].position + beltsTrans[i].forward * speed * currDir * Time.fixedDeltaTime);//计算距离起始点距离dis = Vector3.Distance(beltsTrans[i].position, behindPos);//Collider中心点beltsCollis[i].center = new Vector3(0, 0, Mathf.Lerp(0.5f * currDir, -0.5f * currDir, (dis / length2)));//Collider缩放if (dis<=length){beltsCollis[i].size = new Vector3(1, 1, Mathf.Lerp(0 , 1 , (dis / length)));}else if (dis > length && dis < length2){beltsCollis[i].size = new Vector3(1, 1, Mathf.Lerp(1 , 0 , ((dis - length )/ length)));}//返回起点else if(dis >= length2){beltsTrans[i].position = behindPos;}}}
}