前面提到了关于InputSystem的简单配置 接下来用C#代码的形式用到下面这个接口
public interface IGamePlayActions
{
void OnMove(InputAction.CallbackContext context);//这里的方法是你添加的具体的Input Action
}
创建Input脚本 并做成ScriptableObject(加不加都行) 并继承接口
并实现抽象接口
//这里的InputMove 指的是你刚才Generate的C#类名
public class PlayerMove : MonoBehaviour, InputMove.IGamePlayActions
{
public void OnMove(InputAction.CallbackContext context)
{
throw new System.NotImplementedException();
}
}
获取生成类的引用 并实例化
private InputMove inputActions;
private void OnEnable()
{
inputActions = new InputMove();
//登记回调函数 这样每次添加新的动作表 在这里登记回调函数
inputActions.GamePlay.SetCallbacks(this);
}
public void DisableAllInputs()
{
inputActions.GamePlay.Disable();//禁用动作表
}
public void EnableGamePlayInput()
{
inputActions.GamePlay.Enable();//启用动作表
}
public void OnMove(InputAction.CallbackContext context)
{
throw new System.NotImplementedException();
}
前面我们提到 输入动作是由输入信号触发的事件
声明一个事件onMove
private event UnityAction<Vector2> onMove = delegate { };
//因为需要接收的是来自键盘的输入 是一个二维向量 需要添加一个v2的参数
在OnMove函数中调用这个事件:
public void OnMove(InputAction.CallbackContext context)
{
if (context.phase == InputActionPhase.Performed)//相当于Input.GetKey()
{
//传入输入动作读取到的二维向量的值 将其作为参数
//当按下按键的时候 调用onmove方法 同时将读取到的二维向量值作为参数
onMove.Invoke(context.ReadValue<Vector2>());
}
if (context.phase == InputActionPhase.Canceled)
{
onStopMove.Invoke();
}
}
关于InputAction
简单了解下
Class InputAction
这个类表示的是一种响应动作逻辑,可以绑定到多个物理输入上,这些绑定的物理输入和得到的输入值将影响同一个 InputAction 对象。该类只代表一种动作“逻辑”而不代表任何物理输入。
每个动作逻辑在每一时刻都有现在的状态阶段(Phase),通过 Enum InputActionPhase 表示,有五种阶段。分别为:Canceled, Disabled, Performed, Started, Waiting。在 Start, Performed, Canceled 阶段会分别触发三个对应的 C# 事件
(类型为eventAction<InputAction.CallbackContext>)。
每次动作逻辑被触发时,可以通过ReadValue()成员来获取本次触发的具体值。
Waiting,Started, Performed,Canceled, Disabled,
Waiting:在动作表启用 且没有输入信号传入
Started:按下按键的那一帧 相当于Input.GetKeyDown()
Performed:输入动作已执行 包含了按下按键和按住按键的两个阶段 相当于Input.Getkey()
Cancel:相当于松开按键的时候 相当于Input.GetKeyUp()
这样 当键盘实现输入后 将具体的vector2的参数传入到事件中 调用事件的函数
在具体的事件函数中写对应的移动代码 就可以实现角色的移动。
参考代码:
[CreateAssetMenu(menuName = "Input")]
public class Input : ScriptableObject, InputSystems.IGamePlayActions
{
public event UnityAction<Vector2> onMove = delegate { };
public event UnityAction onStopMove = delegate { };
private InputSystems inputActions;
private void OnEnable()
{
inputActions = new InputSystems();
inputActions.GamePlay.SetCallbacks(this);
}
private void OnDisable()
{
DisableAllInputs();
}
public void DisableAllInputs()
{
inputActions.GamePlay.Disable();
}
public void EnableGamePlayInput()
{
inputActions.GamePlay.Enable();
Cursor.visible = false;
Cursor.lockState = CursorLockMode.None;
}
public void OnMove(InputAction.CallbackContext context)
{
if (context.phase == InputActionPhase.Performed)//相当于Input.GetKey()
{
//传入输入动作读取到的二维向量的值 将其作为参数
//当按下按键的时候 调用onmove方法 同时将读取到的二维向量值作为参数
onMove.Invoke(context.ReadValue<Vector2>());
}
if (context.phase == InputActionPhase.Canceled)
{
onStopMove.Invoke();
}
}
public class Player : MonoBehaviour
{
public float moveSpeed = 6f;
[SerializeField] private Input playerInput;
[SerializeField] private new Rigidbody2D rigidbody2D;
[SerializeField] private float acceleTime = 3f;
[SerializeField] private float deAcceleTime = 3f;
Coroutine coroutine;
private void OnEnable()
{
//事件处理程序 Player订阅 Input的onMove和onStopMove事件
playerInput.onMove += Move;
playerInput.onStopMove += StopMove;
}
private void OnDisable()
{
playerInput.onMove -= Move;
playerInput.onStopMove -= StopMove;
}
private void Awake()
{
rigidbody2D = GetComponent<Rigidbody2D>();
}
private void Start()
{
playerInput.EnableGamePlayInput();//操作玩家角色时 GamePlay动作表激活
}
private void StopMove()
{
if (coroutine != null)
StopCoroutine(coroutine);//每次按键调用 暂停上一次的协程
coroutine = StartCoroutine(MoveCoroutine(deAcceleTime, Vector2.zero));
}
private void Move(Vector2 moveInput)
{
if (coroutine != null)
StopCoroutine(coroutine);
coroutine = StartCoroutine(MoveCoroutine(acceleTime, moveInput.normalized * moveSpeed));
}
IEnumerator MoveCoroutine(float time, Vector2 moveVelocity)
{
float t = 0f;
while (t < time)
{
t += Time.deltaTime / time;
rigidbody2D.velocity = Vector2.Lerp(rigidbody2D.velocity, moveVelocity, t / time);
yield return null;
}
}