跳跃功能介绍
总所周知,跳跃功能的逻辑是很容易的,但是也是很难写的,因为跳跃会引发很多的bug,例如连跳,跳比走还快,卡进了模型里面等等等等,我们常见的跳跃逻辑就是单纯的在按下跳跃键的时候,给予物体一个向上方向上的力,这样物体就跳了起来,但是,在跳的过程中,如果同时按下了方向键,那么物体是会移动的,而且移动的速度是和我们在平面上移动的速度相同,而且跳跃过程中多次按下跳跃键会发生连跳,最简单的解决方案就是加一个bool变量,在跳跃过程中锁定输入,但是这样我们就无法往前跳,那么跳跃的意义就不存在了,同样,在上述思路的基础上,我们可以在跳跃的时候修改移动的速度,使其没有在平面上移动的那么快,这也是一种解决方案,不过,这些逻辑都不用我们去写,UE4已经为我们定义好了一套跳跃的逻辑,我们可以直接使用,也可以在其基础上进行二次开发。不过,UE4的跳跃逻辑比我上述的远要复杂很多,涉及的源码也很多,有些逻辑本人水平有限,暂时还没看懂。
首先,我们依然要设置输入,但是这次我们使用的是按键映射:

我们在ThirdProjectCharacter.h中声明我们的跳跃函数:
protected:
// 按下跳跃键瞬间开始跳跃
void TouchStarted(ETouchIndex::Type FingerIndex, FVector Location);
// 弹起跳跃键瞬间停止跳跃
void TouchStopped(ETouchIndex::Type FingerIndex, FVector Location);
我们在ThirdProjectCharacter.cpp中写入以下定义:
构造函数中先设置和跳跃相关的属性
// 跳跃的高度
GetCharacterMovement()->JumpZVelocity = 600.f;
// 跳跃时可以进行横向移动控制,0为不能控制,1为以MaxWalkSpeed的最大速度进行完全控制
GetCharacterMovement()->AirControl = 0.2f;
绑定输入函数
PlayerInputComponent->BindTouch(IE_Pressed, this, &AThirdProjectCharacter::TouchStarted);
PlayerInputComponent->BindTouch(IE_Released, this, &AThirdProjectCharacter::TouchStopped);
// 跳跃开始
void AThirdProjectCharacter::TouchStarted(ETouchIndex::Type FingerIndex, FVector Location){
// 没错,直接调用Jump函数,这个函数是为我们定义好的
Jump();
}
// 跳跃停止
void AThirdProjectCharacter::TouchStopped(ETouchIndex::Type FingerIndex, FVector Location){
// 同理,这个函数也是定义好的
StopJumping();
}
现在我们看看Jump函数的定义,在Character.cpp下
void ACharacter::Jump(){
// 设置跳跃属性为true
bPressedJump = true;
// 这个是跳跃键可以持续的时间,就是这个跳跃在这个时间内会持续触发
JumpKeyHoldTime = 0.0f;
}
我们在Character.cpp查找bPressedJump这个属性,我们发现一断代码,这段代码很复杂,但是不难看出来,他调用了一个DoJump函数,而这个函数就是执行了我们的跳跃,于是我们查看DoJump函数源码,在CharacterMovementComponent下
bool UCharacterMovementComponent::DoJump(bool bReplayingMoves){
// 在这里调用了CanJump,用于判断是否可以跳跃
if ( CharacterOwner && CharacterOwner->CanJump() ){
// 如果我们无法上下移动,就不跳
if (!bConstrainToPlane || FMath::Abs(PlaneConstraintNormal.Z) != 1.f){
// 添加一个向上方向上的速度,JumpZVelocity为跳跃时的初始速度
Velocity.Z = FMath::Max(Velocity.Z, JumpZVelocity);
// 设置移动(数值方向上的位移,即为跳跃)
SetMovementMode(MOVE_Falling);
return true;
}
}
return false;
}
对于停止跳跃的函数,在Character.cpp内的源码如下:
void ACharacter::StopJumping(){
bPressedJump = false;
ResetJumpState();
}
我们继续追踪ResetJumpState函数:
void ACharacter::ResetJumpState(){
bPressedJump = false;
bWasJumping = false;
JumpKeyHoldTime = 0.0f;
JumpForceTimeRemaining = 0.0f;
if (CharacterMovement && !CharacterMovement->IsFalling()){
JumpCurrentCount = 0;
}
}
我们不难看出,它的作用就是将所有与跳跃相关的参数都进行了初始化。
对于与跳跃相关的另外一个东西,是否在空中的判断,在不使用UE4自带的IsAir属性的情况下,本人能想到的制作逻辑如下:设置碰撞这个碰撞只有地面的物体和角色,如果没有接触,就将IsAir设为flase,如果有接触,也就触发了事件,将IsAir设为true。至于UE4中的IsAir,本人并不清楚他定义在哪个文件,也没有去看,如果使用Visual Studio搜索整个项目,搜索时间过长,而且电脑负担也大,所以也没有进行搜索,后面有时间会去了解的。