用Unity实现Minecraft中的镜头控制

在学习Unity的过程中,最基本而又最重要的一部分就是镜头控制(Camera Control)。

镜头控制就是通过鼠标、键盘等输入设备的操作,来实现在游戏中的导航。在Unity中的本质是通过接收鼠标的移动和键盘的按键,来变换相机对象(Camera)的位置(position)和旋转(rotation),这两个值位于camera的transform组件(conponent)中。

在这里我们通过实现《我的世界》中创造模式的镜头控制方式来学习第一人称的镜头控制。

在我的世界中,镜头的朝向(旋转)是通过鼠标在X和Y方向的平移来控制的,镜头的前后左右移动是通常的WASD键,升起(向上移动)为空格键,降落(向下移动)为Shift键。

下面我先给出完整代码和Demo的建立步骤。运行成功后,我们再进行代码剖析。

建立Demo

1. 新建一个Unity项目。

2. 将下面代码保存为BasicCameraControl.cs,放到Unity项目的Assets文件夹下。

using UnityEngine;
using System.Collections;

public class BasicCameraControl : MonoBehaviour
{
    float yaw = 0;         // 偏航角,绕Y轴旋转的角度
    float pitch = 0;       // 俯仰角,绕Z轴旋转的角度
    const float roll = 0;  // 翻滚角,绕X轴旋转的角度

    void FixedUpdate ()
    {
        // Move forward or backward
        if (Input.GetKey (KeyCode.W))
            transform.position += Vector3.ClampMagnitude (transform.forward, 0.1f);
        else if (Input.GetKey (KeyCode.S))
            transform.position -= Vector3.ClampMagnitude (transform.forward, 0.1f);

        // Move left or right
        if (Input.GetKey (KeyCode.A))
            transform.position -= Vector3.ClampMagnitude (transform.right, 0.1f);
        else if (Input.GetKey (KeyCode.D))
            transform.position += Vector3.ClampMagnitude (transform.right, 0.1f);

        // Move up or down
        if (Input.GetKey (KeyCode.Space))
            transform.position += new Vector3 (0, 0.1f, 0);
        else if (Input.GetKey (KeyCode.LeftShift))
            transform.position -= new Vector3 (0, 0.1f, 0);

        // Rotate
        pitch -= Input.GetAxis ("Mouse Y") * 5;
        pitch = Mathf.Clamp (pitch, -90, 90);
        yaw += Input.GetAxis ("Mouse X") * 5;
        transform.rotation = Quaternion.Euler (pitch, yaw, roll);
    }
}

3. 为场景中的默认相机对象(Main Camera)添加此脚本组件。具体做法为,选择Main Camera,在Inspector中点击底部的Add Component按钮,点击Scripts菜单,点击Basic Camera Control完成。

4. 在场景的中心位置添加一些物体作为移动相机时的参照,比如一个正方体(Cube)。

5. 点击Play按钮,移动鼠标进行转向,按下WASD、空格和Shift进行移动。

建立Demo

1. 镜头平移控制

镜头的平移实际上是在检测到键盘上WASD、空格、Shift的按下后,修改camera.transform.positon的x, y, z分量。

在这里我们需要注意的是,y分量也就是升起和降落,是永远平行于世界坐标系的y轴的,所以直接修改y分量即可:

transform.position -= new Vector3 (0, 0.1f, 0);

但是对于前进后退和左右平移是不一样的,因为我们在这四个方向的移动还和我们面朝的方向有关。所以我们通过tansform.forward和transform.right获取朝向然后与与transform.position进行加减。

使用Vector3.ClampMagnitude()函数是为了减慢移动速度到合适的程度。

2.镜头旋转控制

关于镜头的旋转我们或许可以用下面的一行代码实现:

transform.Rotate (- Input.GetAxis ("Mouse Y") * 5, Input.GetAxis ("Mouse X") * 5, 0);

但是这样无法保证我们的镜头始终与地面保持垂直。通过在屏幕上不断地画圆圈,我们可以实现倒立。我们不是杂技团,所以这肯定不是我们想要的。

为了避免这种情况发生,我们通过先对旋转角的分量进行偏移,然后再用Quaternion.Euler()函数转换为四元数即可。

3.为什么用FixedUpdate()

Update()与FixedUpdate()的区别是Update()是随渲染(Render)过程发生的。而FixedUpdate()是按照固定的周期发生的,也就是说即使由于画面上人物众多,刷新率降低,也能保证函数执行的次数恒定。

了解到这些,我们就可以设想。假如我们在Minecraft中进行一场赛跑,一台高配台式电脑以60FPS运行,而一台笔记本以平均30FPS运行。如果我们用Update()来驱动人物运动的话,那么笔记本上的人物肯定移动没有台式机快。这样肯定不符合公平的原则,所以我们在这里必须使用FixedUpdate()。

