使用Player Input的Send Message模式控制输入
1、新建一个Input Actions,建立一下Action Maps以及Actions
2、如图建立分别的Actions
(注意可以将Processors中的Invert Y反转Y坐标的选择勾选上,使起变成顺手的操作方式)
3、建立控制输入的C#脚本,与Player Inputs一样挂载到需要移动的物体上
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
public class InputController : MonoBehaviour
{
private Vector2 move;
private Vector2 point;
private bool jump;
private bool aim;
private bool sprint;
public void OnMove(InputValue value)
{
move = value.Get<Vector2>();
}
public void OnLook(InputValue value)
{
point = value.Get<Vector2>();
}
public void OnJump(InputValue value)
{
jump = value.Get<bool>();
}
public void OnAim(InputValue value)
{
aim = value.Get<bool>();
}
public void OnSprint(InputValue value)
{
sprint = value.Get<bool>();
}
}
注意:如果之前建立的Actions为Move,则函数的名字需要为OnMove才能在使用Send Message中输入信息!!
建立PlayerController脚本控制角色
PlayerController_1: 将Animation转换成Int类型的变量,方便后续使用
private Animator anim;
private int animWS;
private int animAD;
private int animSprint;
private int animAim;
private int animGrounded;
private int animJump;
private void Awake()
{
anim = this.GetComponent<Animator>();
}
private void Start()
{
SwitchAnimName();
}
private void SwitchAnimName()
{
animWS = Animator.StringToHash("WS");
animAD = Animator.StringToHash("AD");
animSprint = Animator.StringToHash("Sprint");
animAim = Animator.StringToHash("Aim");
animGrounded = Animator.StringToHash("Grounded");
animJump = Animator.StringToHash("Jump");
}
PlayerController_2:实现跳跃功能
[Header("Player Grounded")]
public bool Ground = true;
public LayerMask GroundLayer;
private void Update()
{
Jump();
GroundedCheck();
}
private void Jump()
{
if (Grounded)
{
anim.SetBool(animJump, true);
}
}
private void GroundedCheck()
{
Grounded = Physics.CheckSphere(new Vector3(this.transform.position.x, this.transform.position.y - GroundOffset, this.transform.position.z), CheckRadius, GroundLayer);
}
PlayerController_3:实现人物移动
private InputController input;
private void Awake()
{
anim = this.GetComponent<Animator>();
input = this.GetComponent<InputController>();
}
private void Update()
{
Move();
}
private void Move()
{
anim.SetFloat(animWS, input.move.x);
anim.SetFloat(animAD, input.move.y);
}
在Move中,只对动画进行了设置是因为动画中包含了移动,使用的是Unity购买的资源项目,再到Mixamo.com中找的动作资源,通过重定向进行了绑定。如果动作中不包含移动,则可以使用Character Controller组件Move()方法进行移动。
PlayerController_3:实现人物始终面对镜头前方
[Header("Camera Rotate")]
public GameObject CinemachineTarget;
public float TurningSpeed = 5f;
public bool LockCamera = false;
public float CameraTargetYaw;
public float CameraTargetPitch;
public float TopClamp = 70f;
public float BottomClamp = -30f;
private const float threshold = 0.01f;
private LateUpdate()
{
CameraRotation();
}
private void CameraRotation()
{
if(input.point.sqrMagnitude >= threshold && !LockCamera)
{
CameraTargetYaw += input.point.x * Time.deltaTime;
CameraTargetPitch += input.point.y * Time.deltaTime;
}
CameraTargetYaw = ClampAngle(CameraTargetYaw, float.MinValue, float.MaxValue);
this.transform.rotation = Quaternion.Euler(0, CameraTargetYaw * TurningSpeed, 0);
CinemachineTarget.transform.rotation = Quaternion.Euler(CameraTargetPitch * TurningSpeed, CameraTargetYaw * TurningSpeed, 0);
}
//将角度限制到 -360 +360之间
private static float ClampAngle(float angle, float min, float max)
{
if (angle < -360f) angle += 360f;
if (angle > 360f) angle -= 360f;
return Mathf.Clamp(angle, min, max);
}
因为Cinemachine中Virtual Camera无法直接旋转,所以Create一个Player的子对象作为Virtual Camera的Follow对象。通过对这个对象的旋转,来旋转镜头。
实现了类似于和平精英一样的镜头移动方式,但人的上半身持枪跟着镜头移动未实现。
总结:
新的输入系统在简单的使用上,通过一定的学习,确实能优化输入系统,尤其是当有多种控制方式的时候(例如:手柄、键盘)。Send Message模式用起来感觉比直接通过脚本控制或者Invoke Unity Events模式更加方便。而使用了Maximo中的人型模型的重定向,虽然能避免写移动的逻辑以及动画制作,但是也会失去对移动逻辑的一些控制,有利有弊,可以根据自己的需求来选择是否使用Maximo中的动作模型。