【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
相关推荐
叶帆6 天前
【YFIOs】用C#开发硬件之设备上云
开发语言·unity·c#
久数君6 天前
AI三维建模工具“造形家”:地理场景三维化的高效解决方案
unity·glb·ai算法·ai三维建模工具·地图框选·造形家·城市建筑模型
会思考的猴子7 天前
Unity VFX 属性 Postion 和 TargetPostion
unity
hai3152475437 天前
九章编程法 · 猜数字游戏 (GW-BASIC 重构版) *
人工智能·microsoft·游戏引擎·游戏程序
心前阳光7 天前
Unity资源导入之自动化资源导入
unity·自动化·游戏引擎
心前阳光7 天前
Unity之2021.3.45f2c1发布安卓程序遇到的问题
android·unity·游戏引擎
纪纯7 天前
PicoVR Unity Integration SDK 3.4 常用交互API
unity·游戏引擎·vr·pico
龙智DevSecOps解决方案7 天前
3A 游戏优化技术栈:如何打通引擎级分析工具与 DevOps 持续集成管线?
unity·性能优化·游戏开发·技术美术·perforce·unrealengine
葛兰岱尔7 天前
从 SolidWorks 到 Three.js,从 Inventor 到 Unity——制造业CAD模型“几何-语义一体化“转换,不再是天方夜谭!
开发语言·javascript·unity
鼎艺创新科技7 天前
三维电子沙盘中OSGB倾斜摄影数据的加载与渲染
游戏引擎·cocos2d