Unreal Engine 4 物理模拟之物理碰撞、重叠与射线检测

原创 2016年08月31日 10:50:43

1、碰撞组件基本属性

碰撞组件的属性如图

这里写图片描述

  • 属性简要介绍:
  • Simulation Generates Hit Events:是否对碰撞事件进行通知
  • Phys Material Override:指定该Mesh的物理材质
  • Generate Overlap Events:是否对重叠事件进行通知
  • Collision Presets:碰撞预设
    • Collision Enabled:
      • No Collision:无碰撞
      • Query Only(No Physics Collision):仅响应踪迹碰撞,无物理碰撞
      • Physics Only(No Query Collision):仅响应物理碰撞,无踪迹碰撞
      • Collision Enabled(Physics and Query):同时响应物理碰撞和踪迹碰撞
  • Object Type:表示当前Mesh的对象类型(用于区别场景的Mesh类型,以便进行不同的碰撞响应)
  • Collision Responses:碰撞响应设置
    • Trace Responses:踪迹响应
      • Trace Channel Setting:踪迹响应的相关设置,通常用于射线的碰撞检测。假若现在有一束对Visibility通道进行检测的射线穿过该物体时,如该Mesh的Visibility选择为Block,将会触发碰撞事件,如该Mesh的Visibility选择为Ignore,那么将不会触发碰撞事件。
    • Object Responses: 对象响应
      • Object Type Setting:对象相应的相关设置,可用于射线检测,不同Mesh之间的物理交互等。假若现在有两个Cube(Object Type均为WorldStatic)迎面相撞,那么当Cube1和Cube2的对象响应下的WorldStatic均设置为Block时,两个Cube会相互阻挡对方。否则将会互相穿过对方。
  • Use CCD:是否针对该对象应用连续碰撞检测,增加检测的准确度。
  • Always Create Plysics State:是否总是创建物理状态(它的碰撞属性、质量、休眠等)。设置为真时可减少计算对象的物理状态的性能消耗来提高游戏性能。
  • Multi Body Overlap:如果此值为true,如重叠的物理刚体为多刚体组件,则此组件将对每个重叠的物理刚体将生成单独的重叠。设想一下骨架物理资源,具有其独立的碰撞形状。启用该项后,角色的手将生成 自己 的重叠事件。从而对所报告的内容及特定情况下应该怎么做有更多的控制。
  • Check Async Scene On Move:如果该项设置为 真 ,那么组件将在两个物理场景(同步和异步)中都查找碰撞。异步场景主要由可破坏网格物体的破碎块使用。
  • Trace Complex On Move:如果该项设置为 真, 扫过该组件的对象将在运动时跟踪复杂碰撞。复杂碰撞简而言之就是基于每个面的碰撞,而简单碰撞则是您的球体、胶囊体、盒体及生成的凸面体形状。
  • Return Material on Move:设置该项为 真 将返回物理材质到 Hit Info(碰撞信息) 中。

2、物理碰撞、重叠与包围盒

  • 有如图所示两个物理Mesh: Cube、Terrain
    这里写图片描述

2.1碰撞

  • 设置cube相关组件属性
    这里写图片描述
    • 启用Cube的物理模拟,使用重力。这样Cube将会受到重力而掉落。
    • 将Collision Enabled设置为Collision Enabled
    • 给Cube设置一个对象类型PhysicsBody(根据抽象逻辑设置)
    • 将对象响应类型(Object Type)的WorldStatic(Terrain的对象类型)设置为Block
  • 设置Terrain相关组件属性
    这里写图片描述
    • 将Collision Enabled设置为Collision Enabled
    • 给Terrain设置一个对象类型WorldStatic
    • 将对象响应类型的PhysicsBody(Cube的对象类型)设置为Block
  • 运行游戏
    这里写图片描述
    • 发现Cube落在了Terrain上面而没有穿过Terrain,是因为他们彼此设置了阻挡(Block)对方。
    • 由于Cube设置了Simulation Generates Hit Events为True,我们可以对该Mesh(Cube)使用如下方法进行事件响应。
//假设CubeMesh就是上图的Cube的UStaticMeshComponent组件
UStaticMeshComponent CubeMesh;
    CubeMesh->OnComponentHit.AddDynamic(this, &YourClass::OnHit);
    //注意:用于虚幻4引擎回调的函数都应使用UFUNCTION()修饰
    /*OnHit函数签名为:*/
    UFUNCTION()
        void OnHit(class AActor* OtherActor, class UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit);

2.2重叠

  • 我们现在仅需要在2.1的基础上对Cube和Terrain的对象响应类型做出少许修改即可。
  • 对Cube作出如下图所示的修改
    这里写图片描述
  • 对Terrain做出如下图所示的修改
    这里写图片描述
  • 运行游戏
    这里写图片描述
    • 我们发现Cube已经穿过Terrain
    • 当Cube和Terrain同时设置Generate Overlap Events为True时,如果两者中有一个对象设置为阻挡对方,另一个设置为重叠对方(或者两者都设置为重叠对方),那么我们就可以对该Mesh(Cube和Terrain)通过如下方法进行事件响应。
