[魂类复刻学习日志]3.实现奔跑与初步跳跃
实现奔跑动作
-
在资源中找到奔跑的动画,我们将其加入之前的ground混合树中,调节forward的取值范围,现在它是0-2了,当趋于2时Ybox会逐渐混合奔跑的动画。
-
接下来在代码中更改forward,并且关注速度的改变,由于奔跑是持续性的信号,按住即一直奔跑,所以实现也相对简单,只需要像之前一样
Input.GetKey(KeyA)
即可
//在之前的代码基础上,更改forward
anim.SetFloat("forward",pl.Dmag * Mathf.Lerp(anim.GetFloat("forward"), (pl.run) ? 2.0f : 1.0f, 0.5f)) ;
//在之前的代码基础上,更改其朝向,以及给刚体的速度向量
if(pl.Dmag > 0.1f)
{
model.transform.forward = Vector3.Slerp(model.transform.forward, pl.Dvec, 0.2f);//改变模型的朝向,朝向即为位移的方向
}
movingVec = pl.Dmag * moveSpeed * model.transform.forward * ((pl.run)?runMultplier:1.0f);
- 上述代码中的runMultplier是设定的奔跑速度加快的系数,默认为2倍。
关于Lerp()与Slerp()函数
-Mathf.Lerp()
与Mathf.SmoothDamp()
有些类似,它们都是用作平滑改变值的,Lerp()为线性插值,Slerp()为球形插值
- 线性插值与球形插值通俗的区别在于,从起点到目标值移动的路径,一个是均匀变化的直线,一个是弧线
解决斜向加速问题
- 为何会出现该问题:Dmag的值是按照向量模计算的,当Dup与Dright同时有输入的时候,相加开根号即为1.414,因此要快一些
- 如何解决:可以使用一些if判断,也可以变换为椭圆路径(椭圆映射),直接利用公式改变Dup与Dright的值即可
private Vector2 SquareToCircle(Vector2 input)
{
Vector2 output = Vector2.zero;
output.x = input.x * Mathf.Sqrt(1 - (input.y * input.y) / 2.0f);
output.y = input.y * Mathf.Sqrt(1 - (input.x * input.x) / 2.0f);
return output;
}
加入跳跃动画
-
回到Animator,跳跃是发生在空中的事件,自然要和ground独立开来,直接拖入创建,并与ground状态增加互相的转换
-
这次要新增变量了,类型是比较特殊的触发器——Trigger,注意不是bool,我们将转换的条件设置为刚刚加入的这个
jump
触发器,随后进入代码中进行控制 -
这一次有一些特殊,前面提到的奔跑是持续性的,是需要一直按住某个键的,然而跳跃不是,它是触发器,是一次性的,只需要跳一下,因此需要对状态作出一些处理,我们只在按下跳跃键的一瞬间触发
jump
,然后直到松开也不能再触发了(否则会一直在跳跃动画中!)
-
我们只需要前一段的触发
bool newJump = Input.GetKey(KeyB);
if(lastJump == false && newJump == true)
{
jump = true;
}
else
{
jump = false;
}
lastJump = newJump;
- 至此我们完成了跳跃动画的触发,但仍然有许多问题,比如连续按会发现多次触发
jump
,导致会跳两下(跳第二下的时候已经有一段间隔没按了!),将在下一节解决触发器的问题