【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 自动跑 PlayMode 回归测试:从 BUG 注入到自动判 FAIL 的完整闭环
人工智能·unity·bug·ai编程·mcp·回归测试·游戏测试
WarPigs18 小时前
游戏签到系统
unity
小拉达不是臭老鼠21 小时前
Unity中的UI系统之UGUI
学习·ui·unity
万兴丶21 小时前
Coplay适用于 Unity 的“Al 代理”使用指南
unity·游戏引擎·ai编程
魔士于安1 天前
Unity材质球大合集
unity·游戏引擎·材质
mxwin1 天前
Unity Shader 冰面 Shader 制作原理与流程
unity·游戏引擎·shader
玖玥拾1 天前
Cocos学习笔记:关卡系统、音频管理与物理控制
游戏引擎·cocos2d
小拉达不是臭老鼠1 天前
Unity中的UI系统之UGUI_登陆面板实现
ui·unity
郝学胜-神的一滴1 天前
[简化版 GAMES 101] 计算机图形学 11:频域·卷积·抗锯齿
c++·unity·图形渲染·opengl·three·unreal
玖玥拾2 天前
Cocos学习笔记:滚动视图、关卡系统与本地存储
游戏引擎·cocos2d