unity传送带的简单实现

[toc]
考核项目——初学者的笔记。
参考【unity简单实现传送带效果(代码在简介)-哔哩哔哩】


目前是4个长方体 cube 作为传送带,再加上物体实现的,有一个固定视角摄像机,还有一个移动视角的摄像机。

一、传送带脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ConveyorBelt : MonoBehaviour
{
public float MoveSpeed = 0; // 传送带的移动速度
private Vector3 ver; //向量 代表方向

private void Start() // 在脚本启动时调用方法
{
//MoveSpeed = 5; // 写死了就没办法控制速度了
ver = -transform.right; //这个就是获取自身的方向 这个红色控制的X轴 就是(1,0,0) 这个是往左动的所以要加个符号
}

// 当其他物体进入触发器并保持在触发器中时调用
private void OnTriggerStay(Collider other)
{
// 通过向量 ver 和 MoveSpeed 来移动物体的位置
// Time.deltaTime 用于平稳处理移动,确保在不同设备上表现一致
other.transform.position += ver*MoveSpeed*Time.deltaTime;
}
}

二、相关问题、注意事项

1、为什么需要脚本?

这个脚本的作用是模拟传送带的效果。在游戏开发中,我们可能希望有一些机制或物体,如传送带、流动的河流等,能够以某个方向移动其他物体,而不是简单地通过改变它们的位置。

这个脚本的主要作用是在物体进入触发器时,通过修改它们的位置,使它们沿着传送带的方向移动。这种方法相对简单且易于调整,而不涉及复杂的物理引擎力或速度计算。

2、使用脚本的好处

  1. 简化物体移动: 脚本提供了一种相对简单的方法,无需使用复杂的物理引擎设置。我们只需要只需设置传送带的速度,就能够实现物体在其上移动。
  2. 可定制性: 通过在 Unity 编辑器中调整 MoveSpeed 变量,可以轻松调整传送带的速度。这种可调整性使得在不同情境下使用这个脚本变得方便。
  3. 适用性: 对于一些简单的场景和需求,这个脚本提供了一种有效的方法来实现传送带效果,而无需使用更复杂的物理引擎设置。

需要注意的是,这只是实现传送带效果的一种方法。如果游戏要求更为真实的物理效果,或者需要更复杂的互动,可能需要考虑使用 Unity 的物理引擎和更复杂的脚本逻辑。

3、代码的主要思路

这个脚本的主要目的是创建一个模拟传送带效果的功能。

  1. 初始化
  • public float MoveSpeed = 0 :这个变量用于设置传送带的移动速度。
  • private Vector3 ver :这个向量代表传送带的方向。
  1. Start 方法
  • ver = -transform.right :在脚本启动时,通过将 ver 设置为 -transform.right,初始化传送带的方向为向左。
  1. OnTriggerStay 方法
  • private void OnTriggerStay(Collider other) : 当其他物体进入触发器并停留在触发器中时,此方法被调用。
  • other.transform.position += ver * MoveSpeed * Time.deltaTime;:通过向量 ver 和移动速度 MoveSpeed 来移动进入触发器的物体。Time.deltaTime 用于确保在不同设备上表现一致,以实现平滑移动。

简而言之,这个脚本假定传送带是一个沿着X轴负方向移动的物体。当其他物体进入传送带的触发器时,它们将被沿着传送带的方向移动,模拟了传送带的效果。

4、Unity 触发器

理解 Unity 中的触发器是学习过程中的一部分。在 Unity 中,触发器是一种用于检测物体之间交互的组件。它通常用于检测物体是否进入或离开某个区域,或者两个物体之间是否发生碰撞。

在代码中,使用了 OnTriggerStay 方法,这是 Unity 中特有的一种方法,用于检测物体在触发器内停留的情况。这个触发器通常由 Collider 组件配合使用,可以是一个 Cube、Sphere 或其他形状,它包围在一个物体周围,并且可以设置成触发器模式。

