它在标题中说明了这一切,真的。我有一个混合树设置了4个方向和球员的移动和旋转完美,但如果我转身直接运行在(例如)向左方向,左边的扫射动画在那个方向奔跑的时候播放。2玩家面对的是正确的方向,只是他的腿在播放错误的动画。3我试过使用“标准化”和“转换。4翻译”但似乎没有什么不同。
public class TwinStickMovement : MonoBehaviour
{
[SerializeField] private float playerSpeed = 5f;
[SerializeField] private float graityValue = -9.81f;
[SerializeField] private float controllerDeadZone = 0.1f;
[SerializeField] private float gamepadRotateSmoothing = 1000f;
[SerializeField] private bool isGamePad;
private CharacterController controller;
private Animator animator;
private Vector2 movement;
private Vector2 aim;
private Vector3 playerVelocity;
private Vector3 lookPoint;
private PlayerControls playerControls;
private PlayerInput playerInput;
private bool animLocked = false;
private void Awake()
{
controller = GetComponent<CharacterController>();
playerControls = new PlayerControls();
playerInput = GetComponent<PlayerInput>();
animator = GetComponent<Animator>();
}
private void FixedUpdate()
{
if (!animLocked && movement != Vector2.zero)
{
animator.SetFloat("moveX", movement.x);
animator.SetFloat("moveY", movement.y);
}
}
private void OnEnable()
{
playerControls.Enable();
}
private void OnDisable()
{
playerControls.Disable();
}
private void Update()
{
HandleInput();
HandleMovement();
HandleRotation();
}
private void HandleInput()
{
movement = playerControls.Controls.Movement.ReadValue<Vector2>();
aim = playerControls.Controls.Aim.ReadValue<Vector2>();
}
private void HandleMovement()
{
Vector3 move = new Vector3(movement.x, 0, movement.y);
controller.Move(move * Time.deltaTime * playerSpeed);
playerVelocity.y += graityValue * Time.deltaTime;
controller.Move(playerVelocity * Time.deltaTime);
}
private void HandleRotation()
{
if (isGamePad)
{
if (Mathf.Abs(aim.x) > controllerDeadZone || Mathf.Abs(aim.y) > controllerDeadZone)
{
Quaternion newrotation = Quaternion.LookRotation(new Vector3(aim.x, 0f, aim.y),Vector3.up);
transform.rotation = Quaternion.RotateTowards(transform.rotation, newrotation, gamepadRotateSmoothing * Time.deltaTime);
}
}
else
{
Ray ray = Camera.main.ScreenPointToRay(aim);
Plane groundPlane = new Plane(Vector3.up, Vector3.zero);
float rayDistance;
if (groundPlane.Raycast(ray, out rayDistance))
{
Vector3 point = ray.GetPoint(rayDistance);
LookAt(point);
}
}
}
private void LookAt(Vector3 point)
{
Vector3 heightCorrectPoint = new Vector3(lookPoint.x, transform.position.y, lookPoint.z);
transform.LookAt(heightCorrectPoint);
}
public void OnDeviceChange(PlayerInput pi)
{
isGamePad = pi.currentControlScheme.Equals("Gamepad") ? true : false;
}
}
1条答案
按热度按时间piv4azn71#
我假设你使用的逻辑等价于
if moveX > 0 and moveY approximatly 0 then play strafe animation
。但是这并没有考虑到玩家的方向,因此只有当你向上看的时候才能正确工作。你需要把你的moveX
和moveY
转换到lookX
和lookY
的局部空间,这样动画师才能做出合适的选择。左边的面板显示了你的动画师正在接收的信息,并根据它做出了错误的选择,并说你的角色正在扫射。右边的面板显示了矢量转换后的矢量。在这里你的动画师会认识到你正在向前移动比侧向更强,因此扫射是不合适的,应该播放向前走的动画。
我将简化数学运算,让它更好地工作,并跳到有趣的部分。基本上,你需要将uv坐标系转换为xy坐标系。为此,你在xy坐标系中有两个给定的垂直向量(观察方向和“右”),你可以在下面的两个方程中记录它们:
你可以用它们来求
u
和v
,如果你这样做的话,它们将是:插入所有的值并插入你想要转换成
x
和y
的坐标,会在uv空间给予你一个答案,这实际上是你需要给动画师的。由于数学很难,我可能没有很好地解释它,下面是在Unity中完成它的代码:
如果我的假设真的是问题所在,这应该可以解决它。