猿问

使用虚拟操纵杆旋转 2D Sprite

我正在尝试使用操纵杆沿 z 轴旋转游戏对象,但它的旋转 y 轴。我可能漏掉了一些数学计算。任何帮助?

void FixedUpdate()

    {

        // get input from joystick

        // get input from joystick

        rightJoystickInput = rightJoystick.GetInputDirection();


        float xMovementRightJoystick = rightJoystickInput.x; // The horizontal movement from joystick 02

        float zMovementRightJoystick = rightJoystickInput.y; // The vertical movement from joystick 02



        // if there is only input from the right joystick

        if (rightJoystickInput != Vector3.zero)

        {

            // calculate the player's direction based on angle

            float tempAngle = Mathf.Atan2(zMovementRightJoystick, xMovementRightJoystick);

            xMovementRightJoystick *= Mathf.Abs(Mathf.Cos(tempAngle));

            zMovementRightJoystick *= Mathf.Abs(Mathf.Sin(tempAngle));


            // rotate the player to face the direction of input

            Vector3 temp = transform.position;

            temp.x += xMovementRightJoystick;

            temp.z += zMovementRightJoystick;

            Vector3 lookDirection = temp - transform.position;

            if (lookDirection != Vector3.zero)

            {

                rotationTarget.localRotation = Quaternion.Slerp(rotationTarget.localRotation, Quaternion.LookRotation(lookDirection) * Quaternion.Euler(0, 45f, 0), rotationSpeed * Time.deltaTime);

            }

        }

    }


繁星淼淼
浏览 188回答 2
2回答

蝴蝶刀刀

