0
点赞
收藏
分享

微信扫一扫

Unity项目-黑魂复刻(一)玩家控制器(玩家移动、动画实现以及优化)

小安子啊 2022-02-20 阅读 63

玩家输入–通过转化为数字信号的方式进行输入:

人物移动的数字信号转化:

     public string keyUp = "w";
     public string keyDown="s";
     public string keyLeft="a";
     public string keyRight="d";
     //通过三元运算符判定是否有按下这些键,从而进行赋值水平和垂直方向是 1或者-1
     targetDup = (Input.GetKey(keyUp) ? 1.0f : 0) - (Input.GetKey(keyDown) ? 1.0f : 0);
     targetDright = (Input.GetKey(keyRight) ? 1.0f : 0) - (Input.GetKey(keyLeft) ? 1.0f : 0);
     //当没有按时就需要把玩家停下来
     if (inputEnabled==false) {
           targetDup = 0;
           targetDright = 0;
      }
      //通过Mathf.SmoothDamp让Dup逐渐趋向与目标
      Dup = Mathf.SmoothDamp(Dup, targetDup, ref velocityDup, 0.1f);
      Dright = Mathf.SmoothDamp(Dright, targetDright, ref velocityDright, 0.1f);

人物转向:

//解决斜着的速度比水平垂直的速度快
 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;
    }
 //斜角速度和直线一样
        Vector2 temDAxis = SquareToCircle(new Vector2(Dright,Dup));
        float Dright2 = temDAxis.x;
        float Dup2 = temDAxis.y;

        Dmag = Mathf.Sqrt((Dup2 * Dup2) + (Dright2 * Dright2));
        Dvec = Dright2 * transform.right + Dup2 * transform.forward;

人物移动–通过Rigibody控制玩家的移动

 //移动时需要在FixedUpdate中进行(物理) 
    private void FixedUpdate() // Time.fixedDeltaTime 1/50
    {
        //方法一,position的位置包含y轴
       // rigid.position += movingVec * Time.fixedDeltaTime;
        //方法二,速度不包含y方向
        rigid.velocity =new Vector3(movingVec.x,rigid.velocity.y,movingVec.z);
        print(rigid.velocity.y);
    }

人物动画实现以及优化

混合树
在这里插入图片描述

动画机的运用以及模型旋转

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    // 玩家的人物模型 用来获取模型身上的动画机以及其它
    public GameObject model;
    // 输入模块
    public PlayerInput pi;
    // 动画机
    private Animator anim;

    // Awake适合用来做GetComponent
    void Awake()
    {
        anim = model.GetComponent<Animator>();
        pi = GetComponent<PlayerInput>();
    }

    // Update is called once per frame
    void Update()
    {
        // 将输入转换为速度 赋值给动画机相关参数
        anim.SetFloat("forward", pi.dirMag);
        // 只在有速度时能够旋转 防止原地旋转
        if(pi.dirMag > 0.1f)
            model.transform.forward = pi.dirVec;
    }
}
// 玩家的输入模长量 用于当成向前量大小作为动画控制
    public float dirMag;
    // 玩家的方向 用于旋转模型
    public Vector3 dirVec;

    // Update is called once per frame
    void Update()
    {
        // 计算输入模长
        dirMag = Mathf.Sqrt((dirUp * dirUp) + (dirRight * dirRight));
        // 计算玩家的方向
        dirVec = dirRight * transform.right + dirUp * transform.forward;
        // ...
    }

游戏玩家角色的位移

// 刚体
    public Rigidbody rigidbody;
    // 行走速度
    public float walkSpeed = 2.0f;
    // 角色的位移大小
    private Vector3 movingVec;
    
    // Update is called once per frame
    void Update()
    {
        // ...
        
        // 计算移动量 速度向量
        movingVec = pi.dirMag * model.transform.forward * walkSpeed;

    }
    
    // 处理刚体的操作
    private void FixedUpdate()
    {
        // 直接修改position实现位移
        rigidbody.position += movingVec * Time.fixedDeltaTime;
         修改rb.velocity来实现位移
        //rb.velocity = new Vector3(m_planarVec.x, rb.velocity.y, m_planarVec.z)
    }

跑步

public string keyRun; //跑步键
    
    // 是否正在奔跑 按压信号
    public bool run; 
    
    // Update is called once per frame
    void Update()
    {
        // 跑步信号
        run = Input.GetKey(keyRun);
        // ...
    }
// Update is called once per frame
    void Update()
    {
        // 将输入转换为速度 赋值给动画机相关参数
        anim.SetFloat("forward", pi.dirMag * (pi.run ? 2.0f : 1.0f));
        // 计算移动量 速度向量
        movingVec = pi.dirMag * model.transform.forward * walkSpeed * (pi.run ? runMultiplier : 1.0f);
        // ...
    }

旋转的优化

// Update is called once per frame
    void Update()
    {
        // 只在有速度时能够旋转 防止原地旋转
        if(pi.dirMag > 0.1f)
        {
            // 运用旋转 使用Slerp进行效果优化   
            model.transform.forward = 
                Vector3.Slerp(model.transform.forward, pi.dirVec, 0.3f);
        }

        // ...
    }

跑步动画的优化

// 将输入转换为速度 赋值给动画机相关参数
    anim.SetFloat("forward", pi.dirMag * (pi.run ? 2.0f : 1.0f));
void Update()
    {
        // 将现在的动画参数forward值通过lerp变化得到
        anim.SetFloat("forward", Mathf.Lerp(anim.GetFloat("forward"), pi.dirMag * (pi.run ? 2.0f : 1.0f), 0.1f));
        // ...
    }
举报

相关推荐

0 条评论