当前位置:   article > 正文

Unity-BattleStar丨8. 物理引擎Rigidbody组件、Collider组件、Raycast_physics.raycast和collider的性能

physics.raycast和collider的性能

游戏中物理引擎用于模拟真实世界物理环境效果,要实现游戏对象的物理行为,Rigidbody(刚体)组件是必不可少的,当挂载该组件之后,物体立刻受到重力等物理效果影响。如果对象身上还挂载着Collider(碰撞)组件,那么该对象还受到碰撞物理效果影响,例如游戏中的被车撞飞

 

一、Rigidbody组件

Rigidbody组件Unity Manual介绍:Rigidbody

力的效果展示是由Rigidbody组件实现的,只有拥有该组件,物体才会进行力的计算。由Unity Manual我们可知道Rigidbody可实现的功能有哪些

 

1、组件名称释义

1). Mass:质量,kg,并不是重量mg=N

2). Drag:空气阻力

3). Angular Drag:角旋转阻力

4). Use Gravity:用于确认物体是否受重力影响,如果不勾选该项,则物体不受地心引力影响,不再下坠。但该物体还受其他物理效果影响

5). Is Kinematic:物体不受任何物理效果影响,即使我们通过脚本给它赋予很大的力,也不会移动,只能通过Transform来改变其位置。这通常用于玩家的移动,即不使用力来移动物体,也希望物体进行物理计算的情况,这种运动方式称为“动力学(Kinematic)运动”。

        如果该属性设置为true表示该物体运动状态不受外力,碰撞和关节的影响,而只受到动画以及附加在物体上的脚本影响,但是该物体仍然能改变其他物体运动状态,例如游戏中倒下的敌人始终不动 ,就是利用这个不受外力影响的属性,但它也能反馈给其他与他碰撞到的物体一个反作用力,前提是与他碰撞的物体身上要有Rigidbody组件,否则无法产生力的效果(当刚体开启 IsKinematic时,刚体不再参与物理引擎的力计算,如果和他碰撞的物体还没有力,自然就不能计算出碰撞结果)

        a、b都有Collider、Rigidbody组件,a开启Is K inematic,b不开启。a撞b,b动;b撞a,b受反作用力动,a不动

6). Constraints:是否约束该物体在X、Y、Z方向的移动或旋转

 

2、给游戏对象整体施加某个方向的力 AddForce()

Unity Scripting API:Rigidbody.AddForce    ForceMode

我们可通过C#脚本方式给物体施加力

  1. using UnityEngine;
  2. public class CubeAddForce : MonoBehaviour {
  3. private Rigidbody myRigidbody;
  4. void Start () {
  5. myRigidbody = GetComponent<Rigidbody>();
  6. myRigidbody.AddForce(new Vector3(0, 10, 0), ForceMode.Impulse);
  7. }
  8. }

当然,代码中的力的方向我们也可写成

AddForce(Vector3.up*10,ForceMode.Impulse)

注意:Vector3(0,10,0)要加new,Vector3.up不用

附单位向量代码

  1. Vector3.up (0,1,0)
  2. Vector3.down (0,-1,0)
  3. Vector3.left (-1,0,0)
  4. Vector3.right (1,0,0)
  5. Vector3.forward (0,0,1)
  6. Vector3.back (0,0,-1)

 

ForceMode有四个属性:

a、Force:给Rigidbody添加一个可持续的力,受Mass影响,写在Update()等接口中

b、Acceleration:给Rigidbody添加一个可持续的加速度,忽略Mass影响,可在Start()接口

c、Impulse:立即给Rigidbody添加一个冲力,受Mass影响,可在Start()接口

d、VelocityChange:立即给Rigidbody添加速度,忽略Mass影响,写在Update()等接口中

不考虑其他力,仅考虑重力情况下,在Update中添加的力,并不是每帧调用Force会使物体受到的力处于叠加状态,而是遵循牛顿定律,看该力与物体重力关系,相等时则处于平衡状态,其他情况也遵循牛顿定律F-mg=ma

但不受重力影响的力,不断的调用,没有重力的平衡,只能会使物体受到的力叠加地越来越大,直至飞了出去

 

3、在指定位置施加力  AddForceAtPosition()

AddForceAtPosition(Vector3 Force,Vector3  Position,ForceMode)

在指定位置施加力实现特定效果。

myRigidbody.AddForceAtPosition(Vector3.up, new Vector3(1,0,1),ForceMode.Force);

 

4、实战:模仿手雷爆炸效果 AddExplosionForce()

AddExplosionForce(float explosionForce,Vector3 explosionPosition,float explosionRadius,float upwardsModifier,ForceMode mode)

float explosionForce:爆炸力

Vector3 explosionPosition:爆炸中心位置

float explosionRadius:爆炸半径

