【问题标题】:How to rotate locally in Y axis如何在 Y 轴上进行局部旋转
【发布时间】:2021-09-09 11:28:43
【问题描述】:

你好,我在零重力下有像宇航员一样的角色控制,但我想在 y 轴上局部旋转它,但它不能旋转。我尝试在 y 轴上旋转它,但玩家正在相对于世界旋转。我想要它相对于对象。谢谢你的帮助。

这是我的脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;

public class Astronaut : MonoBehaviour
{
    private static AstronautControls astronautControls;
    public Rigidbody rb;
    public float force;
    public float torque;
    public Vector2 move;
    float rotateHorizontal;
    float rotateVertical;
    float upDown;
    public PlayerInput playerInput;

    private void Awake()
    {
        astronautControls = new AstronautControls();
    }


    private void OnEnable()
    {
        astronautControls.Enable();
    }

    private void OnDisable()
    {
        astronautControls.Disable();
    }

    void Start()
    {
        rb = GetComponent<Rigidbody>();
    }

    void FixedUpdate()
    {
        Move();
        MoveUpDown();
        RotateHorizontal();
        RotateVertical();
    }

    private void Move()
    {
        move = playerInput.actions["Move"].ReadValue<Vector2>();
        rb.AddForce(transform.forward * force * move.y * Time.deltaTime);
        rb.AddForce(transform.right * force * move.x * Time.deltaTime);
        rb.AddForce(transform.up * force * upDown * Time.deltaTime);
    }

    private void MoveUpDown()
    {
        upDown = playerInput.actions["MoveVertical"].ReadValue<float>();
        rb.AddForce(transform.up * force * upDown * Time.deltaTime);
    }

    private void RotateHorizontal()
    {
        rotateHorizontal = playerInput.actions["RotateHorizontal"].ReadValue<float>();
        MouseLook.Z += rotateHorizontal;
    }

    //here is the problem when i rotate it seems it has gimbal lock or something i want local rotate relative to the player
    private void RotateVertical()
    {
        rotateVertical = playerInput.actions["RotateVertical"].ReadValue<float>();
        MouseLook.Y += rotateVertical;
    }
}

这是鼠标的样子

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;


public class MouseLook : MonoBehaviour
{
    Mouse mouse;
    public static float X;
    public static float Y;
    public static float Z;
    const float MIN_X = -90f;
    const float MAX_X = 90f;
    const float MIN_Y = -180f;
    const float MAX_Y = 180f;
    public static Vector3 euler;

    public float Sensitivity;
 
    void Awake()
    {
        mouse = Mouse.current;
        euler = transform.rotation.eulerAngles;
        X = euler.x;
        Y = euler.y;
        Z = euler.z;
    }

    void Update()
    {
        X -= mouse.delta.y.ReadValue() * (Sensitivity * Time.deltaTime);
        if (X < MIN_X) X = MIN_X;
        else if (X > MAX_X) X = MAX_X;
        Y += mouse.delta.x.ReadValue() * (Sensitivity * Time.deltaTime);
        if (Y < MIN_Y) Y = MIN_Y;
        else if (Y > MAX_Y) Y = MAX_Y;
        transform.parent.localRotation = Quaternion.Euler(X, Y, Z);
    }
}

我的刚体设置

【问题讨论】:

  • 你能不能不使用RotateAround之类的东西并传入父母的本地transform.Up作为第二个参数? transform.RotateAround(transform.position, parent.transform.up, speed * Time.deltaTime);。其他选项是使用transform.Rotate(0, yRotation, 0, Space.Self);,因为Space.Self 应该会在其本地空间中旋转对象,而不是在世界空间中。
  • 因为它不适合我的上一条评论,所以你可以采取的最后一种方法是将原始角度乘以更改后的角度transform.rotation = originAngle * Quaternion.Euler(xRotationChange, yRotationChange, zRotationChange);

标签: c# unity3d


【解决方案1】:

我提到了一些关于如何在本地空间中旋转对象的解决方案,但我相信应该为您的实现工作的解决方案将是最后一个。为了展示它的工作原理,这里有一个简单的测试脚本:

using UnityEngine;

public class TestScript2 : MonoBehaviour
{
    private float changeInX = 0f;
    private float changeInY = 10f;
    private float changeInZ = 0f;

    private void Update()
    {
        if(Input.GetKey(KeyCode.Space))
        {
            transform.rotation = transform.rotation * Quaternion.Euler(changeInX, changeInY, changeInZ);
        }
    }
}

只要按下Space 键,它就会旋转一个对象。我使用此脚本设置的对象是旋转对象的子对象。这是一个 gif,显示了一个立方体与另一个立方体围绕其局部 Y 轴旋转。

如果您希望所有轴在本地旋转,我相信插入 changeInXchangeInZ 会产生与 gif 相似的结果,其中旋转是在本地应用的。

【讨论】:

  • 您好,感谢您的回答,但我想旋转父对象和子对象。父变换应该继承孩子的旋转,就像当我用鼠标看着孩子相机时,玩家父母也应该反映旋转。并且在更改父级旋转时,子级相机也应更改为父级。
  • @ArtZolinaIII 抱歉误解了你的问题。 sn-p 应该仍然可以工作。而不是改变孩子的旋转,用sn-p改变父母的旋转,孩子,因为它是孩子,不需要做任何事情。
  • 或者我可能仍然对您想要实现的目标感到有些困惑。您是否希望父对象承担子对象的局部旋转,然后让子对象与父对象一起旋转?
  • 是的,我上面的代码在 z 轴上工作,当玩家 y 向上时它也在工作,但是当我用鼠标向下看 45 度时,旋转开始变成本地世界。
  • 你能上传一个 gif 或视频来表达你的意思吗?您是否遇到云台锁定问题?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-02-14
  • 1970-01-01
  • 1970-01-01
  • 2016-10-06
  • 1970-01-01
  • 1970-01-01
  • 2012-08-05
相关资源
最近更新 更多