//假设CubeMesh就是上图的Cube的UStaticMeshComponent组件
UStaticMeshComponent CubeMesh;
CubeMesh->OnComponentBeginOverlap.AddDynamic(this, &YourClass::OnBeginOverlap);
CubeMesh->OnComponentEndOverlap.AddDynamic(this,&YourClass::OnEndOverlap);
/*OnBeginOverlap和OnEndOverlap的函数签名为:*/
//开始重叠
UFUNCTION()
    void OnBeginOverlap(class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);
//结束重叠
UFUNCTION()
    void OnEndOverlap(class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);

2.3包围盒

  • 基本概念
    包围盒(Unity中常成为碰撞盒)常用语碰撞检测,基本思想是用体积稍大且特性简单的几何体(称为包围盒)来近似地代替复杂的几何对象。
  • 添加包围盒,打开Mesh编辑器如下图所示
    这里写图片描述
    • 下拉列表中是一些包围盒的形状,添加了包围盒的Mesh才能进行物理模拟。

3、射线的使用

3.1自定义踪迹通道、对象通道、预设

  • 打开碰撞设置面板
    这里写图片描述->这里写图片描述->这里写图片描述
  • 新建如下图所示的对象通道和踪迹通道
    这里写图片描述

  • Object Channel和Trace Channel的可自定义通道总数为18个

  • 打开项目的DefaultsEngine.ini文件
    这里写图片描述
    • DefaultsEngine.ini
      这里写图片描述
    • 自定义通道与ECollisionChannel枚举类型映射关系
      可以看到,每一个新建的通道对应了一个ECC_GameTraceChannel,我们找到枚举类型ECollisionChannel的定义,由此,我们可以获得该枚举类型下的枚举值和我们自己定义的通道的映射。
      这里写图片描述

3.2使用射线

  • 基本场景
    这里写图片描述
  • 对自定义通道进行宏定义
//自定义踪迹通道的宏定义
#define CubeChannel     ECollisionChannel::ECC_GameTraceChannel6
#define SphereChannel   ECollisionChannel::ECC_GameTraceChannel5;
#define CylinderChannel ECollisionChannel::ECC_GameTraceChannel4
//自定义对象通道的宏定义
#define  CubeObject     ECollisionChannel::ECC_GameTraceChannel3
#define SphereObject    ECollisionChannel::ECC_GameTraceChannel2
#define  CylinderObject ECollisionChannel::ECC_GameTraceChannel1
  • 射线检测基本参数初始化
    /*射线的长度*/
    #define MAXRAYDISTANCE 100000
    //以下代码是写在APlayerController子类下的片段

    UWorld world = this->GetWorld();
    /*获取鼠标在屏幕上的坐标*/
    FVector2D mousePosition(0, 0);
    this->GetMousePosition(mousePosition.X, mousePosition.Y);

    FHitResult hitInfo;
    FVector rayWorldOrigin;
    FVector rayWorldDirection;
    /*获得屏幕上的坐标在世界坐标系下的位置,方向*/
    UGameplayStatics::DeprojectScreenToWorld(this, mousePosition, rayWorldOrigin, rayWorldDirection);

    FCollisionQueryParams queryParamInfo(false);

3.2.1根据踪迹通道进行检测

  • LineTraceSingleByChannel是根据踪迹通道来响应的,因此我们仅需要对踪迹通道进行如下设置,以Sphere为例(Cylinder,Cube设置同理),对象通道对射线踪迹通道追踪是没有影响的,故在此不用设置。
    这里写图片描述
  • 代码如下
//You always can change this variable to CubeChannel/CylinderChanneletc.
    ECollisionChannel TraceChanel = SphereChannel;
    if (world!=nullptr)
    {
        world->LineTraceSingleByChannel(hitInfo, rayWorldOrigin, rayWorldDirection * MAXRAYDISTANCE, TraceChanel, queryParamInfo);
    }
  • 运行游戏
    这里写图片描述
    • 当鼠标放在Sphere上时,射线碰撞到了Sphere,放在其他位置时是没有反应的。

3.2.2根据对象通道进行检测

  • LineTraceSingleByObjectType是根据对象类型(Object Type)来进行响应的,因此我们仅需要对Object Type进行设置,以Cube为例(Sphere,Cylinder同理)
    这里写图片描述

  • 代码如下

    FCollisionObjectQueryParams traceObjectTypeInfo;
    //traceObjectTypeInfo.AddObjectTypesToQuery(CubeObject);
    //traceObjectTypeInfo.AddObjectTypesToQuery(SphereObject);
    if (FCollisionObjectQueryParams::IsValidObjectQuery(CubeObject))
    {
        traceObjectTypeInfo.AddObjectTypesToQuery(CubeObject);
        //此处添加你要追踪的对象类型
    }
    if (world!=nullptr)
    {
        world->LineTraceSingleByObjectType(hitInfo, rayWorldOrigin, rayWorldDirection * MAXRAYDISTANCE, traceObjectTypeInfo, queryParamInfo);
    }
  • 运行游戏
    这里写图片描述
    • 当鼠标移动到Cube上,射线检测到了Cube,鼠标放到其他位置是没有反应的,因为仅仅添加了CubeObject用于检测。

