玩家输入–通过转化为数字信号的方式进行输入:
人物移动的数字信号转化:
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));
// ...
}