您不需要问题中的大部分代码,这非常简单。1 .找到角度,Mathf.Atan2然后乘以Mathf.Rad2Deg。2。使用Quaternion.Euler(new Vector3(0, 0, angle))得到的旋转然后将其应用到对象。这应该是Update函数中的一个,而不是FixedUpdate因为FixedUpdate用于移动Rigidbody对象。public Transform rotationTarget;public bool flipRot = true;void Update(){&nbsp; &nbsp; rightJoystickInput = rightJoystick.GetInputDirection();&nbsp; &nbsp; float horizontal = rightJoystickInput.x;&nbsp; &nbsp; float vertical = rightJoystickInput.y;&nbsp; &nbsp; float angle = Mathf.Atan2(horizontal, vertical) * Mathf.Rad2Deg;&nbsp; &nbsp; angle = flipRot ? -angle : angle;&nbsp; &nbsp; rotationTarget.rotation = Quaternion.Euler(new Vector3(0, 0, angle));}如果使用Rigidbody2D则Rigidbody2D.MoveRotation在FixedUpdate函数中使用。其余代码保持不变。public Rigidbody2D rg2d;public bool flipRot = true;void FixedUpdate(){&nbsp; &nbsp; rightJoystickInput = rightJoystick.GetInputDirection();&nbsp; &nbsp; float horizontal = rightJoystickInput.x;&nbsp; &nbsp; float vertical = rightJoystickInput.y;&nbsp; &nbsp; float angle = Mathf.Atan2(horizontal, vertical) * Mathf.Rad2Deg;&nbsp; &nbsp; angle = flipRot ? -angle : angle;&nbsp; &nbsp; rg2d.MoveRotation(angle);}编辑:但唯一的问题是当我离开操纵杆时,它的旋转立即设置为 0,这看起来太奇怪了。我该如何解决?您必须检测何时释放操纵杆,OnPointerUp然后慢慢将操纵杆重击回零位置。您还必须将当前目标对象角度设置为零或其默认值,这应该在协程函数中完成。当OnPointerDown被调用时,停止当前协程功能。防止FixedUpdate手指松开时代码运行,以免干扰协程功能。为了完整起见,下面是操纵杆代码和上面刚体答案的组合:public class VirtualJoystickController : MonoBehaviour,&nbsp; &nbsp; IDragHandler, IPointerUpHandler, IPointerDownHandler{&nbsp; &nbsp; private Image bgImg;&nbsp; &nbsp; private Image joystickImg;&nbsp; &nbsp; public float mas_distance = 7f;&nbsp; &nbsp; void Start()&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; bgImg = GameObject.Find("JoystickBGImage").GetComponent<Image>(); // the joysticks background&nbsp; &nbsp; &nbsp; &nbsp; joystickImg = GameObject.Find("Joystickthumb").GetComponent<Image>(); // the joystick object to use&nbsp; &nbsp; }&nbsp; &nbsp; private Vector3 _inputDirection = Vector3.zero;&nbsp; &nbsp; //the movementDirection&nbsp; &nbsp; public Vector3 joystickInputDirection&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; set&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //Change only if value is different from old one&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (_inputDirection != value)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _inputDirection = value;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Debug.Log("Dir: " + _inputDirection);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; get&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return _inputDirection;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; public void OnDrag(PointerEventData eventData)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; dragJoyStick(eventData);&nbsp; &nbsp; }&nbsp; &nbsp; void dragJoyStick(PointerEventData eventData)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; Vector3 tempDir = Vector3.zero;&nbsp; &nbsp; &nbsp; &nbsp; Vector2 pos = Vector2.zero;&nbsp; &nbsp; &nbsp; &nbsp; if (RectTransformUtility.ScreenPointToLocalPointInRectangle&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (bgImg.rectTransform,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; eventData.position,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; eventData.pressEventCamera,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; out pos))&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pos.x = (pos.x / bgImg.rectTransform.sizeDelta.x);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pos.y = (pos.y / bgImg.rectTransform.sizeDelta.y);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; float x = (bgImg.rectTransform.pivot.x == 1) ? pos.x * 2 + 1 : pos.x * 2 - 1;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; float y = (bgImg.rectTransform.pivot.y == 1) ? pos.y * 2 + 1 : pos.y * 2 - 1;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tempDir = new Vector3(x, y, 0);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (tempDir.magnitude > 1)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tempDir = tempDir.normalized;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; joystickImg.rectTransform.anchoredPosition = new Vector3(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tempDir.x * (bgImg.rectTransform.sizeDelta.x / mas_distance),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tempDir.y * (bgImg.rectTransform.sizeDelta.y / mas_distance));&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; joystickInputDirection = tempDir;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; public void OnPointerDown(PointerEventData eventData)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; released = false;&nbsp; &nbsp; &nbsp; &nbsp; //Stop current coroutine&nbsp; &nbsp; &nbsp; &nbsp; if (retCoroutine != null)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; StopCoroutine(retCoroutine);&nbsp; &nbsp; &nbsp; &nbsp; if (eventData.pointerCurrentRaycast.gameObject == bgImg.gameObject ||&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; eventData.pointerCurrentRaycast.gameObject == joystickImg.gameObject)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; OnDrag(eventData);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; public void OnPointerUp(PointerEventData eventData)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; released = true;&nbsp; &nbsp; &nbsp; &nbsp; //Stop current coroutine then start a new one&nbsp; &nbsp; &nbsp; &nbsp; if (retCoroutine != null)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; StopCoroutine(retCoroutine);&nbsp; &nbsp; &nbsp; &nbsp; retCoroutine = StartCoroutine(SlowReturn(returnTime));&nbsp; &nbsp; }&nbsp; &nbsp; IEnumerator SlowReturn(float duration)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; RectTransform thumbstickTransform = joystickImg.rectTransform;&nbsp; &nbsp; &nbsp; &nbsp; Vector3 toPosition = Vector3.zero;&nbsp; &nbsp; &nbsp; &nbsp; float counter = 0;&nbsp; &nbsp; &nbsp; &nbsp; //Get the current position of the object to be moved&nbsp; &nbsp; &nbsp; &nbsp; Vector2 currentThumb = thumbstickTransform.anchoredPosition;&nbsp; &nbsp; &nbsp; &nbsp; while (counter < duration)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; counter += Time.deltaTime;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //Slowly returns thumbstick&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Vector2 tempThumbStickVal = Vector2.Lerp(currentThumb, toPosition, counter / duration);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; joystickInputDirection = tempThumbStickVal;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; thumbstickTransform.anchoredPosition = tempThumbStickVal;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //Slowly returns the target Object to original pos&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; float tempTargetObjAngle = Mathf.Lerp(angle, originalAngle, counter / duration);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rg2d.MoveRotation(tempTargetObjAngle);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; yield return null;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; public float returnTime = 1.0f;&nbsp; &nbsp; public Rigidbody2D rg2d;&nbsp; &nbsp; public bool flipRot = true;&nbsp; &nbsp; const float originalAngle = 0;&nbsp; &nbsp; bool released = true;&nbsp; &nbsp; float angle;&nbsp; &nbsp; Coroutine retCoroutine;&nbsp; &nbsp; void FixedUpdate()&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; if (released)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return;&nbsp; &nbsp; &nbsp; &nbsp; float horizontal = joystickInputDirection.x;&nbsp; &nbsp; &nbsp; &nbsp; float vertical = joystickInputDirection.y;&nbsp; &nbsp; &nbsp; &nbsp; angle = Mathf.Atan2(horizontal, vertical) * Mathf.Rad2Deg;&nbsp; &nbsp; &nbsp; &nbsp; angle = flipRot ? -angle : angle;&nbsp; &nbsp; &nbsp; &nbsp; rg2d.MoveRotation(angle);&nbsp; &nbsp; }}

catspeake

您的函数计算您要查看的点:Vector3 temp = transform.position;temp.x += xMovementRightJoystick;temp.z += zMovementRightJoystick;Vector3 lookDirection = temp - transform.position;此点在 XZ 平面上,这就是汽车绕 Y 轴旋转的原因如果要在 Z 轴上旋转,请像这样计算 XY 平面上的一个点:Vector3 temp = transform.position;temp.x += xMovementRightJoystick;temp.y += zMovementRightJoystick;Vector3 lookDirection = temp - transform.position;PS:我不知道你为什么乘以 Quaternion.Euler(0, 45f, 0) - 这是 Y 轴上的一个恒定角度,它只是意味着每个 lookDirection 将旋转 45 度 - 我必须看到你的场景知道你为什么需要这个......
随时随地看视频慕课网APP
我要回答