第十三章 Unity 移动和旋转(上)

这篇具有很好参考价值的文章主要介绍了第十三章 Unity 移动和旋转(上)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

移动和旋转是游戏对象最频繁地操作。我们上个章节简单介绍了Cube的移动和旋转。移动是修改transform的position属性,旋转是修改transform的eulerAngles(欧拉角)属性,两者属性值均可以使用Vector3向量来实现。需要大家注意的是,transform.forward和Vector3.forward的区别(参考坐标系是不一样的)。接下来,我们使用transform的Translate方法来进行移动。首先,我在重新创建一个“SampleScene4”场景。我们在该创建中同样创建一个“Cube”游戏对象和“CubeTranslate.cs”脚本文件,并附加两者在一起。

第十三章 Unity 移动和旋转(上)

 第十三章 Unity 移动和旋转(上)

以下是脚本代码内容

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

public class CubeTranslate : MonoBehaviour
{

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.W))
        {
            transform.Translate(new Vector3(0, 0, 1));
        }

        // 向左旋转45度
        if (Input.GetKeyDown(KeyCode.Q))
        {
            transform.eulerAngles += new Vector3(0, -45, 0);
        }

        // 向右旋转45度
        if (Input.GetKeyDown(KeyCode.E))
        {
            transform.eulerAngles += new Vector3(0, 45, 0);
        }
    }
}

我们实现的功能还是之前的一样,按下“W”键向前移动。为了方便观察Cube的移动,我们需要将相机放置Cube的正上方“俯视”Cube。摄像机修改参数如下:

第十三章 Unity 移动和旋转(上)

为什么要修改成这些数值,我们上一个章节介绍过了,修改后效果如下:

第十三章 Unity 移动和旋转(上)

然后,我们Play工程,查看运行结果。

测试结果就是相对于本地坐标系的移动,也就是游戏对象的正前方移动。

第十三章 Unity 移动和旋转(上)

 第十三章 Unity 移动和旋转(上)

 第十三章 Unity 移动和旋转(上)

很明显,默认情况下,Translate(Vector3(0, 0, 1))方法与transform.forward是等效的,也就是相对于本地坐标系而言。那么,如何改成世界坐标系的移动呢,不受游戏物体旋转影响呢?

其实该方法还有第二个参数,也就是Space.Self本地坐标系和Space.World世界坐标系。

显然,如果我们不填写第二个参数的话,默认就是Space.Self本地坐标系,我们改一下

        if (Input.GetKeyDown(KeyCode.W))
        {
            //transform.Translate(new Vector3(0, 0, 1));
            transform.Translate(new Vector3(0, 0, 1), Space.World);
        }

接下来,我们在重新测试,发现现在的移动就是相对于世界坐标系的啦,截图就不添加了。总结:游戏对象的移动可以通过在transform.translate()方法实现,也可以直接修改transform.position属性。这里需要区分的是世界坐标系还是自身坐标系。如下:

世界坐标系z轴前进:transform.position += vector3.forward
自身坐标系z轴前进:transform.position += transform.forward
世界坐标系z轴前进:transform.translate(vector3.forward, space.world)
自身坐标系z轴前进:transform.translate(vector3.forward, space.self)

如果是space.world的话,还可以使用transform.forward;但是最好不要将transform.forward应用到space.self上。因此还是建议translate方法+ vector3向量搭配使用进行移动。

接下来,我们来说一说旋转,这个是比较复杂的。我们之前的旋转是通过修改transform的eulerAngles(欧拉角)实现的。但是,在我们的印象中,游戏对象的旋转应该是rotation属性,尤其是在Inspector检视面板中,我们也能够看到这个名字的属性。例如下面的截图就是我们对摄像机对象做的旋转设置,也就是在X轴方向上面旋转90度。请注意,此时的参考坐标系是父对象,如果没有父对象就是世界坐标系。

第十三章 Unity 移动和旋转(上)

因此,显而易见这是欧拉角数值。但是在Unity API中,这个rotation属性是一个四元数(Quaternion)。关于四元数的概念以及它相对于欧拉角的优势,我们这里不在介绍,它唯一的缺点就是不如欧拉角简单直观。因此,我们往往借助欧拉角转换成四元数再控制游戏对象旋转。接下来,我们修改一下代码,如下所示:

        // 向左旋转45度
        if (Input.GetKeyDown(KeyCode.Q))
        {
            //transform.eulerAngles += new Vector3(0, -45, 0);
            transform.rotation = Quaternion.Euler(new Vector3(0, -45, 0));
        }

        // 向右旋转45度
        if (Input.GetKeyDown(KeyCode.E))
        {
            //transform.eulerAngles += new Vector3(0, 45, 0);
            transform.rotation = Quaternion.Euler(new Vector3(0, 45, 0));
        }

