unity3d 自上而下Unity 3d,玩家只能识别一个方向为向前、向左等

6kkfgxo0  于 2022-11-16  发布在  其他
关注(0)|答案(1)|浏览(163)

它在标题中说明了这一切,真的。我有一个混合树设置了4个方向和球员的移动和旋转完美,但如果我转身直接运行在(例如)向左方向,左边的扫射动画在那个方向奔跑的时候播放。2玩家面对的是正确的方向,只是他的腿在播放错误的动画。3我试过使用“标准化”和“转换。4翻译”但似乎没有什么不同。

  1. public class TwinStickMovement : MonoBehaviour
  2. {
  3. [SerializeField] private float playerSpeed = 5f;
  4. [SerializeField] private float graityValue = -9.81f;
  5. [SerializeField] private float controllerDeadZone = 0.1f;
  6. [SerializeField] private float gamepadRotateSmoothing = 1000f;
  7. [SerializeField] private bool isGamePad;
  8. private CharacterController controller;
  9. private Animator animator;
  10. private Vector2 movement;
  11. private Vector2 aim;
  12. private Vector3 playerVelocity;
  13. private Vector3 lookPoint;
  14. private PlayerControls playerControls;
  15. private PlayerInput playerInput;
  16. private bool animLocked = false;
  17. private void Awake()
  18. {
  19. controller = GetComponent<CharacterController>();
  20. playerControls = new PlayerControls();
  21. playerInput = GetComponent<PlayerInput>();
  22. animator = GetComponent<Animator>();
  23. }
  24. private void FixedUpdate()
  25. {
  26. if (!animLocked && movement != Vector2.zero)
  27. {
  28. animator.SetFloat("moveX", movement.x);
  29. animator.SetFloat("moveY", movement.y);
  30. }
  31. }
  32. private void OnEnable()
  33. {
  34. playerControls.Enable();
  35. }
  36. private void OnDisable()
  37. {
  38. playerControls.Disable();
  39. }
  40. private void Update()
  41. {
  42. HandleInput();
  43. HandleMovement();
  44. HandleRotation();
  45. }
  46. private void HandleInput()
  47. {
  48. movement = playerControls.Controls.Movement.ReadValue<Vector2>();
  49. aim = playerControls.Controls.Aim.ReadValue<Vector2>();
  50. }
  51. private void HandleMovement()
  52. {
  53. Vector3 move = new Vector3(movement.x, 0, movement.y);
  54. controller.Move(move * Time.deltaTime * playerSpeed);
  55. playerVelocity.y += graityValue * Time.deltaTime;
  56. controller.Move(playerVelocity * Time.deltaTime);
  57. }
  58. private void HandleRotation()
  59. {
  60. if (isGamePad)
  61. {
  62. if (Mathf.Abs(aim.x) > controllerDeadZone || Mathf.Abs(aim.y) > controllerDeadZone)
  63. {
  64. Quaternion newrotation = Quaternion.LookRotation(new Vector3(aim.x, 0f, aim.y),Vector3.up);
  65. transform.rotation = Quaternion.RotateTowards(transform.rotation, newrotation, gamepadRotateSmoothing * Time.deltaTime);
  66. }
  67. }
  68. else
  69. {
  70. Ray ray = Camera.main.ScreenPointToRay(aim);
  71. Plane groundPlane = new Plane(Vector3.up, Vector3.zero);
  72. float rayDistance;
  73. if (groundPlane.Raycast(ray, out rayDistance))
  74. {
  75. Vector3 point = ray.GetPoint(rayDistance);
  76. LookAt(point);
  77. }
  78. }
  79. }
  80. private void LookAt(Vector3 point)
  81. {
  82. Vector3 heightCorrectPoint = new Vector3(lookPoint.x, transform.position.y, lookPoint.z);
  83. transform.LookAt(heightCorrectPoint);
  84. }
  85. public void OnDeviceChange(PlayerInput pi)
  86. {
  87. isGamePad = pi.currentControlScheme.Equals("Gamepad") ? true : false;
  88. }
  89. }
piv4azn7

piv4azn71#

我假设你使用的逻辑等价于if moveX > 0 and moveY approximatly 0 then play strafe animation。但是这并没有考虑到玩家的方向,因此只有当你向上看的时候才能正确工作。你需要把你的moveXmoveY转换到lookXlookY的局部空间,这样动画师才能做出合适的选择。

左边的面板显示了你的动画师正在接收的信息,并根据它做出了错误的选择,并说你的角色正在扫射。右边的面板显示了矢量转换后的矢量。在这里你的动画师会认识到你正在向前移动比侧向更强,因此扫射是不合适的,应该播放向前走的动画。
我将简化数学运算,让它更好地工作,并跳到有趣的部分。基本上,你需要将uv坐标系转换为xy坐标系。为此,你在xy坐标系中有两个给定的垂直向量(观察方向和“右”),你可以在下面的两个方程中记录它们:

  1. x = au+bv
  2. y = cu+dv

你可以用它们来求uv,如果你这样做的话,它们将是:

  1. u = (by-dx)/(bc-da)
  2. v = (ay-cx)/(cd-ab)

插入所有的值并插入你想要转换成xy的坐标,会在uv空间给予你一个答案,这实际上是你需要给动画师的。
由于数学很难,我可能没有很好地解释它,下面是在Unity中完成它的代码:

  1. private Vector2 MovementRelativeToLookdirection(){
  2. float x = movement.x;
  3. float y = movement.y;
  4. float a = transform.forward.x;
  5. float b = transform.forward.z;
  6. float c = transform.right.x;
  7. float d = transform.right.z;
  8. float u = (b*y-d*x)/(b*c-d*a);
  9. float v = (a*y-c*x)/(c*d-a*b);
  10. Vector2 transformedVector = new Vector2(u, v);
  11. return transformedVector;
  12. }
  13. private void FixedUpdate()
  14. {
  15. if (!animLocked && movement != Vector2.zero)
  16. {
  17. Vector2 actualDir = MovementRelativeToLookdirection();
  18. animator.SetFloat("moveX", actualDir.x);
  19. animator.SetFloat("moveY", actualDir.y);
  20. }
  21. }

如果我的假设真的是问题所在,这应该可以解决它。

展开查看全部

相关问题