击退
本课属于 Coddy Unity 学习旅程的“物理与游戏玩法”单元。第 57 课,共 71 课。
击退就是把击中你的物体踢开:沿着从击打者到被击中物体的直线施加一次冲量。这个缓冲器会击退所有撞上它的物体:
[SerializeField] private float power = 8f;
void OnCollisionEnter(Collision collision)
{
Vector3 away = collision.transform.position - transform.position;
away.y = 0f;
collision.rigidbody.AddForce(away.normalized * power, ForceMode.Impulse);
}collision.transform.position - transform.position 指向从缓冲器到撞上它的物体的方向。将它的 y 设为 0,这样踢击就会保持水平;normalized 会让方向向量的大小保持不变,无论两个中心相距多远。ForceMode.Impulse 表示一次性的踢击:它会立刻将速度改变 power 除以质量的大小,因此质量为 2 的球飞出的速度是质量为 1 的球的一半。默认的 ForceMode.Force 适用于每一步都施加力,其效果只有一步的量,也就是小 50 倍。
只要没有东西覆盖速度,这次踢击就会持续生效。如果玩家的 FixedUpdate 在每一步都根据方向键设置 rb.linearVelocity,那么踢击效果会在一步后消失。因此,这样的脚本必须在受到击打后暂时不改动速度,或者用力来移动玩家。
挑战
中等让玩家按下 Space 触发冲击波。
- 当
Input.GetKeyDown(KeyCode.Space)时,遍历foreach (Collider hit in Physics.OverlapSphere(transform.position, radius)),跳过玩家自己的碰撞体。 - 对于每个
hit.TryGetComponent(out Rigidbody body),使用away = hit.transform.position - transform.position,并设置away.y = 0f。 - 调用
body.AddForce(away.normalized * power + Vector3.up * lift, ForceMode.Impulse);。
按下“开始”,然后在箱子之间按下 Space。接着点击“检查”。
亲手试试
using UnityEngine;
public class Shockwave : MonoBehaviour
{
[SerializeField] private float radius = 4f;
[SerializeField] private float power = 6f;
[SerializeField] private float lift = 2f;
void Update()
{
// 按下 Space 时:将 radius 范围内的每个 Rigidbody 推离玩家
}
}
物理与游戏玩法中的所有课
自己练习: Unity 在线编辑器