3.2.3根据预设进行检测

  • 新建自定义预设CustomQuery
    这里写图片描述
  • 设置Cylinder碰撞属性
    • LineTraceSingleByProfile相当于赋予了射线拥有自己的对象类型,故在此我们设置相应物体的对象类型响应下WorldStatic为阻挡(Block),在此以Cylinder为例(Cube、Sphere同理)
      这里写图片描述
  • 代码如下
FName profileName(TEXT("CustomQuery"));
    if (world != nullptr)
    {
        world->LineTraceSingleByProfile(hitInfo, rayWorldOrigin, rayWorldDirection * MAXRAYDISTANCE, profileName,queryParamInfo);
    }
  • 运行游戏
    这里写图片描述

    • 由于CustomQuery设置了阻挡CylinderObject和CubeObject,故可看到射线检测到了Cylinder2和Cube,由于我把Cylinder1的对象类型响应下的WorldStatic响应设置为Igore,故在此没有检测到Cylinder1.
  • 总结:以上讲述了虚幻4引擎的物理碰撞、重叠、射线检测部分。其中射线检测部分主要围绕UWorld下的LineTraceSingleByChannel、LineTraceSingleByObjectType、LineTraceSingleByProfile三种检测方法进行检测。同时,在使用c++编程时还应该注意自定义踪迹通道、对象通道时,DefaultsEngine.ini配置文件中的ECollisionChannel
    枚举值与自定义通道的映射关系,然后用宏定义进行声明以便于代码的可读性。

  • 源代码文件下载:
版权声明:本文为博主原创文章,未经博主允许不得转载。

UE4里启动物件的碰撞机制

在UE4里面有时候 会发现当某个静态物件拖拽上去后,并没有碰撞机制 如图所示: 人直接穿过去 其实很简单:一般在Mesh里面我们见到的是 Default默认的是Use Simple...

如何在Unreal里给角色绑定碰撞体

1. 在Personal里,往角色的SkeletonTree中合适的位置Add Socket。如果碰撞体要绑定到已经存在的Bone上,请略过此步骤。 2. CharacterBP的Component...

UE4的Collision与Physics

Collision和Physics都是各种Mesh的属性,和Unity3D很像,Collision和Physics是两个独立的Component,Collision仅仅掌管碰撞发生的检测和回调,而Ph...
  • zzk1995
  • zzk1995
  • 2015年10月10日 18:43
  • 5214

UE4模拟物理效果开关门

很久没有写文章了,最近一直在UE4和unity之间两头跑,对于一个unity出身的程序员来说,这是一种什么滋味啊。好了, 今天给大家讲一下如何在UE4种模拟开关门的效果,类似VR使用的动画开门的效果,...

虚幻4已免费 PhysX物理引擎有开源希望

NVIDIA的物理运算引擎PhysX一直都是目前最强大的物流引擎质疑,在《地铁:最后的曙光》以及《蝙蝠侠》等作品中发挥了巨大成效。甚至连最新的《巫师3》和《生化危机:启示录2》业绩将采用分。不过Phy...

开源的物理引擎

开源的物理引擎 用开源构建可信世界 M. Tim Jones, 顾问工程师, Independent author 简介: 图形赋予游戏一种视觉的吸引力,但是能够让游戏的世界鲜活起来的...

Unreal 入门-Collision和Physics,碰撞检测

Collision仅仅掌管碰撞发生的检测和回调,而Physics仅仅模拟碰撞发生之后位置速度等等的变化。 Collision 可以设置persets,里边的标签都是不同的碰撞处理逻辑。Col...
  • shidya
  • shidya
  • 2017年03月22日 23:55
  • 253

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

UE4蓝图碰撞检测解析

任意两个物体有碰撞的条件 ①一定是互相设置了Collision Preset。 ②至少有一个实体开启了simulate physics。   OnActorHit事件响应条件 ①事件所对应的物体必须开...

UE4的射线拾取

Ray-Trace作用于射线拾取。射线拾取主要相关 1.拾取函数是UWorld的多个方法。比如LineTraceSingle是单一拾取,拾取到一个之后就不继续穿透了,而LineTraceMulti会...
  • zzk1995
  • zzk1995
  • 2015年10月10日 00:23
  • 5740
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Unreal Engine 4 物理模拟之物理碰撞、重叠与射线检测
举报原因:
原因补充:

(最多只允许输入30个字)