float upwardsModifier:调节爆炸出现的位置,使其看起来像掀起对象。默认从爆炸中心到刚体的质量中心力的方向是线性,如果upwardsModifier是非0值,该方向将通过减去中心点Y轴的值修改。例如:如果该值为2,那么爆炸出现在实际位置中心点2单位以下。使用这个参数,可轻易使爆炸似乎把物体扔到空中,这往往比单纯的外力更具戏剧性效果

ForceMode mode:力模式,同上2描述

 

思路:爆炸的力位置是从手雷中心开始的,因此力的位置在手雷中心;

        爆炸是瞬间发生而不是持续发生的,因此要写在Start接口中();

        爆炸力模式应为瞬间力,而不是持续发生,因此要力的模式应该是Impulse

  1. using UnityEngine;
  2. public class CubeAddForce : MonoBehaviour {
  3. private Rigidbody myRigidbody;
  4. private void Start()
  5. {
  6. myRigidbody = GetComponent<Rigidbody>();
  7. myRigidbody.AddExplosionForce(20, new Vector3(0,0.5f,0), 5, 0, ForceMode.Impulse);
  8. }
  9. }

 

cube中心是(0,0.5,0),我们设置的爆炸中心也是(0,0.5,0),我们可以看到,运行时在cube中心的爆炸,使其向上飞了出去。当我们将爆炸中心调整到(0,0.51,0)时,爆炸力在cube质心点之上,cube无法移动。同时我们也发现,周围的物体无法受中心cube影响而移动,这是因为力没传到周围物体上。

 

 

二、Collider组件

物体运动轨迹改变有两个方式,碰撞或代码。上例没有发生碰撞,力无法传递过去,但没碰撞我们就无法传递力了吗?也可以!通过物理引擎Collider组件的代码,Physics.OverlapSphere(Vector3 position,float radius)方法返回带有Collider的对象,我们只需要遍历他们并给他们的Rigidbody组件施加爆炸位置的力就好了,这当然是要有Collider组件才能实现

注意:组件类型定义变量有GetComponent<>()方法,object型变量不具备该方法

        为什么要检测是否拥有Rigidbody组件?因为只有拥有该组件,物体才会进行力的计算。力才有地方去赋值。有Collider组件,才额外进行碰撞计算

  1. using UnityEngine;
  2. public class CubeAddForce : MonoBehaviour {
  3. private Rigidbody myRigidbody;
  4. void Update()
  5. {
  6. if (Input.GetKeyDown(KeyCode.A))
  7. {
  8. myRigidbody = GetComponent<Rigidbody>();
  9. myRigidbody.AddExplosionForce(20, new Vector3(0, 0.51f, 0), 5, 0, ForceMode.Impulse);
  10. Collider[] colliders = Physics.OverlapSphere(transform.position, 5);
  11. //Collider[] colliders = Physics.OverlapSphere(new Vector3(0,0,0), 5);
  12. //以pointBottom为底部半圆圆心,PointTop为顶部半圆圆心,radius为半径,连接起来构成一个胶囊体
  13. Physics.OverlapCapsule(pointBottom, pointTop, radius, LayerMask);
  14. foreach(Collider obj in colliders)
  15. {
  16. if (obj.GetComponent<Rigidbody>() != null) //只有组件变量才有GetComponent<>()方法,因此object型变量自然不具备该方法了
  17. obj.GetComponent<Rigidbody>().AddExplosionForce(20, new Vector3(0, 0.5f, 0), 5, 2, ForceMode.Impulse);
  18. }
  19. }
  20. }
  21. }

 

三、Raycast

发射射线,检测一定范围内的物体,返回该物体

Physics.Raycast(Vector3 origin,Vector3 direction,out RaycastHit hitinfo,float maxDistance)

Vector3 origin:射线起点

Vector3 direction:射线方向

out RaycastHit hitinfo:返回检测距离内检测到的物体

float maxDistance:最大检测距离

 

此例我们用Physics.Raycast()方法检测10m距离内的物体。我们先定义RaycastHit类型的变量,用于承载该方法检测返回的物体,当我们按下B键,若距离小于5m,则给它施加一个向上的力

  1. using UnityEngine;
  2. public class CubeAddForce : MonoBehaviour
  3. {
  4. RaycastHit hit;
  5. void Update()
  6. {
  7. if (Input.GetKeyDown(KeyCode.B))
  8. {
  9. if (Physics.Raycast(transform.position, new Vector3(0, -1, 0), out hit, 10f))
  10. {
  11. if (hit.distance < 5)
  12. GetComponent<Rigidbody>().AddForce(Vector3.up*10,ForceMode.Impulse);
  13. }
  14. }
  15. }
  16. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/105106
推荐阅读
相关标签
  

闽ICP备14008679号