上面的代码实现了“Q”和“E”键分别向左右两方向按照45度单位的旋转。但是当我们运行当前工程的时候,发现它并不能连续旋转,而只是旋转一下就停止了。我们很容易想到使用“+=”操作符,但是很遗憾的是,transform.rotation并不支持这样的运算。因此,我们只能换一种方式来解决这个问题,我们可以使用一个类全局变量来存储游戏对象的旋转数据。

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

public class CubeTranslate : MonoBehaviour
{
    // Y轴旋转角度值
    private float y = 0.0f;

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.W))
        {
            //transform.Translate(new Vector3(0, 0, 1));
            transform.Translate(new Vector3(0, 0, 1), Space.World);
        }

        // 向左旋转45度
        if (Input.GetKeyDown(KeyCode.Q))
        {
            //transform.eulerAngles += new Vector3(0, -45, 0);
            //transform.rotation = Quaternion.Euler(new Vector3(0, -45, 0));

            y -= 45;
            transform.rotation = Quaternion.Euler(new Vector3(0, y, 0));
        }

        // 向右旋转45度
        if (Input.GetKeyDown(KeyCode.E))
        {
            //transform.eulerAngles += new Vector3(0, 45, 0);
            //transform.rotation = Quaternion.Euler(new Vector3(0, 45, 0));

            y += 45;
            transform.rotation = Quaternion.Euler(new Vector3(0, y, 0));
        }
    }
}

重新运行后,我们发现Cube可以进行“连续性”的旋转了,如下Gif图所示:

第十三章 Unity 移动和旋转(上)

我们发现使用transform.rotation进行旋转的话,还是比较费劲的。但是,有一点大家要明白,这里的旋转和上面的移动是相同的道理,同样存在世界坐标系和局部坐标系的前提条件。这个当然取决于我们使用Vector3类还是使用Transform类。接下来我们就使用transform提供的Rotate方法来进行旋转,它的参数是欧拉角,比较容易让人直观的理解,而且也提供了坐标系参数的指定(Space.Self或者Space.World,当然默认还是Space.Self)。

        // 向左旋转45度
        if (Input.GetKeyDown(KeyCode.Q))
        {
            //transform.eulerAngles += new Vector3(0, -45, 0);
            //transform.rotation = Quaternion.Euler(new Vector3(0, -45, 0));

            //y -= 45;
            //transform.rotation = Quaternion.Euler(new Vector3(0, y, 0));

            transform.Rotate(new Vector3(0, -45, 0));
        }

        // 向右旋转45度
        if (Input.GetKeyDown(KeyCode.E))
        {
            //transform.eulerAngles += new Vector3(0, 45, 0);
            //transform.rotation = Quaternion.Euler(new Vector3(0, 45, 0));

            //y += 45;
            //transform.rotation = Quaternion.Euler(new Vector3(0, y, 0));

            transform.Rotate(new Vector3(0, 45, 0));
        }

我们发现transform.Rotate使用起来就比较简单了。当我们Play当前工程之后,我们就发现效果和之前是一样的(可以连续的旋转,而不是只旋转一下)。但是,请大家明白的是,之前的旋转是相对于世界坐标系的Y轴,现在的旋转是相对于游戏对象本地坐标系的Y轴,之所以效果一样是,是因为两者坐标系重合了而已。

第十三章 Unity 移动和旋转(上)

从Scene视图中我们可以看到,Cube对象坐标系和世界坐标系是一致的。接下来,我们调整Cube,让两个坐标系不一致,我们让Cube沿着Z轴顺时针旋转90度,也就是修改Cube的Inspector视图中的Rotation中的Z值为“-90”,效果如下所示:

第十三章 Unity 移动和旋转(上)

 第十三章 Unity 移动和旋转(上)

为什么“-90”度是顺时针旋转呢?这个取决于我们的观察方向。在默认的左手坐标系下,负值就是顺时针旋转;当然右手坐标系下,正值是顺时针旋转。此时世界坐标系的Y轴仍然是向上的方向,而游戏对象Cube的Y轴是向右的。那么,此时如果我们让Cube在Y轴上按照两个不同坐标系进行旋转的话,那肯定是不一样了。为了能够看到这个效果,我们修改摄像机的位置参数,从侧面观察cube的旋转。

第十三章 Unity 移动和旋转(上)

然后(保持相机选中状态)我们点击菜单栏“GameObject”->“Align View to Selected”

第十三章 Unity 移动和旋转(上)

此时,我们的Scene视角与Game视角一致。如果是本地坐标系的话,Y轴是向里的。因此围绕它旋转的话,Cube应该是类似“车轮滚动”的方式进行旋转。

// 向左旋转45度
transform.Rotate(new Vector3(0, -45, 0));

// 向右旋转45度
transform.Rotate(new Vector3(0, 45, 0));

然后我们Play工程,查看运行结果,Gif图如下

