获取鼠标位置:
gamedevbeginner.com/how-to-conv…
一般使用 RigidBody 的冲刺写法:
我觉得这个挺不错的,但是就是 InputSystem 有一个微妙的逻辑。假设 Player Input 使用 Invoke Unity Event 的方式调用角色的控制脚本,移动是 WASD,冲刺是右键,在我按下 WASD 之中几个键的时候,如果我按下右键冲刺,那么冲刺完之后如果设当前运动方向为 0,那么角色之后就不会动了,即使冲刺之后你依然按着 WASD。
这就和一般人的游戏直觉相悖,但是这是因为 Input System 默认只在按键按下或者松开的时候才 Invoke,虽然你可以改成 Hold 方式……但是那个响应有点慢感觉
所以还需要考虑在冲刺之前缓存当前运动方向,冲刺完之后再恢复
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerHandler : MonoBehaviour
{
#region Move Var
[Header("Move")]
[SerializeField]
private float walkSpeed = 2f;
[SerializeField]
private Vector3 moveDir = Vector3.zero;
[SerializeField]
private Vector3 curVelocity = Vector3.zero;
[SerializeField]
private float stopThreshold = 0.01f;
private bool isMoving
{
get => curVelocity.magnitude > stopThreshold;
}
protected CharacterController character;
#endregion
#region Dash Var
[Header("Dash")]
[SerializeField]
private bool canDash = true;
[SerializeField]
private bool isDashing;
[SerializeField]
private float dashSpeed = 8f;
[SerializeField]
private float dashingTime = 0.2f;
[SerializeField]
private float dashingCooldown = 1f;
[SerializeField]
private TrailRenderer tr;
Vector3 worldPosition = Vector3.zero;
Plane plane = new Plane(Vector3.up, 0);
Vector3 walkDirCached = Vector3.zero;
#endregion
private void Start()
{
character = this.GetComponent<CharacterController>();
}
private void FixedUpdate()
{
if (isDashing)
{
curVelocity = Vector3.Lerp(curVelocity, Vector3.zero, Time.fixedDeltaTime);
}
else
{
curVelocity = moveDir * walkSpeed;
}
character.Move(curVelocity * Time.fixedDeltaTime);
}
#region InputSystem Callback
public void TryMove(InputAction.CallbackContext context)
{
if (isDashing)
return;
Debug.Log("Trying Move!");
Vector2 moveInput = context.ReadValue<Vector2>().normalized;
moveDir = new Vector3(moveInput.x, 0, moveInput.y);
moveDir = Quaternion.AngleAxis(45, Vector3.up) * moveDir;
}
public void TryDash(InputAction.CallbackContext context)
{
if(canDash)
StartCoroutine(Dash());
}
#endregion
private IEnumerator Dash()
{
canDash = false;
isDashing = true;
tr.emitting = true;
walkDirCached = moveDir;
float distance;
plane.SetNormalAndPosition(Vector3.up, transform.position);
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (plane.Raycast(ray, out distance))
{
worldPosition = ray.GetPoint(distance);
moveDir = new Vector3(worldPosition.x - transform.position.x, 0, worldPosition.z - transform.position.z);
curVelocity = dashSpeed * moveDir;
}
yield return new WaitForSeconds(dashingTime);
tr.emitting = false;
isDashing = false;
curVelocity = Vector3.zero;
moveDir = walkDirCached;
yield return new WaitForSeconds(dashingCooldown);
canDash = true;
}
}