日志
好多天没写日志了,其实最近做了很多东西,只是一直懒得记录而已,所以这两天先把前面的日志补完再继续开发
好了,值得一提的是最近又找到了几款合适的资源,日子真是越来越有盼头了^_^
之前在第一次的时候我们制作了一个探索风格的第三人称视角,但沙盒游戏中更多的时候是战斗,所以我们需要开发
一个一般状态的操控器,之前的那个可以留在一些特定的场合使用。在战斗方面我觉得饥荒给我的感觉最舒服,所以我
决定模仿饥荒的人物操控来制作。
我们依然是在之前的两个脚本LocomotionController和ViewController中做补充
人物移动
事实是这样的,如果你想让人物控制感到真实,那么左右按键应该是旋转人物无论是lerp还是瞬间调整rotation;如果你想让人物操作简单,可以去“走位”,那么左右按键应该直接让人物转到对应的角度并向对应方向移动,如果我长按左键我是希望人物向左移动而非向左转动,这一点至关重要
想让人物“向左移动”需要两个步骤,第一是转到“左”,第二是向“左”走。 这里的“左”指得是摄像机观察方向下的左,所以我们应该获取摄像机观察方向下的前后左右(viewEulerAngle和viewDirForward,viewDirRight)。注意第一部是转到左而不是向左转,我们摄像机不会随人物转动,它受到单独的控制,所以摄像机的“左”是固定的,不会因为人物的转动而改变
但你可能也注意到如果这样做的话我们人物将不能向360度的任意方向移动,事实也确实如此,一般在这种情况下都会声明两个变量forward和right,由他们来组合成8个方向(0,-1,1)(算上静止的话就是9个),最终和视角方向和速度一起构成人物的位移
void FixedUpdate()
{
Vector3 viewEulerAngle = viewController.thirdPersonCam.transform.eulerAngles;
Vector3 viewDirForward = viewController.thirdPersonCam.transform.forward;
Vector3 viewDirRight = viewController.thirdPersonCam.transform.right;
Vector3 lastPos = transform.position;
float forward = 0, right = 0;
if(Input.GetKey(KeyCode.A))
{
viewController.model.rotation = Quaternion.Euler(0, viewEulerAngle.y - 90, 0);
right -= 1;
}
if(Input.GetKey(KeyCode.D))
{
viewController.model.rotation = Quaternion.Euler(0, viewEulerAngle.y + 90, 0);
right += 1;
}
if(Input.GetKey(KeyCode.W))
{
viewController.model.rotation = Quaternion.Euler(0, viewEulerAngle.y, 0);
forward += 1;
}
if(Input.GetKey(KeyCode.S))
{
viewController.model.rotation = Quaternion.Euler(0, viewEulerAngle.y + 180, 0);
forward -= 1;
}
Vector3 moveDir = viewDirForward * forward + viewDirRight * right;
moveDir.y = 0;
moveDir.Normalize();
transform.position += moveDir * Time.deltaTime * runSpeed;
}
这里还会有一个老生常谈的问题:我该把相机作为人物的子物体还是单独的物体?
在第一篇中已经讲过,单独控制相机跟随人物移动是困难的,并且它很容易产生bug,所以我们应该尽可能的让相机作为子物体;但我们的要求是:相机能跟随人物移动,但不跟随人物转动。这可能吗?其实这个问题在养成一个好习惯后往往不会遇到,因为我们一般不会将脚本直接挂载在模型上,而是重新创造一个空物体,那么我们只需要“移动”这个空物体,而“转动”模型,摄像机和模型都是空物体的子物体,就实现了我们的要求。
第三人称视角
其实视角部分的最核心问题已经解决了,在将摄影机作为子物体后视角部分不需要处理复杂的移动了,只有简单的旋转视角,因为是按照饥荒的风格,所以视角是绕人物旋转的即RotateAround。顺便旋转模型也是按照饥荒的感觉来模仿的,这里可以*选择是否旋转或者旋转角度。
void FixedUpdate()
{
if(Input.GetKeyDown(KeyCode.Q))
{
thirdPersonCam.transform.RotateAround(model.position, Vector3.up, 45);
model.Rotate(0, 45, 0);
}
if(Input.GetKeyDown(KeyCode.E))
{
thirdPersonCam.transform.RotateAround(model.position, Vector3.up, -45);
model.Rotate(0, -45, 0);
}
}
总结
这次的代码看起来很简单,但实际上并不是,我至少来回玩了3次饥荒才比较好的复刻了这种手感,看似完全不合理的操控旋转方式产出了一个很丝滑的控制效果,将一个看到的效果转换为代码的过程真的会学到很多。