写在前面
这里介绍一下如何为Pawn定制自定义的运动组件。
一、新建一个运动组件C++类
- 需要在Editor中新建类,不要直接Visual Studio中新建;
- Pawn的运动组件继承自
UPawnMovementComponent
,需要勾选显示所有类才能找到;
- 初始时,头文件里面是什么都没有的,如下:
USlidePawnMovementComponent
的继承结构是:UObject
:最基本的类;UActorComponent
:最基本的Component类;UMovementComponent
:最基本的运动组件类;UNavMovementComponent
;UPawnMovementComponent
;USlidePawnMovementComponent
;
二、实现运动组件的功能
1. 头文件
- 为了实现自定义的移动方式,这里仅需要重写
TickComponent()
函数,如下:
- 这个函数是在
MovementComponent
类中定义的,如下:
2. cpp实现
- 为了让Pawn能够产生实时的移动,需要在每一帧中为Pawn更新位置,重写的
TickComponent()
函数就是执行每一帧中Component施加给Actor的动作,相当于在Actor中的void Tick(float DeltaTime)
函数; - 因此,在
TickComponent()
函数中需要把从外部设备输入的信号施加到Pawn上产生作用效果,实现如下:
- 一些注意的点如下:
- 如果运动组件没有挂载到某个Pawn上,或者运动组件没有对应施加运动的组件(默认是根组件),则
TickComponent()
不会进行具体的移动; - 这里的输入信号的传递用的是生产者-消费者模型,这是因为输入信号可能是同时发生的,但消费这些信号(也就是实际让Pawn运动起来)则需要一个个执行,因此用生产者-消费者模型而不是Unreal Engine08:Pawn的实现中的简单绑定到
CurrentVelocity
变量可以实现异步执行,也降低了输入和执行之间的耦合性; - 实现Pawn的运动仍然用的是位移 = 速度 * 时间的公式,和之前实现的无异;
- 为了实现Pawn撞向其他物体时的沿表明滑动效果,这也是该自定义运动组件的核心目的,这里需要调用
SlideAlongSurface()
函数来实现移动,而不是直接将当前Pawn的位置设置为某个地方; - 如果在试算的过程中发生了碰撞,则不会执行真正的移动的;
- 如果运动组件没有挂载到某个Pawn上,或者运动组件没有对应施加运动的组件(默认是根组件),则
三、在Pawn中使用自定义运动组件
1. 头文件
- 首先在头文件中定义运动组件,如下:
- 另外要重写
GetMovementComponent()
函数,因为默认的返回不是自定义的运动组件;
2. cpp实现
- 首先在构造函数中分配对象,如下:
-
另外要为运动组件初始化它所施加运动的组件;
-
这里是因为Pawn可以有很多组件,因此运动组件需要选其中一个来控制,也就是施加运动的对象不是Pawn而是另一个组件(组件得是
UScenceComponent
类型才能被施加运动); -
然后是重写
GetMovementComponent()
函数,如下:
- 最后是运动组件在响应输入的函数中被调用,如下:
- 一些注意的地方如下:
- 由于在
TickComponent()
函数中已经做了数值截断和与速度相乘计算位移的操作,所以这里直接传数值即可; - 调用的是
GetActorForwardVector()
和GetActorRightVector()
函数,这样相当于是把GetActorLocation()
拆开了三个维度分别控制; AddMovementInput()
函数实际上是充当了生产者的作用,负责把对应的输入信号放到队列中供消费者处理,它的实现在Pawn.h
中,如下:
- 由于在
-
注意:
- 这里调用了重写的
GetMovementComponent()
函数; - 也调用了自定义组件的默认生产者函数;
- 这里调用了重写的
-
这样无需在Pawn中的
Tick()
函数里面写有关位置的更新,也可以实现Pawn的运动效果; -
这当然是推荐的写法,因为即使不实现自定义的运动组件,UE4也已经提供了默认的运动组件供使用;