【Unity开发】Rigidbody中Body Type属性


🐾 个人主页 🐾

阿松爱睡觉,横竖醒不来 🏅你可以不屠龙,但不能不磨剑🗡


文章目录

一、前言

在Unity的物理系统中,无论是3D还是2D,RigidbodyBody Type有三种类型,每种类型都有不同的物理行为和适用场景。

三种Body Type类型:Dynamic(动态类型)Kinematic(运动学类型)Static(静态类型)

先来详细看下对比表格

特性 Dynamic Kinematic Static
受重力影响
受外力影响
可代码控制
可碰撞检测
可推动其他物体
被其他物体推动
性能消耗 中等 最低
可休眠

下面分别具体的看下各个类型值的具体讲解和代码实例。(以2D世界为例------Rigidbody2D )

二、Dynamic(动态类型)

Dynamic是Unity开发中最常用的类型,完全受物理引擎的控制,主要有一下特性:

特性:

  • ✅ 受重力影响
  • ✅ 受外力作用(AddForce等)
  • ✅ 与其他碰撞体发生碰撞
  • ✅ 速度和质量影响运动
  • ✅ 可以休眠以优化性能

代码示例:

csharp 复制代码
public class DynamicBodyExample : MonoBehaviour
{
    private Rigidbody2D rb;
    
    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        rb.bodyType = RigidbodyType2D.Dynamic;
        
        // 动态物体可以施加力
        rb.AddForce(Vector2.up * 10f, ForceMode2D.Impulse);
        rb.gravityScale = 1f; // 受重力影响
    }
    
    void Update()
    {
        // 玩家控制
        if (Input.GetKey(KeyCode.RightArrow))
        {
            rb.AddForce(Vector2.right * 5f);
        }
    }
}

应用场景:

  • 玩家角色
  • 敌人NPC
  • 可交互的物体(箱子、球等)
  • 发射的炮弹
  • 任何需要物理交互的物体

三、Kinematic(运动学类型)

这个类型可以通过代码控制运动,不受物理力影响,但可以影响其他物体。

特性:

  • ❌ 不受重力影响
  • ❌ 不受外力影响
  • ✅ 通过代码控制运动(velocity、MovePosition)
  • ✅ 可以推动Dynamic物体
  • ❌ 不会因碰撞而改变运动方向

代码示例:

csharp 复制代码
public class KinematicBodyExample : MonoBehaviour
{
    private Rigidbody2D rb;
    public float moveSpeed = 5f;
    
    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        rb.bodyType = RigidbodyType2D.Kinematic;
        rb.gravityScale = 0f; // 明确设置不受重力
    }
    
    void Update()
    {
        // 通过代码直接控制运动
        Vector2 input = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
        rb.velocity = input * moveSpeed;
        
        // 或者使用MovePosition
        // Vector2 newPosition = rb.position + input * moveSpeed * Time.deltaTime;
        // rb.MovePosition(newPosition);
    }
    
    void OnCollisionEnter2D(Collision2D collision)
    {
        // 碰撞时不会自动改变运动,但可以推动Dynamic物体
        if (collision.gameObject.CompareTag("Box"))
        {
            Debug.Log("推动了箱子!");
        }
    }
}

应用场景:

  • 平台游戏中的移动平台
  • 玩家控制的角色(如果需要精确控制)
  • 电梯、传送带
  • 通过代码精确控制的物体
  • 需要推动其他物体但自身运动不受物理影响的物体

四、Static(静态类型)

完全静止的物体,性能最优,处于睡眠状态,性能开最小,但是只能用于一些静止不动的物体上。

特性:

  • ❌ 完全静止,无法移动
  • ❌ 不受任何物理影响
  • ✅ 可以与Dynamic物体碰撞
  • ✅ 最佳性能(物理引擎不需要计算其运动)
  • ❌ 运行时无法改变位置

代码示例:

csharp 复制代码
public class StaticBodyExample : MonoBehaviour
{
    void Start()
    {
        Rigidbody2D rb = GetComponent<Rigidbody2D>();
        rb.bodyType = RigidbodyType2D.Static;
        
        // 静态物体无法在运行时移动
        // rb.velocity = Vector2.zero; // 无效
        // rb.AddForce(Vector2.right); // 无效
    }
    
    void OnCollisionEnter2D(Collision2D collision)
    {
        // 仍然可以检测到碰撞
        if (collision.gameObject.CompareTag("Player"))
        {
            Debug.Log("玩家撞到了静态物体");
        }
    }
}

应用场景:

  • 地形、墙壁
  • 静止的障碍物
  • 建筑物
  • 任何永远不会移动的物体

五、实际应用场景示例

(一)平台游戏角色控制