在代码中,这个触发器(传送带的触发器)的作用是检测进入它范围的其他物体。当其他物体进入传送带的触发器时,OnTriggerStay 方法就会被调用。在这个方法里,可以执行一些逻辑,比如修改物体的位置,模拟传送带的效果。

为什么要使用触发器?

  1. 检测碰撞和交互: 触发器用于检测物体之间的碰撞或交互。通过在触发器中添加脚本,你可以在物体之间的碰撞或交互发生时执行特定的代码逻辑。

  2. 触发事件: 当物体进入、停留或离开触发器时,你可以触发特定的事件,执行相应的操作。

  3. 灵活性: 触发器提供了一种灵活的方式来设计游戏中的交互和行为。你可以在 Unity 编辑器中直观地设置触发器,而无需编写大量的代码。

对于这个传送带脚本,通过使用触发器,可以在物体进入触发器时触发传送带的效果,而无需使用物理引擎的力或速度来实现。这使得传送带的实现更加灵活和容易调整。

5. 传送带的方向控制

  1. 写死方向,设置为 private
    下面的 MoveSpeed 如果在start里写死的话,再加上 private,是不能在unity编辑器里更改的。
private Vector3 ver; // 向量 代表方向

private void Start() // 在脚本启动时调用方法
{
//MoveSpeed = 5; // 写死了就没办法控制速度了
ver = -transform.right; //这个就是获取自身的方向 这个红色控制的X轴 就是(1,0,0) 这个是往左动的所以要加个符号
}
  1. 在 unity 编辑器里具体调整每个传送带方向,设置为 public
public class ConveyorBelt : MonoBehaviour
{
public float MoveSpeed = 4; // 传送带的移动速度
public Vector3 ver; //向量 代表方向

// 当其他物体进入触发器并保持在触发器中时调用
private void OnTriggerStay(Collider other)
{
// 通过向量 ver 和 MoveSpeed 来移动物体的位置
// Time.deltaTime 用于平稳处理移动,确保在不同设备上表现一致
other.transform.position += ver * MoveSpeed * Time.deltaTime;
}
}

注意
public Vector3 ver = transform.right; //向量 代表方向public Vector3 ver = Vector3.right; //向量 代表方向 是错误的:

这表明正在类的字段初始化过程中,尝试使用了非静态的 Component.transform。在C#中,字段初始化阶段要求所有引用都是静态的或常量。

解决这个问题的一种方式是将 ver 字段的初始化移到 Start 方法中。在 Start 方法中,可以访问 transform

public class ConveyorBelt : MonoBehaviour
{
public float MoveSpeed = 4; // 传送带的移动速度
public Vector3 ver; // 向量 代表方向

private void Start() // 在脚本启动时调用方法
{
// 在 Start 方法中初始化 ver
ver = -transform.right;
}

// 当其他物体进入触发器并保持在触发器中时调用
private void OnTriggerStay(Collider other)
{
// 通过向量 ver 和 MoveSpeed 来移动物体的位置
// Time.deltaTime 用于平稳处理移动,确保在不同设备上表现一致
other.transform.position += ver * MoveSpeed * Time.deltaTime;
}
}

通过将初始化移到 Start 方法中,可以确保在 transform 可以正确使用的时候进行初始化,从而避免了字段初始化的限制。

6. public Vector3 ver = Vector3.right;public Vector3 ver = -transform.right; 的区别

这两行代码分别初始化了 ver 变量为不同的向量,有着不同的含义:

  1. public Vector3 ver = Vector3.right;
  • 这行代码将 ver 初始化为世界坐标系中的正 X 轴的单位向量。
  • 无论物体自身的朝向如何,ver 始终指向全局坐标系中的正 X 轴方向。
  1. public Vector3 ver = -transform.right;
  • 这行代码将 ver 初始化为物体自身坐标系中的负 X 轴的单位向量。
  • 根据物体的朝向,ver 会指向物体左方向,因为负 X 轴是右手坐标系中的左方向。

所以,主要的区别在于这两个向量所处的坐标系。如果希望传送带的方向是世界坐标系中的某个方向,使用 Vector3.right 就足够了。如果想要根据物体的朝向来确定传送带的方向,可以使用 -transform.right

