Unity通过物理带动实现传输带运输物品

前言:遇到个听起来挺简单的需求,就是实现一个传输带,传输物品。但细想发现如果是直接设置物品的速度,或者通过设置父物体的方式带动物品,都挺不好,关联性太强。最后选择用到一个很实用的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;
            }
        }
    }
}

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-02-06 03:34:01       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-02-06 03:34:01       100 阅读
  3. 在Django里面运行非项目文件

    2024-02-06 03:34:01       82 阅读
  4. Python语言-面向对象

    2024-02-06 03:34:01       91 阅读

热门阅读

  1. 【Django-ninja】使用schema

    2024-02-06 03:34:01       51 阅读
  2. docker容器stop流程

    2024-02-06 03:34:01       45 阅读
  3. Linux cp命令(cp指令)解析

    2024-02-06 03:34:01       50 阅读
  4. 每日一题 力扣1696跳跃游戏

    2024-02-06 03:34:01       60 阅读
  5. 【数学1】基础数学问题

    2024-02-06 03:34:01       60 阅读
  6. 【Android】代码混淆简单介绍

    2024-02-06 03:34:01       62 阅读
  7. 异或加密原理及简单应用(C语言版)

    2024-02-06 03:34:01       56 阅读
  8. Docker Compose下载

    2024-02-06 03:34:01       52 阅读
  9. 【lesson12】高并发内存池项目最终完整版代码

    2024-02-06 03:34:01       45 阅读
  10. Simulink仿真中Simulink.ConfigSet用法

    2024-02-06 03:34:01       53 阅读
  11. 流量控制原理

    2024-02-06 03:34:01       60 阅读
  12. Android~集成opencv问题

    2024-02-06 03:34:01       50 阅读
  13. 蓝桥杯刷题day05——2023

    2024-02-06 03:34:01       52 阅读