一、准备工作
1.创建项目
2.创建示例场景
a.创建3d ——Plane(地面)(0,0,0)和Sphere(游戏对象)(0,0.5,0),Sphere添加拖尾组件TrailRenderer
b.创建脚本 MovingSphere ——该脚本挂载到Sphere上
二、需求如下
1.将带有尾迹的球体放在平面上。
2.根据玩家输入定位球体。
3.控制速度和加速度。
4.限制球体的位置并使其从边缘反弹。
三、废话不多说直接上代码
public class MovingSphere : MonoBehaviour
{
// 使用SerializeField特性使得私有字段可以在Unity编辑器中显示,Range特性限制字段的值在指定范围内,Tooltip特性为字段添加提示信息
[SerializeField, Range(0f, 100f), Tooltip("最大速度")]
private float maxSpeed = 10f; // 最大速度
[SerializeField, Range(0f, 100f), Tooltip("最大加速度")]
private float MaxAcceleration = 10f; // 最大加速度
[SerializeField, Tooltip("活动范围(矩形)")]
private Rect allowedArea = new Rect(-5f, -5f, 10f, 10f); // 允许的活动范围,一个矩形区域
[SerializeField, Range(0f, 1f), Tooltip("反弹量")]
private float bounciness = 0.5f; // 反弹系数,用于计算碰撞后的反弹速度
/// <summary>
/// 当前速度
/// </summary>
Vector3 velocity; // 当前速度向量
private void Update()
{
Vector2 playerInput; // 玩家输入向量
playerInput.x = Input.GetAxis("Horizontal"); // 获取水平轴输入
playerInput.y = Input.GetAxis("Vertical"); // 获取垂直轴输入
playerInput = Vector2.ClampMagnitude(playerInput, 1f); // 将输入向量的长度限制为1,确保输入是单位向量
// 计算加速度和期望速度,但这里似乎有误,因为加速度和期望速度都使用了maxSpeed而不是MaxAcceleration,且方向计算也有误
// 正确的加速度计算应该基于MaxAcceleration和玩家输入方向
// 下面的代码只是简单地将玩家输入方向乘以maxSpeed来模拟“期望速度”,这并不是真正的加速度计算
Vector3 acceleration = new Vector3(playerInput.x, transform.y, playerInput.y) * maxSpeed; // 这里应该是加速度,但计算方式有误
Vector3 desiredVelocity = new Vector3(playerInput.x, transform.y, playerInput.y) * maxSpeed; // 期望速度,同样计算方式有误
float maxSpeedChange = MaxAcceleration * Time.deltaTime; // 每帧允许的最大速度变化量
// 平滑过渡到期望速度
velocity.x = Mathf.MoveTowards(velocity.x, desiredVelocity.x, maxSpeedChange);
velocity.z = Mathf.MoveTowards(velocity.z, desiredVelocity.z, maxSpeedChange);
// 根据当前速度计算位移
Vector3 displacement = velocity * Time.deltaTime;
Vector3 newPosition = transform.localPosition + displacement; // 计算新位置
// 检查新位置是否在允许的活动范围内,并处理碰撞反弹
if (newPosition.x < allowedArea.xMin)
{
newPosition.x = allowedArea.xMin; // 限制在左边界
velocity.x = -velocity.x * bounciness; // 反弹
}
else if (newPosition.x > allowedArea.xMax)
{
newPosition.x = allowedArea.xMax; // 限制在右边界
velocity.x = -velocity.x * bounciness; // 反弹
}
if (newPosition.z < allowedArea.yMin)
{
newPosition.z = allowedArea.yMin; // 限制在下边界(注意:Rect的yMin和yMax对应的是z轴的最小和最大值,因为Unity中Z轴通常是垂直的)
velocity.z = -velocity.z * bounciness; // 反弹
}
else if (newPosition.z > allowedArea.yMax)
{
newPosition.z = allowedArea.yMax; // 限制在上边界
velocity.z = -velocity.z * bounciness; // 反弹
}
transform.localPosition = newPosition; // 更新位置
}
}