在具体应用中,选择哪个取决于需求。如果传送带的方向不受物体朝向的影响,使用 Vector3.right 可能更直观。如果希望传送带的方向与物体的朝向有关,使用 -transform.right 可能更适合。

7. C#字段

在C#中,字段(field)是类的成员变量,它们用于存储类或结构体的数据。字段是类的一部分,用于表示对象的状态。字段可以是各种基本数据类型(如整数、浮点数等)或引用类型(如类的实例)。

在C#中,类的字段有一些初始化的规则:

  1. 静态字段的初始化: 静态字段是属于类本身而不是类的实例的。静态字段可以在声明时进行初始化,也可以在静态构造函数中初始化。静态字段的初始化是在类加载的过程中进行的。
public class Example
{
public static int staticField = 10; // 静态字段的初始化
}
  1. 实例字段的初始化: 实例字段是属于类的实例的。在类的构造函数中对实例字段进行初始化。这是在每次创建类的实例时进行的。
public class Example
{
public int instanceField;

public Example()
{
instanceField = 20; // 实例字段的初始化
}
}

  1. 字段初始化阶段要求的静态或常量引用: 当在字段声明时直接赋值,这个赋值在初始化阶段进行。在这个阶段,C#规定初始化的值必须是静态的(在编译时就能确定的)或常量的。这是为了确保在编译时就能够确定类的初始状态。
public class Example
{
// 这里的常量引用是允许的
public const int ConstantValue = 30;

// 这里的静态字段引用是允许的
public static int StaticFieldValue = 40;

// 这里的实例字段引用是不允许的(会导致 CS0236 错误)
public int instanceField = StaticFieldValue;
}

总的来说,这些规则有助于确保在程序的执行过程中,类和对象的状态始终处于合理的初始状态。如果允许在字段初始化阶段使用非静态的引用,那么可能会导致不确定的行为,因为这些引用的值可能在运行时才能确定。

8. 传送带上物体移动的方式

如果有多个传送带,每个传送带上都有多个物体需要移动,可以考虑以下几种方式:

  1. 使用多个脚本

为每个传送带创建一个独立的脚本,脚本中处理该传送带上的物体移动逻辑。这样,可以为每个传送带独立设置移动速度和方向。

// ConveyorBeltScript1.cs
public class ConveyorBeltScript1 : MonoBehaviour
{
public float MoveSpeed = 4;

private void OnTriggerStay(Collider other)
{
other.transform.position += -transform.right * MoveSpeed * Time.deltaTime;
}
}

// ConveyorBeltScript2.cs
public class ConveyorBeltScript2 : MonoBehaviour
{
public float MoveSpeed = 2;

private void OnTriggerStay(Collider other)
{
other.transform.position += transform.forward * MoveSpeed * Time.deltaTime;
}
}
// ... 另外两个传送带的脚本类似 ...
  1. 使用参数化的脚本

将脚本参数化,以便一个脚本可以适用于多个传送带。这样只需要一个脚本,但可以在每个传送带上调整参数。

// ConveyorBeltScript.cs
public class ConveyorBeltScript : MonoBehaviour
{
public float MoveSpeed = 4;
public Vector3 MoveDirection = -Vector3.right;

private void OnTriggerStay(Collider other)
{
other.transform.position += MoveDirection * MoveSpeed * Time.deltaTime;
}
}

然后,将这个脚本附加到每个传送带上,并在每个传送带上调整 MoveSpeedMoveDirection

  1. 传送带作为子物体:

如果多个传送带共享相似的行为,可以将传送带作为一个空的父物体,然后将每个传送带的物体作为子物体。在这种情况下,移动传送带会影响所有子物体。

// ConveyorBeltScript.cs
public class ConveyorBeltScript : MonoBehaviour
{
public float MoveSpeed = 4;

private void OnTriggerStay(Collider other)
{
other.transform.position += -transform.right * MoveSpeed * Time.deltaTime;
}
}

每个传送带的物体都成为传送带的子物体。这样,当移动传送带时,所有的子物体都会跟着移动。