Unity - 虚拟操纵杆 - 相机旋转

Unity - Virtual Joystick - Camera rotation

我有一个虚拟运动操纵杆,我用它来控制播放器对象的运动,它工作正常,代码如下。

我遇到的问题是当我在游戏模式(或设备)中旋转相机时,方向没有根据相机旋转进行调整,就像 this post 中所示我仔细查看以尝试理解问题所在。

我意识到我需要围绕相机面向的前进方向旋转我的运动,我试图用底部的代码片段来做,但是当玩家对象移动得非常快并且最终统一变得无响应时,这会产生非常奇怪的行为,所以我猜有些东西乘错了。

有人能指出我哪里错了吗? ta !
编辑 - 修改为可能的答案

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using EasyJoystick; 


public class NewJoystick : MonoBehaviour
{
    [SerializeField] private float speed;
    [SerializeField] private Joystick1 joystick; 
    [SerializeField] Camera MainCam;
    private Rigidbody RB;
    private Transform cameraTransform; 
     // Start is called before the first frame update
    void Start()
    {
         cameraTransform = MainCam.transform; 
        
        
    }
    void Awake()
    {
         RB = gameObject.GetComponent<Rigidbody>();

    }

    // Update is called once per frame
    void Update()
    {
        
        float xMovement = joystick.Horizontal();
        float zMovement = joystick.Vertical();  
        Vector3 inputDirection = new Vector3(xMovement, 0, zMovement);
        //Get the camera horizontal rotation
        Vector3 faceDirection = new Vector3(cameraTransform.forward.x, 0, cameraTransform.forward.z);
        //Get the angle between world forward and camera
        float cameraAngle = Vector3.SignedAngle(Vector3.forward, faceDirection, Vector3.up);
        //Finally rotate the input direction horizontally by the cameraAngle
        Vector3 moveDirection = Quaternion.Euler(0, cameraAngle, 0) * inputDirection;
        RB.velocity  = moveDirection * speed;

        
    }
}

我在更新循环中试过了 -

  var Direction = transform.position += new Vector3(xMovement, 0f,zMovement);  //* speed * Time.deltaTime; 
        Vector3 newDir = MainCam.transform.TransformDirection(Direction); 
        transform.position += new Vector3(newDir.x, 0f,newDir.z) * speed * Time.deltaTime; 

好吧,这是一个简单的解决方法。至少我是这样做的,而且从那以后似乎一直有效。

首先,您需要像您一样获得操纵杆输入。两个轴的输入值都应介于 -1 和 1 之间。这实际上决定了方向本身,因为水平轴为您提供矢量的 X 坐标,而垂直轴为您提供该矢量的 Y 坐标。你可以很容易地想象它:

注意,我只是在那里设置了一些随机值,但你明白了。

Now, your problem is, that this angle you get from your raw input is static in direction, meaning that it doesn't rely on the camera's face direction. You can solve this problem by "locking it to the camera", or in other words, rotate the input direction based on the camera rotation. Here's a quick example:

//Get the input direction
float inputX = joystick.Horizontal();
float inputY = joystick.Vertical();
Vector3 inputDirection = new Vector3(inputX, 0, inputY);

//Get the camera horizontal rotation
Vector3 faceDirection = new Vector3(cameraTransform.forward.x, 0, cameraTransform.forward.z);

//Get the angle between world forward and camera
float cameraAngle = Vector3.SignedAngle(Vector3.forward, faceDirection, Vector3.up);

//Finally rotate the input direction horizontally by the cameraAngle
Vector3 moveDirection = Quaternion.Euler(0, cameraAngle, 0) * inputDirection;

IMPORTANT: The code above should be called in the Update cycle, since that is where you get the input information.

在此之后,您可以使用 moveDirection 来移动您的播放器。 (我建议使用物理来移动,而不是修改它的位置)

简单移动示例:

public RigidBody rigidbody;
public Vector3 moveDirection;
public float moveSpeed = 5f;

void FixedUpdate()
{
   rigidbody.velocity = moveDirection * moveSpeed;
}