本文系作者原创,转载请注明出处

刚刚入门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:机翻..../滑稽

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

 using UnityEngine;
 using System.Collections;

 public class example : MonoBehaviour {
     public float yRotation = 5.0F;
     void Update() {
         yRotation += Input.GetAxis("Horizontal");
         transform.eulerAngles = , yRotation, );
     }
     public void Awake() {
         print(transform.eulerAngles.x);
         print(transform.eulerAngles.y);
         print(transform.eulerAngles.z);
     }
 }

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

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,
        MouseX,
        MouseY
    }
    /// <summary>
    /// 枚举:鼠标按键值
    /// </summary>
    private enum MouseButton
    {
        MouseButton_Left = ,
        MouseButton_Right = ,
        MouseButton_Middle =
    }
    /// <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 = );
                lastTimePosition = transform.localEulerAngles;
                //重置Z轴旋转
                deltaRotationZ = 0f;
            }
            Debug.Log("到处看!");
        }
        if (axes == RotationAxes.MouseX)
        {
            //获取鼠标的X移动增量
            //希望摄像机移动Yaw即Y轴
            deltaMouseRotationX += Input.GetAxis("Mouse X") * sensitivityX * Damping;
            //比较X旋转角度与最大、最小旋转角度限制
            deltaMouseRotationX = Mathf.Clamp(deltaMouseRotationX, minimumX, maximumX);
            transform.localEulerAngles = , deltaMouseRotationX, );
            Debug.Log("移动鼠标X轴!左右看!");
        }
        if (axes == RotationAxes.MouseY)
        {
            //获取鼠标的Y移动增量
            //希望摄像机移动Pitch即X轴
            deltaMouseRotationY += Input.GetAxis("Mouse Y") * sensitivityY * Damping;
            //比较Y旋转角度与最大、最小旋转角度限制
            deltaMouseRotationY = Mathf.Clamp(deltaMouseRotationY, minimumY, maximumY);
            transform.localEulerAngles = , );
            Debug.Log("移动鼠标Y轴!上下看!");
        }

    }

    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;
    }
}

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

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

    一 简介 HttpWebRequest和HttpWebResponse类是用于发送和接收HTTP数据的最好选择.它们支持一系列有用的属性.这两个类位 于System.Net命名空间,默认情况下这个类对 ...

  2. DataReader,DataTable利用泛型填充实体类

    using System; using System.Collections.Generic; using System.Linq; using System.Web; /// <summary ...

  3. 利用neon技术对矩阵旋转进行加速

    一般的矩阵旋转操作都是对矩阵中的元素逐个操作,假设矩阵大小为m*n,那么时间复杂度就是o(mn).如果使用了arm公司提供的neon加速技术,则可以并行的读取多个元素,对多个元素进行操作,虽然时间复杂 ...

  4. unity3D 使用欧拉角控制视野注意点

    变量声明: public PlayerInput p; //表示控制代码用来获得用户是否按下 public float rotateSpeed = 50f; //旋转速度 private GameOb ...

  5. 使用hibernate利用实体类生成表和利用表生成实体类

    1,配置数据库,这里以oracle数据库为例.点击右侧Database图标:

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

    一.旋转向量 1.0 初始化旋转向量:旋转角为alpha,旋转轴为(x,y,z) Eigen::AngleAxisd rotation_vector(alpha,Vector3d(x,y,z)) 1. ...

  7. [Unity3D]利用Raycast实现物体的选择与操作

    本文系作者原创 转载请注明出处 如果是一个2D的平面项目或者说需要在三维空间选择一个物体时(经常表现为抓取物件),我们需要用到Raycast事件 那么首先先说说什么是Raycast 按照字面上来理解的 ...

  8. Unity3D 利用NGUI2.6.3做技能冷却的CD效果

    转自http://blog.csdn.net/qqmcy/article/details/9469021 NGUI非常强大我们今天来学习一下,如何利用NGUI做技能冷却的CD效果.先导入NGUI的插件 ...

  9. Unity3D 之防止刚体碰撞导致旋转

    有时候两个刚体发生碰撞的时候,其中一个质量小的会有发生旋转的情况 如果遇到这样的情况,只需要给刚体添加一个约束就行了. 添加这个就行了.

随机推荐

  1. SQL Server中TOP子句可能导致的问题以及解决办法

    简介      在SQL Server中,针对复杂查询使用TOP子句可能会出现对性能的影响,这种影响可能是好的影响,也可能是坏的影响,针对不同的情况有不同的可能性.      关系数据库中SQL语句只 ...

  2. 从零开始编写自己的C#框架(1)——前言

    记得十五年前自学编程时,拿着C语言厚厚的书,想要上机都不知道要用什么编译器来执行书中的例子.十二年前在大学自学ASP时,由于身边没有一位同学和朋友学习这种语言,也只能整天混在图收馆里拼命的啃书.而再后 ...

  3. EasyUI中那些不容易被发现的坑——EasyUI重复请求2次的问题

    问题控件:datagrid.combobox.所有能设置url属性的控件 问题版本:1.4.4.1.4.5(之前的版本没测) 问题如图: 重复请求2次,错误代码如图: 错误问题分析:html加载的时候 ...

  4. 1.C#WinForm基础制作简单计算器

    利用c#语言编写简单计算器: 核心知识点: MessageBox.Show(Convert.ToString(comboBox1.SelectedIndex));//下拉序号 MessageBox.S ...

  5. 一个由Response.Redirect 引起的性能问题的分析

    现象: 某系统通过单点登录(SSO) 技术验证用户登录.用户在SSO 系统上通过验证后,跳转到某系统的主页上面.而跳转的时间很长,约1分钟以上. 分析步骤: 在问题复现时抓取Hang dump 进行分 ...

  6. LinqToDB 源码分析——生成与执行SQL语句

    生成SQL语句的功能可以算是LinqToDB框架的最后一步.从上一章中我们可以知道处理完表达式树之后,相关生成SQL信息会被保存在一个叫SelectQuery类的实例.有了这个实例我们就可以生成对应的 ...

  7. 百度编辑器UEditor与UEditor 公式插件完整Demo

    1.下载UEditor(我的是.net项目) 2.下载UEditor公式插件 3.新建解决方案和项目 4.在浏览器中预览index.html页面 结果: 5.index.html源码 <!DOC ...

  8. 2016年最新mac下vscode配置golang开发环境支持debug

    网上目前还找不到完整的mac下golang环境配置支持,本人配置成功,现在整理分享出来. mac最好装下xcode,好像有依赖关系安装Homebrew打开终端窗口, 粘贴脚本执行/usr/bin/ru ...

  9. Mybatis配置一对多的关联关系(五)

    问题:是查询一个部门中的员工? 一.web项目构架 二.lib文件的jar 三.配置大小配置和该工具类 1大配置mybatis-config.xml <?xml version="1. ...

  10. jquery瀑布流的制作

    首先,还是来看一下炫酷的页面: 今天就边做边说了: 一.准备工作 新建css,js,img文件夹存放相应文件,并在demo.html文件中引入外部文件(注意要把jquery文件引入),这里就不过多描述 ...