我在网上查找如何创建一个没有rigidbody的角色控制器。 我想学习碰撞和移动的基础知识。 我在github上找到了一段代码,但我不能理解为什么使用vector2.dot,因为我们已经修改了距离了,而且为什么有两个Move()函数在fixedUpdate中。 如果只有一个Move()函数,系统就会崩溃。 我读了注释,但我不能完全理解它。 为什么会这样发生呢?

使用 System.Collections;

using System.Collections.Generic;

using UnityEngine;

[RequireComponent(typeof(Rigidbody2D), typeof(BoxCollider2D))]

public class PhysicsObject : MonoBehaviour
{

public float m_GravityModifier = 1f; // 我们可以设置重力值

public LayerMask m_Mask; // 障碍物遮罩

protected BoxCollider2D m_BoxCollider2D; // 必须用于boxcasting,需要知道其大小

protected Rigidbody2D m_Rigidbody2D; // 我们使用rigidbody.position来移动对象

protected Vector2 m_Velocity; // 速度向量

protected RaycastHit2D[] m_HitInfos = new RaycastHit2D[16]; // 物理盒子投射返回的信息

protected bool m_Grounded; // 如果地面正常为1,表示我们在地面上

protected const float m_ShellDistance = 0.01f; // 这个值使得碰撞器不会进入其他碰撞器

// Start是调用在第一帧更新之前

void Awake()
{

m_BoxCollider2D = GetComponent();

m_Rigidbody2D = GetComponent();

}

}

private void FixedUpdate()
{

m_Grounded = false;

// 物理定律:最后速度 = 初速度 + 加速度 * 时间差

// delta表示两个帧之间的时间差

m_Velocity += m_GravityModifier * Physics2D.gravity * Time.fixedDeltaTime;

// 位置变化 = 速度 * 时间差

Vector2 deltaPosition = m_Velocity * Time.fixedDeltaTime;

// 现在我们到了最痛苦的位置。 为什么有两个Move函数。 因为如果角色试图水平移动

// rigidbody.position会试图进入地面。 我们必须单独计算。

Vector2 moveHorizontal = Vector2.right * deltaPosition.x; // 水平移动向量

Move(moveHorizontal);

// 垂直移动向量

Vector2 moveVertical = deltaPosition.y * Vector2.up;

Move(moveVertical);

// 如果你删除两个Move函数并写一个Move(deltaPosition)你会看到什么意思。

}

void Move(Vector2 move)
{

float distance = move.magnitude;

// 移动起点

Vector2 origin = m_Rigidbody2D.position + m_BoxCollider2D.offset;

// 检测碰撞

int count = Physics2D.BoxCastNonAlloc(origin, m_BoxCollider2D.size, 0f, move, m_HitInfos, distance + m_ShellDistance, m_Mask);

// 检测碰撞后处理

for (int i = 0; i < count; i++)
{

Vector2 currentNormal = m_HitInfos[i].normal;

// 如果当前正常为1,表示我们在地面上

if (currentNormal.y == 1)
{

m_Grounded = true;

}

// 如果速度向量和当前正常向量的点积小于0,表示速度向量在当前正常向量的反方向

float project = Vector2.Dot(currentNormal, m_Velocity);

if (project < 0)
{

m_Velocity -= project * currentNormal;

}

// 修改距离

float modifiedDistance = m_HitInfos[i].distance - m_ShellDistance;

distance = modifiedDistance < distance ? modifiedDistance : distance;

}

// 移动角色

m_Rigidbody2D.position += move.normalized * distance;

}

}