Unity3D利用欧拉角实现实体的旋转

刚刚入门U3D,也是很多东西搞不懂,最先接触的就是自己尝试去获取键盘上的GetPress之类的事件了吧

官方的API DOC也是帮了不少忙,到处吸收了各位博主的文章也是获益匪浅~

话又说回来,最近遇到的问题就是如何新建一个camera并且利用鼠标四处查看场景,一路试下来发现transform.Rotate不能良好实现这个事件

(PS:Z轴会乱动)

后来发现必须用四元数或者欧拉角来解决,这两个也算是transform里面的几只老虎了

先贴一个看见的视频,关于欧拉角

其实游戏物体的属性视图中调整的角度就是欧拉角,在场景编辑的时候我们对物体进行的旋转都是通过欧拉角来表示的

就像这个(图片引用自☆A希亿)

官方文档有个解释:

--------------------------------------------------------------------------------

Transform.eulerAngles 欧拉角

var eulerAngles : Vector3

Description描述

The rotation as Euler angles in degrees.

旋转为欧拉角度

The x, y, and z angles represent a rotation z degrees around the z axis, x degrees around the x axis, and y degrees around the y axis (in that order).

x、y、z角代表绕z轴旋转z度,绕x轴旋转x度,绕y轴旋转y度

Only use this variable to read and set the angles to absolute values. Don‘t increment them, as it will fail when the angle exceeds 360 degrees. Use Transform.Rotate instead.

仅使用这个变量读取和设置角度到绝对值,不要递增它们。当超过角度360度它将失败。

使用Transform.Rotate替代。

--------------------------------------------------------------------------------

PS:机翻..../滑稽

这很抽象,但是官方文档也给了一个示例代码

 1 using UnityEngine;
 2 using System.Collections;
 3
 4 public class example : MonoBehaviour {
 5     public float yRotation = 5.0F;
 6     void Update() {
 7         yRotation += Input.GetAxis("Horizontal");
 8         transform.eulerAngles = new Vector3(10, yRotation, 0);
 9     }
10     public void Awake() {
11         print(transform.eulerAngles.x);
12         print(transform.eulerAngles.y);
13         print(transform.eulerAngles.z);
14     }
15 }

并且在下面标出了使用的注意事项

Do not set one of the eulerAngles axis separately (eg. eulerAngles.x = 10; ) since this will lead to drift and undesired rotations. When setting them to a new value set them all at once as shown above. Unity will convert the angles to and from the rotation stored in Transform.rotation

不要单独设置欧拉角其中一个轴(例如: eulerAngles.x = 10; )因为这将导致偏移和不希望的旋转。

当设置它们一个新的值时,要同时对整个进行赋值(new Vector3)

因为如果单独进行赋值,可能会出现Gimbal Lock,也就是说的万向节锁(详见上文发的视频)

也就是说,用欧拉角度对一个实体进行旋转,需要按照以下步骤进行:

1.定义XYZ轴的增量变量

2.用Input.GetAxis获取鼠标的X\Y轴偏移量

    注:就如下文代码所说,相对于右手坐标系,我们想获取鼠标的X轴偏移来旋转相机的Yaw也就是Y轴;获取鼠标的Y轴偏移来移动相机的Pitch也就是X轴;

    而且对于鼠标向上移动(Y轴偏移+),那么对需要被旋转的实体来说,它的X轴应该负向旋转,所以在new Vector3的X轴应该写入负的鼠标Y轴偏移

3.对物体的transform.localEulerAngles进行一次性赋值new Vector3,尽量避免单值更改引起万向节锁

