[方法] Unity 解决类《原神》角色移动方向问题

第三人称视角类的游戏有很多,比如《原神》、《崩坏:星穹铁道》、《剑星》、《绝地求生》等。这些游戏中,角色的移动方向取决于玩家的输入和相机的方向,例如玩家在键盘上按下D键,则角色会相对于相机方向向右移动,本篇文章就来揭晓这背后的实现方式。

1. 基于骨骼动画的移动

1.1 骨骼设置

首先选中一个骨骼动画,单击 Inspector 面板里的 Animation 选项卡按钮:

我们以行走动画为例,如果我们想让动画中出现的模型偏移来改变角色的实际位置,那么我们就要取消勾选 XZ轴 的 Bake into Pose

如果是跳跃动画,则需要取消勾选 Y轴 的 Bake into Pose

1.2 位移同步

假设目前我们的角色有一个胶囊体(characterController)和一个动画器(animator),并正在播放与位移相关的动画,如下代码实现了动画的运动偏移对模型造成了一个实际的位移:

// 根运动事件
private void OnAnimatorMove()
{
    OnRootMotion(animator.deltaPosition, animator.deltaRotation);
}

private void OnRootMotion(Vector3 deltaPosition, Quaternion deltaRotation)
{
    // 加入重力影响
    deltaPosition.y = gravity * Time.deltaTime;
    // 对玩家进行一个实际的位移
    characterController.Move(deltaPosition);
}

1.3 模型朝向纠正

接下来,我们要根据玩家的输入相机的朝向来实现类似于《原神》的角色移动方向的机制,核心代码十分简单,并不需要我们亲自编写旋转算法,拿来即用:

void Update()
{
    // 玩家输入向量:x - 水平输入,y - 垂直输出
    Vector2 moveVector = PlayerInput.input.Player.Move.ReadValue<Vector2>().normalized;
    // 转向过渡
    float rotateSpeed = 5f;

    // -----------核心代码-----------

    // 将玩家的输入组合成一个三维向量
    Vector3 input = new Vector3(moveVector.x, 0, moveVector.y);
    // 拿到相机的朝向
    float y = Camera.main.transform.rotation.eulerAngles.y; 
    // 求得角色的目标移动方向
    Vector3 targetDic = Quaternion.Euler(0, y, 0) * input;
    // 让模型旋转到目标方向
    transform.rotation = Quaternion.Slerp(transform.rotation, 
        Quaternion.LookRotation(targetDic), Time.deltaTime * rotateSpeed);
}

 2. 非骨骼动画的模型朝向纠正

private void PlayerMoveControl() {
    // 让模型旋转到目标方向
    if (transform.eulerAngles != targetDic)
        transform.rotation = Quaternion.Slerp(transform.rotation, 
            Quaternion.LookRotation(targetDic), Time.deltaTime * rotateSpeed);
    // 处理玩家输入方向
    moveVector = inputControl.Player.Move.ReadValue<Vector2>().normalized;
    if (moveVector == Vector2.zero)
        return;
    Vector3 inputDirection = new Vector3(moveVector.x, 0, moveVector.y);
    // 拿到相机的朝向
    float cameraDic = Camera.main.transform.eulerAngles.y; 
    // 更新角色的目标移动方向
    targetDic = Quaternion.Euler(0, cameraDic, 0) * inputDirection;
    // 让角色朝该方向移动
    controller.Move(targetDic * moveSpeed * Time.deltaTime);
}
  • 17
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值