Unity基础(12)-物理系统

2020-06-02 15:06:37 浏览数 (1)

1.什么是Unity物理系统

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

2.什么是刚体

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

3.Unity中的刚体组件

刚体组件

代码语言:javascript复制
参数说明
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-方法

方法

代码语言:javascript复制
添加一个力到刚体,参考世界坐标(瞬时)
�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.小练习

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

代码语言:javascript复制
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.封装

使用刚体移动封装的脚本

代码语言:javascript复制
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);
    }
}

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

代码语言:javascript复制
 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.力场组件

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

力场组件

代码语言:javascript复制
代码添加
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);

0 人点赞