csharp 复制代码
public class PlatformerPlayer : MonoBehaviour
{
    private Rigidbody2D rb;
    public bool useDynamicPhysics = true;
    
    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        
        if (useDynamicPhysics)
        {
            // 使用Dynamic:真实的物理感觉,但控制较难
            rb.bodyType = RigidbodyType2D.Dynamic;
            rb.gravityScale = 3f;
            rb.freezeRotation = true; // 防止旋转
        }
        else
        {
            // 使用Kinematic:精确控制,但物理感较弱
            rb.bodyType = RigidbodyType2D.Kinematic;
            rb.gravityScale = 0f;
        }
    }
    
    void Update()
    {
        float moveInput = Input.GetAxis("Horizontal");
        
        if (rb.bodyType == RigidbodyType2D.Dynamic)
        {
            // Dynamic控制:施加力
            rb.AddForce(new Vector2(moveInput * 10f, 0));
        }
        else
        {
            // Kinematic控制:直接设置速度
            rb.velocity = new Vector2(moveInput * 5f, rb.velocity.y);
        }
        
        // 跳跃
        if (Input.GetKeyDown(KeyCode.Space) && IsGrounded())
        {
            if (rb.bodyType == RigidbodyType2D.Dynamic)
            {
                rb.AddForce(Vector2.up * 8f, ForceMode2D.Impulse);
            }
            else
            {
                rb.velocity = new Vector2(rb.velocity.x, 8f);
            }
        }
    }
    
    bool IsGrounded()
    {
        // 地面检测逻辑
        return Physics2D.Raycast(transform.position, Vector2.down, 0.1f);
    }
}

(二)移动平台系统

csharp 复制代码
public class MovingPlatform : MonoBehaviour
{
    private Rigidbody2D rb;
    public Vector2[] waypoints;
    public float speed = 2f;
    private int currentWaypoint = 0;
    
    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        rb.bodyType = RigidbodyType2D.Kinematic; // 必须使用Kinematic
    }
    
    void FixedUpdate()
    {
        // 移动到下一个路径点
        Vector2 target = waypoints[currentWaypoint];
        Vector2 newPosition = Vector2.MoveTowards(rb.position, target, speed * Time.fixedDeltaTime);
        rb.MovePosition(newPosition);
        
        // 检查是否到达路径点
        if (Vector2.Distance(rb.position, target) < 0.1f)
        {
            currentWaypoint = (currentWaypoint + 1) % waypoints.Length;
        }
    }
    
    void OnCollisionEnter2D(Collision2D collision)
    {
        // 让站在平台上的物体随平台移动
        if (collision.gameObject.CompareTag("Player"))
        {
            collision.transform.SetParent(transform);
        }
    }
    
    void OnCollisionExit2D(Collision2D collision)
    {
        if (collision.gameObject.CompareTag("Player"))
        {
            collision.transform.SetParent(null);
        }
    }
}

(三)动态切换Body Type

csharp 复制代码
public class SwitchBodyType : MonoBehaviour
{
    private Rigidbody2D rb;
    
    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
    }
    
    // 切换到Dynamic(变成物理物体)
    public void MakeDynamic()
    {
        rb.bodyType = RigidbodyType2D.Dynamic;
        rb.gravityScale = 1f;
        rb.velocity = Vector2.zero;
    }
    
    // 切换到Kinematic(变成可控制物体)
    public void MakeKinematic()
    {
        rb.bodyType = RigidbodyType2D.Kinematic;
        rb.velocity = Vector2.zero;
    }
    
    // 切换到Static(变成静态障碍物)
    public void MakeStatic()
    {
        rb.bodyType = RigidbodyType2D.Static;
    }
    
    // 示例:当物体落地后变成静态,比如掉地上就失效捡不起来的物体
    void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.gameObject.CompareTag("Ground"))
        {
            // 延迟后变成静态
            Invoke("BecomeStatic", 2f);
        }
    }
    
    void BecomeStatic()
    {
        MakeStatic();
        Debug.Log("物体已静止");
    }
}

六、选择指南

  1. 需要真实物理效果 → 选择 Dynamic
  2. 需要精确代码控制 → 选择 Kinematic
  3. 完全静止的物体 → 选择 Static
  4. 移动平台/电梯 → 必须使用 Kinematic
相关推荐
winlife_2 小时前
AI 怎么验证 Unity PlayMode 行为:截图 + 输入模拟的完整闭环
人工智能·unity·游戏引擎·ai编程·claude·playmode
CandyU24 小时前
Cursor AI Unity
unity
LF男男4 小时前
Bullect.cs(bullet)——子弹基类
unity
mxwin21 小时前
unity shader中 ddx ddy是什么
unity·游戏引擎·shader
郝学胜-神的一滴1 天前
[简化版 GAMES 101] 计算机图形学 08:三角形光栅化上
c++·unity·游戏引擎·godot·图形渲染·opengl·unreal
nnsix1 天前
Unity ILRuntime 笔记
unity·游戏引擎
nnsix1 天前
Unity API 兼容的 .NET Standard 2.1 和 .NET Framework 区别
unity·游戏引擎·.net
mxwin1 天前
Unity Shader 制作半透明物体 使用多Pass提前写入深度的方式 避免穿模
unity·游戏引擎
nnsix1 天前
Unity HybridCLR 笔记
笔记·unity·游戏引擎