建议阅读缩放比例:150%
前言
嘿!看到这里的你,请你现在回想一下,你在玩旷野之息、鬼泣、怪猎、战神、黑魂、巫师这些ARPG时,你是如何操作你的角色移动的,我没有在开玩笑啊,请你认真的回想一下。
如果你有 "不就是使用WASD就可以就可以操作,这有什么好想的" 这种想法时,恭喜你,你所玩的ARPG游戏的操作体验制作的非常好,在ARPG中的移动和常规的操作有一些不同,因为要考虑到摄像机位置的问题,我们要保证角色的移动始终都是参照摄像机的位置移动的,而不是角色自身的方向,不然你的操作手感会相当的奇怪。
如果你想要知道如何制作ARPG那种移动效果,希望我的这篇文章能够帮到你
(这个是我自研的方法,肯定不会是最好的方法,仅供思路参考)
需要解决的问题
制作ARPG的时候我用了Input System和Cinemachine,所以我的情况更复杂一些
- 角色转向时的旋转问题
- 角色移动时需要参考摄像机的位置移动
- 摄像机所给出的角度需要垂直于地面
- 当角色180°的大旋转时的急停过渡动画如何使用
方法参考
角色转向时的旋转问题
我的第一版制作的时候,人物的旋转是依靠动画的效果,但这样后面有些问题(出现的问题写在文章末尾了),所以最终的版本是让角色真正旋转。
人物移动的动画机逻辑
真旋转版就很简单了(如上图所示),不需要使用动画树就可以实现,接下来需要考虑的就是代码需要控制的角色旋转效果,这个没什么难度,只需要参考摄像机的方向逐渐改变rotation就可以了。
transform.rotation = Quaternion.Lerp(transform.rotation, Quaternion.LookRotation(Camera.main.transform.forward), 15f * Time.deltaTime);`
这个是转向前方向的代码,如果想转其他方向,
则修改Camera.main.transform.forward为你想要的方向即可
角色移动时需要参考摄像机的位置移动
这个是最简单的问题,移动的值直接使用摄像机的位置信息就好了
示例:transform.Translate(Camera.main.transform.forward)
摄像机所给出的角度需要垂直于地面
这个部分的难点在于,我的角色是没有RootMotion的移动效果的,所以我是用代码实现移动的,但要参照摄像机的位置给出的角度不会全都是平行于地面的,摄像机角度一旦倾斜,角色的移动角度也会发生变化,会出现人物只按照摄像机的角度移动,而不是在地面上移动。
所以,我们需要让向量在地面上做一个投影向量,使得无论镜头怎么旋转,人物都是沿着地面移动的,所以我们就需要用到Vector3下的ProjectOnPlane方法。
使用示例:Vector3.ProjectOnPlane(Camera.main.transform.forward, Vector3.up)
这样就使得摄像机的前方向的向量始终的平行于地面
当角色180°的大旋转时的急停过渡动画如何使用
目前还在测试阶段...(我的肝在哭啊啊啊!!)
代码部分
注:按键获取使用的是Input System的方法
private void move() //真旋转版
{
if (isRotate)
{
Vector2 moveInput = action.Player.Move.ReadValue<Vector2>();
//moveValue.x = Mathf.Lerp(moveValue.x, moveInput.x, 0.05f);
//moveValue.z = Mathf.Lerp(moveValue.z, moveInput.y, 0.05f);
if (keyboard.wKey.isPressed)
{
transform.Translate(Vector3.ProjectOnPlane(Camera.main.transform.forward, Vector3.up).normalized * Time.deltaTime * moveSpeed * moveInput.y, Space.World);
transform.rotation = Quaternion.Lerp(transform.rotation, Quaternion.LookRotation(Camera.main.transform.forward), 15f * Time.deltaTime);
}
if (keyboard.sKey.isPressed)
{ transform.Translate(Vector3.ProjectOnPlane(Camera.main.transform.forward, Vector3.up).normalized * Time.deltaTime * moveSpeed * moveInput.y, Space.World);
transform.rotation = Quaternion.Lerp(transform.rotation, Quaternion.LookRotation(-Camera.main.transform.forward), 15f * Time.deltaTime);
}
if (keyboard.aKey.isPressed)
{ transform.Translate(Vector3.ProjectOnPlane(Camera.main.transform.right, Vector3.up).normalized * Time.deltaTime * moveSpeed * moveInput.x, Space.World);
transform.rotation = Quaternion.Lerp(transform.rotation, Quaternion.LookRotation(-Camera.main.transform.right), 10f * Time.deltaTime);
}
if (keyboard.dKey.isPressed)
{
transform.Translate(Vector3.ProjectOnPlane(Camera.main.transform.right, Vector3.up).normalized * Time.deltaTime * moveSpeed * moveInput.x, Space.World);
transform.rotation = Quaternion.Lerp(transform.rotation, Quaternion.LookRotation(Camera.main.transform.right), 10f * Time.deltaTime);
}
}
}
一些无关紧要的话
做ARPG项目的整个流程,让我感觉最困难的部分反而是人物的移动效果,仅仅是这一个模块我就大改了三遍代码,耗费近一个月的时间,一开始就想到了旋转的问题,索性我就直接做成了动画树,让人物的转向变成动画效果,而不是人物真正的旋转,以为可以让人物的转向看起来更顺滑,我称之为“动画旋转版”,但这个但做起来看似简单方便,事实上后面改动起来更麻烦,因为我的动画没有root motion,最要命的是我的音效用的是Animation event实现同步的,使用动画树会导致稍微有一点融合进来的动画都会触发event,最后被迫无奈的我改为了旋转的方法。