4.附加的,可以限制XYZ轴旋转的角度来进一步减少万向节锁的发生概率,并且让视角的移动更贴近于真实(比如说我们在转头看东西时,不转身最多只能看到正负90度内的东西,或者我们抬头角度不超过90度。

    /滑稽 除非你仰过身子倒立看东西23333

贴个代码吧

注意,这个代码就如开头的summary所说,会检测调用它的父级

也就是说你把它加到摄像机上面,移动鼠标,摄像机会跟着旋转

但是你把它只添加到物体上,就只有物体跟着鼠标转,摄像机(你的视角)不会改变

using UnityEngine;
using System.Collections;

/// <summary>
/// 此脚本会检测调用此Component的父级
/// 并将Actions应用到父级上
/// </summary>

[AddComponentMenu("Camera-Control/Mouse Look")]
public class MouseLook : MonoBehaviour
{
    /// <summary>
    /// 枚举:需要旋转的轴
    /// </summary>
    public enum RotationAxes
    {
        MouseXAndY = 0,
        MouseX = 1,
        MouseY = 2
    }
    /// <summary>
    /// 枚举:鼠标按键值
    /// </summary>
    private enum MouseButton
    {
        MouseButton_Left = 0,
        MouseButton_Right = 1,
        MouseButton_Middle = 2
    }
    /// <summary>
    /// 定义轴变量
    /// </summary>
    public RotationAxes axes = RotationAxes.MouseXAndY;
    //鼠标X、Y轴的灵敏度
    public float sensitivityX = 3F;
    public float sensitivityY = 3F;
    private float Damping = 1.5f;
    //X轴最大旋转角度
    public float minimumX = -80F;
    public float maximumX = 80F;
    //Y轴最大旋转角度
    public float minimumY = -60F;
    public float maximumY = 60F;
    //Z轴偏向最大旋转角度
    public float minimumZ =-15F;
    public float maximunZ = 15F;

    //XYZ轴增量
    float deltaMouseRotationX = 0F;
    float deltaMouseRotationY = 0F;
    float deltaRotationZ = 0F;

    //上一个Update时鼠标的XY轴位置
    private Vector3 lastTimePosition;

    void Update()
    {
        if (axes == RotationAxes.MouseXAndY)
        {
            //获取鼠标的X移动增量
            //希望摄像机移动Yaw即Y轴
            deltaMouseRotationX += Input.GetAxis("Mouse X") * sensitivityX * Damping;
            //比较X旋转角度与最大、最小旋转角度限制
            deltaMouseRotationX = Mathf.Clamp(deltaMouseRotationX, minimumX, maximumX);

            //获取鼠标的Y移动增量
            //希望摄像机移动Pitch即X轴
            deltaMouseRotationY += Input.GetAxis("Mouse Y") * sensitivityY * Damping;
            //比较Y旋转角度与最大、最小旋转角度限制
            deltaMouseRotationY = Mathf.Clamp(deltaMouseRotationY, minimumY, maximumY);

            //按住右键时锁定XY轴,仅移动Z轴
            if (Input.GetMouseButton((int)MouseButton.MouseButton_Right))
            {
                //获取鼠标的X移动增量
                //希望摄像机移动Roll即Z轴
                deltaRotationZ += Input.GetAxis("Mouse X") * sensitivityX * Damping;
                deltaRotationZ = Mathf.Clamp(deltaRotationZ, minimumZ, maximunZ);
                transform.localEulerAngles = new Vector3(transform.localEulerAngles.x, transform.localEulerAngles.y, -deltaRotationZ);
            }
            //不按住右键时正常移动视角
            else
            {
                //Transform中的欧拉角需要一次性赋值
                //以防发生万向节锁
                transform.localEulerAngles = new Vector3(-deltaMouseRotationY, deltaMouseRotationX, 0);
                lastTimePosition = transform.localEulerAngles;
                //重置Z轴旋转
                deltaRotationZ = 0f;
            }
        }

        else if (axes == RotationAxes.MouseX)
        {
            transform.Rotate(0, Input.GetAxis("Mouse X") * sensitivityX*Damping, 0);
        }

        else
        {
            deltaMouseRotationY += Input.GetAxis("Mouse Y") * sensitivityY * Damping;
            deltaMouseRotationY = Mathf.Clamp(deltaMouseRotationY, minimumY, maximumY);

            transform.localEulerAngles = new Vector3(-deltaMouseRotationY, transform.localEulerAngles.y, 0);
        }

    }

    void Start()
    {
        // Make the rigid body not change rotation
        if (GetComponent<Rigidbody>())
        {
            GetComponent<Rigidbody>().freezeRotation = true;
            Debug.Log("Rigid Body name:\n" + GetComponent<Rigidbody>().name);
        }
        Cursor.visible = false;
    }
}
时间: 2024-10-10 04:51:05

Unity3D利用欧拉角实现实体的旋转的相关文章

【C#】利用反射构建实体

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data; using System.Reflection; namespace RftToModel { class Program { static void Main(string[] args) { var result = ToModel<TestModel>.GetDelegate_To

利用HttpWebRequest实现实体对象的上传

一 简介 HttpWebRequest和HttpWebResponse类是用于发送和接收HTTP数据的最好选择.它们支持一系列有用的属性.这两个类位 于System.Net命名空间,默认情况下这个类对于控制台程序来说是可访问的.请注意,HttpWebRequest对象不是利用new关键字通过构 造函数来创建的,而是利用工厂机制(factory mechanism)通过Create()方法来创建的.另外,你可能预计需要显式地调用一个“Send”方法,实际上不需要.接下来调用 HttpWebRequ

利用XStream实现实体类与xml的转换

package com.wanhua.util; import com.thoughtworks.xstream.XStream;import com.thoughtworks.xstream.io.xml.DomDriver; /** * 利用XStream实现实体类与xml的转换 *  * @author w_xfpenga *  *         2014-11-27 */public class XStream2Text { static XStream xStream = new X

利用Button实现移动, 缩放, 旋转, 重置等功能.

在UIView里面有一个叫做Button的View, 这个控件简单来说就是点击, 就是手机上我们一切可以点击的东西都是Button, 现在我们利用这一个控件来实现上面等更能. PS: 方法和注释都在文件工程里面, 你们可以下载下来运行一下试试, 这里我就只写代码了. 关于怎么使用UIButton, 各位可以去百度一下, 有专门视频讲解, 这里贴图比较麻烦, 不好操作, 请谅解. ViewController.h声明所有的方法. #import <UIKit/UIKit.h> @interfac

eigen 中四元数、欧拉角、旋转矩阵、旋转向量

一.旋转向量 1.0 初始化旋转向量:旋转角为alpha,旋转轴为(x,y,z) Eigen::AngleAxisd rotation_vector(alpha,Vector3d(x,y,z)) 1.1 旋转向量转旋转矩阵 Eigen::Matrix3d rotation_matrix;rotation_matrix=rotation_vector.matrix(); Eigen::Matrix3d rotation_matrix;rotation_matrix=rotation_vector.

Unity3D 利用FSM设计相机跟随实现

笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,国家专利发明人;已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D实战核心技术详解>电子工业出版社等. CSDN视频网址:http://edu.csdn.net/lecturer/144 FSM有限状态机前面已经跟读者介绍过,使用Unity3D引擎实现了动作状态以及技能切换,FSM使用的条件是有限个状态切换,我们可以将FSM应用到相机中,很多人会问在相机中如何使用FS

利用CSS3给图片添加旋转背景特效

首先看旋转特效:http://www.w2bc.com/demo/201512/2015-12-09-css3-image-hover-animate/index.html 这是一款纯CSS3实现的当鼠标滑过图片时文字旋转动画特效,效果图如下: 实现代码: <div class="main">       <div class="view">           <img src="images/modeo02.jpg&quo

Unity3d利用opencv保存游戏视频

脚本MyVideoWriter.cs using UnityEngine; using System.Collections; using OpenCvSharp; using OpenCvSharp.CPlusPlus; using System.IO; /*author:bluebeandate:2016.8.8all rights reserved*/ public class MyVideoWriter : MonoBehaviour { VideoWriter writer; int

Unity3D利用Logcat调试安卓

发布安卓包之后再次测试发生什么问题很难知道怎么了,比如说出现闪退等情况,可以用Logcat检测到,logcat是Android中一个命令行工具,可以用于得到程序的log信息,可以用 logcat 命令来查看系统日志缓冲区的内容. 用模拟器运行安卓程序或者真机也可以进行测试. 它的位置在SDK/platform-tools中. 指令格式   [adb] logcat [<option>] ... [<filter-spec>] ... option部分 V - Verbose (lo