【End】

时间: 2024-12-28 16:43:14

用Unity实现Minecraft中的镜头控制的相关文章

Unity实现游戏中摄像机视角控制

using UnityEngine; using System.Collections; public class NewCamera : MonoBehaviour { public GameObject cameraFather; public Transform target; public float rotatespeed; public float scalespeed; public float min; public float max; public Transform obj

unity中camera摄像头控制详解

目录 1. 缘起 2. 开发 2.1. 建立项目 2.2. 旋转 2.2.1. 四元数 2.3. 移动 2.3.1. 向量操作 2.4. 镜头拉伸 2.5. 复位 2.6. 优化 1 缘起 我们的产品是使用unity开发水利BIM(水利建筑信息模型),项目中需要控制摄像 头对模型进行360度查看,请注意所有操作都是移动摄像头,不是移动模型.摄 像头能进行移动.旋转.改变焦距操作,类似于SketchUp的控制操作: 摄像头移动时,根据当前旋转方向(Rotation)进行移动 摄像头距离模型越远,摄

Unity 4.0 中的新动画系统——MecAnim

分享一个文档资料,关于动画系统的,版本应该很老了,但是有借鉴意义的: Unity 4.0 已于 2012 年 11 月 15 日正式发布,Unity 每一次版本的提升,都给游戏开发者带来惊喜,这一次也不例外,该版本最大变化之一就是引入了新动画系统--MecAnim,通过 MecAnim 新的动画系统,开发者在 Unity 中可以非常方便地实现角色动画.所以 Unity 4.0 的启动画面都突出了新的动画系统这一最新功能  . 这里需要说明的是,在 Unity 4.0 中,开发者还是可以使用原有的

PHP中的流程控制

PHP中的流程控制: 任何PHP脚本都是由一系列的语句构成.一条语句可以是一个赋值语句,一个函数调用,一个循环,一个条件语句或者甚至是一个什么也不做的语句(空语句).语句通常以分号结束.此外还可以用花括号将一组语句封装成一个语句组.语句本省可以当作是一行语句. if语句 if结构是很多语言包括php在内最重要的特性之一,他允许按照条件执行代码片段.php的if结构和C语言相似: <?phpif($a > $b) echo"a is bigger than b"; ?>

第04章 程序设计中的流程控制

/**第四章 程序设计中的流程控制 @选择语句 形式一:if(条件表达式) 单条语句; 形式二:if(条件表达式){ 语句体;} 形式三:if(条件表达式){ 语句体;}else{ 语句体;} 形式四:if(条件表达式){ 语句体;}else if{ 语句体;} 形式五:if(条件表达式){ 语句体;}else if{ 语句体;}else{ 语句体;}=========================================================================

在YARN中,如何控制和监控map/reduce的并发数

配置建议: 1.     In MR1, the mapred.tasktracker.map.tasks.maximum and mapred.tasktracker.reduce.tasks.maximum properties dictated how many map and reduce slots each TaskTracker had. These properties no longer exist in YARN. Instead, YARN uses yarn.nodema

xcode6中导航栏 控制view用程序编写

1.新建个视图控制器用来管理视图 2.新建个按钮 通过按钮把新的view压入栈中 爽歪歪是个按钮  一点击它  直接进入第二界面   在第二界面自动生成个返回按钮 xcode6中导航栏 控制view用程序编写,布布扣,bubuko.com

&lt;实训|第九天&gt;掌握linux中普通的权限控制和三种特殊的权限(sst),做合格的运维工程师

linux中,权限的学习是必不可少的,不论是作为一名运维工程师或者是单一的管理者,学习好linux中的权限控制,你就可以保护好自己的隐私同时规划好你所管理的一切. 权限的学习是很多的,不要认为自己已经把自己的隐私保护的很好,漏洞总是有的,侧面的攻击往往是难以防守的.所以大家跟我一起学习一下基础的权限控制,在后面也会有更多关于权限控制的知识点分享出来.谢谢各位的关注和支持!  开班第九天: 今天的课程大纲: linux系统中文件目录的基本权限控制 如何来修改默认的生成权限 三种特殊的权限(s,s,

Java实战之03Spring-05Spring中的事务控制(基于AOP)

五.Spring中的事务控制(基于AOP) 1.Spring中事务有关的接口 1.1.明确: JavaEE体系进行分层开发,事务处理位于业务层,Spring提供了分层设计业务层的事务处理解决方案 1.2.Spring事务管理主要包括3个接口 1.2.1.PlatformTransactionManager事务管理器 具体实现类: 1.2.2.TransactionDefinition事务定义信息 事务的隔离级别: 事务的传播行为:有时面试会问到 REQUIRED:如果当前没有事务,就新建一个事务