美文网首页Unity3d
Unity基础(12)-物理系统

Unity基础(12)-物理系统

作者: 元宇宙协会 | 来源:发表于2018-02-03 20:56 被阅读192次

    1.什么是Unity物理系统

    Unity是一款3D引擎软件,内置NVIDIA PhysX物理引擎,使3D物体具备物理属性,产生物理效果。

    2.什么是刚体

    刚体使物体接受物理的控制,可以使物理实现移动
    刚体就是模拟现实物体的运动状态,物体添加刚体后将受重力影响,并可以与其他物体发生碰撞。
    Unity中两种刚体:
    1.普通刚体(影响自己也影响其他物体),如:3D角色,运动的车子等
    2.运动学刚体(Is Kinematic为 true, 自己不受物理引擎的驱动,但是会影响其他刚体)如:山体,房子等

    3.Unity中的刚体组件

    刚体组件
    参数说明
    Mass        质量
    Drag        位移阻力
    Angular Drag    角阻力
    Use Gravity     是否受重力影响
    Is Kinematic    是否为运动学刚体
    Interpolate     平滑物理运行的插值类型,该项用于控制刚体运动抖动情况
    None:没有差值
    Interpolater:内插值,基于前一帧的transform来平滑此次的transform
    Extrapolate:外插值,基于下一帧的trransform来平滑此次的transform
    Collision Detection 碰撞检测方式(枚举)控制避免高速运动的游戏对象穿过其他游戏对象昂而未发生碰撞
    Discrete:离散碰撞检测
    Continuous:连续碰撞检测:用于检测与动态碰撞体(带有rigidbody)碰撞,使用连续碰撞检测模式来检测与网格碰撞体的(不带rigidbody)碰撞。此模式用于连续动态碰撞检测的对象相碰撞的对象。如果不需要对快速运动的物体进行碰撞检测,请使用离散
    Continuous Dynamic : 连续动态碰撞检测。检测与采用来连续碰撞模式或连续动态碰撞模式对象的碰撞,一般用于检测快速运动的游戏对象
    Constraits  冻结位置和旋转
    

    4-方法

    方法
    添加一个力到刚体,参考世界坐标(瞬时)
    �AddForce (force : Vector3, mode : ForceMode = ForceMode.Force) : void�
    添加一个力到刚体,参考本地坐标(瞬时)
    � AddRelativeForce (force : Vector3, mode : ForceMode = ForceMode.Force) : void
    添加一个力矩到刚体,参考世界坐标(瞬时)
    �AddTorque (torque : Vector3, mode : ForceMode = ForceMode.Force) : void�
    添加一个力矩到刚体,参考本地坐标(瞬时)
    � AddRelativeTorque (torque : Vector3, mode : ForceMode = ForceMode.Force) : void
    
    说明在有阻力的作用下,物体会慢慢停下
    在position位置应用force力。作为结果这个将在这个物体上应用一个力矩和力(瞬时)。
    �AddForceAtPosition (force : Vector3, position : Vector3, mode : ForceMode = ForceMode.Force) : void
    
    ForceModel

    5.小练习

    让一个方块产生,左键下落,右键暂停效果

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class RigidbodyTest : MonoBehaviour {
    
        private Rigidbody r;
    void Start () {
           r = this.gameObject.AddComponent<Rigidbody>(); // 通过代码的方式添加刚体
            r.mass = 1;
            r.angularDrag = 0.0f;
            
        }
    public void RigidbodyGreat(bool IsTrue)
        {
            if (IsTrue)  // 表示IsTrue = yes;
            {
                r.isKinematic = true; // 设置当前游戏对象为运动学刚体
                // r.constraints = RigidbodyConstraints.FreezePositionY; //锁定当前刚体即刚体所在的游戏物体的Y轴
            }
            else {
                 r.isKinematic = false; 
                // r.constraints = RigidbodyConstraints.None; // 不锁定任何轴  
            }
        }
    
    void Update () {
            if (Input.GetMouseButtonDown(1))
            {
                RigidbodyGreat(true);  
            }
            if (Input.GetMouseButtonDown(0))
            {
                RigidbodyGreat(false);
            }
        }
    

    6.封装

    使用刚体移动封装的脚本

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class MoveControllerWithRighd {
    
        /// <summary>
        /// 判断游戏对象是否有刚体,如果没有自动添加,同时可以冻结的传入的物体旋转位置
        /// </summary>
        /// <param name="obj">判断的物体</param>
        /// <param name="rc">冻结的参数</param>
        /// <returns></returns>
        public static Rigidbody ObjIsHaveRid(GameObject obj,  RigidbodyConstraints rc)
        {
            Rigidbody r = ObjIsHaveRid(obj);
            r.constraints = rc;
            return r;
        }
    
        /// <summary>
        ///  判断游戏对象是否有刚体,如果没有自动添加
        /// </summary>
        /// <param name="obj">判断的对象</param>
        private static Rigidbody ObjIsHaveRid(GameObject obj)
        {
            Rigidbody r = obj.GetComponent<Rigidbody>();
            if (r == null)
            {
                r = obj.AddComponent<Rigidbody>();
            }
            return r;
        }
    
    
        /// <summary>
        ///  物体移动方法
        /// </summary>
        /// <param name="obj">移动的物体</param>
        public static void ObjMoveWithKey(GameObject obj,float speed)
        {
            KeyContro(KeyCode.W, obj, new Vector3(0, 0, speed));
            KeyContro(KeyCode.S, obj, new Vector3(0, 0, -speed));
            KeyContro(KeyCode.A, obj, new Vector3(-speed, 0, 0));
            KeyContro(KeyCode.D, obj, new Vector3(speed, 0, 0));
        }
    
        /// <summary>
        /// 按键控制方法
        /// </summary>
        /// <param name="key">控制的键</param>
        /// <param name="player">需要控制的对象</param>
        /// <param name="move">按键控制移动的方向</param>
        private static void KeyContro(KeyCode key, GameObject player, Vector3 move)
        {
            if (Input.GetKey(key))
            {
                RidMove(player, move, ForceMode.Force);
            }
        }
    
        /// <summary>
        /// 刚体的移动
        /// </summary>
        /// <param name="obj">要移动的对象</param>
        /// <param name="Move">移动的方向</param>
        /// <param name="m">力的模式</param>
        private static void RidMove(GameObject obj, Vector3 Move, ForceMode m)
        {
            // 耦合性
            obj.GetComponent<Rigidbody>().AddForce(Move, m);
        }
    }
    

    物体身上的脚本可以像下面一样调用

     public  GameObject Player;
        void Start () {
            Player = CreatObj(PrimitiveType.Cube,"PlayerA", new Vector3(0, 0.5f, 0));
            MoveControllerWithRighd.ObjIsHaveRid(Player, RigidbodyConstraints.FreezeRotation);
        }
    
    
        public  GameObject CreatObj(PrimitiveType p, string ObjName, Vector3 Pos)
        {
            GameObject obj = GameObject.CreatePrimitive(p);
            obj.name = ObjName;
            obj.transform.position = Pos;
            return obj;
        }
    
        void Update () {
            MoveControllerWithRighd.ObjMoveWithKey(Player,15f);
        }
    
    

    7.力场组件

    力场是一种为刚体快速添加恒定作用力的方法,使用与类似火箭发射的对象,起初没有很大的速度但是不断地加速

    力场组件
    代码添加
    ConstantForce cf = this.gameObject.AddComponent<ConstantForce>();
    cf.force = new Vector3(5, 0, 0);
    cf.relativeForce = new Vector3(5, 0, 0);
    cf.torque = new Vector3(5, 0, 0);
    cf.relativeTorque = new Vector3(5f, 0, 0);
    

    相关文章

      网友评论

        本文标题:Unity基础(12)-物理系统

        本文链接:https://www.haomeiwen.com/subject/rfcpzxtx.html