第十三章 Unity 移动和旋转(上)

如果是世界坐标系的话,Y轴是向上的。如果它应该是“陀螺”旋转的方式。

//transform.Rotate(new Vector3(0, -45, 0));
transform.Rotate(new Vector3(0, -45, 0), Space.World);

//transform.Rotate(new Vector3(0, 45, 0));
transform.Rotate(new Vector3(0, 45, 0),Space.World);

我们直接Play工程,查看Gif效果图吧

第十三章 Unity 移动和旋转(上)文章来源地址https://www.toymoban.com/news/detail-454206.html

到了这里,关于第十三章 Unity 移动和旋转(上)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 第十三章 python之爬虫

    Python基础、函数、模块、面向对象、网络和并发编程、数据库和缓存、 前端、django、Flask、tornado、api、git、爬虫、算法和数据结构、Linux、设计题、客观题、其他

    2024年02月04日
    浏览(54)
  • [C国演义] 第十三章

    力扣链接 根据题目要求: 返回的数对应的下标各不相同 三个数之和等于0 不可包含重复的三元组 – – 即 顺序是不做要求的 如: [-1 0 1] 和 [0, 1, -1] 是同一个三元组 输出答案顺序不做要求 暴力解法: 排序 + 3个for循环 + 去重 — — N^3, 肯定超时 优化: 排序 + 双指针 + 去重 — —

    2024年02月08日
    浏览(40)
  • NodeJs第十三章 cookie

    假设服务器有一个接口,通过请求这个接口,可以添加一个管理员 但是,不是任何人都有权力做这种操作的 那么服务器如何知道请求接口的人是有权力的呢? 答案是:只有登录过的管理员才能做这种操作 可问题是,客户端和服务器的传输使用的是http协议,http协议是无状态

    2024年01月19日
    浏览(34)
  • 《微服务实战》 第十三章 JWT

    【项目实战】Spring boot整合JWT、Vue案例展示用户鉴权 【微服务实战】JWT JSON Web Token(JWT)是目前最流行的跨域身份验证解决方案。 基于JSON的开发标准 用户信息加密到token里,服务器不保存任何用户信息 在传统的用户登录认证中,因为http是无状态的,所以都是采用session方式

    2024年02月06日
    浏览(76)
  • 精读《图解密码技术》——第十三章 PGP

      PGP是一款由个人编写的密码软件,PGP是为了保护处于极端状况下的人们的隐私而开发的,如果这些人的信息被窃听,那么可能是性命攸关的大事件。   OpenPGP是对密文和数字签名格式进行定义的标准规格。   GNU Privacy Guard ( GnuPG、GPG)是一款基于OpenPGP标准开发的密码学

    2024年02月05日
    浏览(54)
  • 第十三章_Redis中的BigKey

    MoreKey案例 大批量往redis里面插入2000W测试数据key  Linux Bash下面执行,插入100W # 生成100W条redis批量设置kv的语句(key=kn,value=vn)写入到/tmp目录下的redisTest.txt文件中 for((i=1;i=100*10000;i++)); do echo \\\"set k$i v$i\\\" /tmp/redisTest.txt ;done; 通过redis提供的管道--pipe命令插入100W大批量数据 结合自己

    2024年02月03日
    浏览(44)
  • 第十三章,枚举与泛型例题

    例题1 结果   例题2 结果   例题3 结果     例题4 结果 例题5  结果 例题6  结果 例题7  结果 例题8  结果

    2024年02月06日
    浏览(47)
  • 第十三章 opengl之模型(导入3D模型)

    使用Assimp并创建实际的加载和转换代码。Model类结构如下: Model类包含一个Mesh对象的vector,构造器参数需要一个文件路径。 构造器通过loadModel来加载文件。私有函数将会处理Assimp导入过程中的一部分,私有函数还存储了 文件路径的目录,加载纹理时会用到。 Draw函数的作用:

    2024年02月05日
    浏览(48)
  • Vue3——第十三章(插槽 Slots)

    这里有一个 FancyButton 组件,可以像这样使用: 而 FancyButton 的模板是这样的: slot 元素是一个插槽出口 (slot outlet),标示了父元素提供的插槽内容 (slot content) 将在哪里被渲染。 最终渲染出的 DOM 是这样: 通过使用插槽, FancyButton 仅负责渲染外层的 button (以及相应的样式),而

    2024年02月07日
    浏览(55)
  • 《c++ primer笔记》第十三章 拷贝控制

    1.1拷贝构造函数 ​ 如果一个构造函数的第一个参数是自身类类型的 引用 ,且任何额外参数都由默认值,则此构造函数成为拷贝构造函数。 拷贝构造函数在某些情况下会被隐式地使用,所以不能定义为 expicit 。 合成拷贝构造函数 ​ 合成某某函数 一般出现在我们没定义该函

    2023年04月25日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包