Unity学习_JuniorProgrammer_1.1_玩家控制
本文记录Unity Learn, Create with code 1, Unit 1内容
启动U3D,创建一个3D场景
创建一个新3D项目
打开unity hub, 选择3D core, 自行选择命名你的新project. 然后需要我们导入官网提供的资源包.
在Unity中,选择 Assets > Import Package > Custom Package 找到 Prototype 1 Starter Files.
导入后,在下方的导航栏里,双击打开Assets > Scenes > Prototype 1.
之后我们便可以看到一个公路的场景。
Unity 基础操作
在scene中,按住右键可以调整摄像机角度。按住右键时,可以用wasd前后左右移动摄像机,qe上下移动摄像机。移动鼠标滚轮可以放大缩小画面,按住鼠标中键可以拖动画面(平行移动摄像机)。当你飞太远找不到你想要的物体时,选中物体按F
即可使摄像机聚焦该物体。按住alt拖动左键可以使摄像机绕焦点旋转,拖动右键可使画面放大或者缩小。
为场景添加一个小车
在Assets > Course Library > Vehicles 里,将任意小车拖拽到Hierarchy窗口。选中刚才的小车按F
,摄像机会聚焦到小车。整个的unity界面看起来应该如下图所示。
左边Hierarchy的蓝色方框是我们刚才添加的小车。小车在unity里被识别为一个object,其object的属性可以在右侧的Inspector里查看以及编辑。红色方框是一些常见的transformation工具,可以允许我们调整物体的大小,位置,角度。同样的,我们也可以在右侧的Inspector,transform属性里手动调整。
为场景添加一个障碍物
在Course Library > Obstacles为场景添加一个障碍物,并且在右侧的Inspector>transform模块内重置它的位置。Reset按钮可以在transform的小窗口右上角的三个小点…的下拉菜单里找到。然后再Inspector里,将障碍物的z坐标设置为25。最后将添加的小车和障碍物重新命名为Vehicle和obstacle。
调整游戏的摄像头
注意,在没有开始游戏之前,我们观测场景的摄像头并不是游戏开始后的摄像头。游戏开始后的摄像头是Hierarchy里的main camera。为了保证游戏开始后我们可以驾驶这辆车,我们需要将摄像头移动到车后方。
在选中main camera后,我们可以在画面右下角看到他的preview,如下图。
配合旋转和移动工具,将摄像头调整到想要的位置,在移动中按住ctrl可以移动整数个单位,直到进入游戏后效果大致如下图。
让小车动起来
创建代码Scripts文件夹
在Project窗口,Assets文件夹下, 创建名问Scripts的文件夹。这个文件夹会放置以后我们所写的所有 C# 脚本文件。在刚才创建好Scripts文件夹下,创建名为 PlayerController
的C# 脚本。并且将创建好的脚本拖到Vehicle的Inspector里。同样也可以直接在其Inspector里的 Add Component 直接创建。
使小车匀速前进的代码
双击打开刚才创建的PlayerController
脚本中,我们会看到如下内容:
1 | using System.Collections; |
除了使用的库,一个继承了MonoBehaviour
的公有类PalyerController
, 还有两个方法Start
和Update
, 并且贴心地写好了注释. MonoBehaviour
类提供了一个框架,允许你在编辑器中将脚本附加到Unity的GameObject
上,同时也提供了一些有用事件的hook,如Start
和Update
。更详细的Monobehaviour
的介绍可以参考Unity的官方文档.这里的Start
方法会在游戏开始的第一帧调用,一般用来初始化一些属性。Update
方法会在每一帧刷新的时候调用。
在脚本里可以调用和操作GameObject
的各类属性,这里为了让小车移动,我们需要让小车每一帧都向前挪动一点位置。GameObject
的位置由其transform属性的position决定,所以我们需要对这一变量在每一帧进行修改。注意到,Unity引擎采用的是左手系,并且这里的前方是z轴。
在Update
里添加:
1 | transform.Translate(Vector3.forward * Time.deltaTime * 20); |
这里 transform.Translate()
是Game Object
做平移的方法,传入参数为一个Vector3
类。Vector3.forward
是值为Vector3(0,0,1)向量的简写。Time.deltaTime
指从上一帧到当前帧的秒间隔(只读)。由于速度不随帧率变化,所以我们每帧调用的时候都要保证使用Time.deltaTime
保证我们的移动是匀速的。
为小车和障碍物添加物理
选择我们的Vehicle和Obstacle, 在Add Component处选择添加Rigidbody
给小车和障碍物以刚体属性。同时,小车和障碍物已经有了Mesh Collider
这个属性。MeshCollider是unity判断物体间碰撞的碰撞体积,不一定与原物体的网格是相同的。注意当只有碰撞体积但是没有刚体属性的时候,物体之间是不会发生碰撞的。在添加Rigidbody
之后,给小车更高的质量,使其更接近真实(Rigidbody
里的Mass属性)。
更多的障碍物!
现在让我们为小车添加几个更多的障碍物,右键选中Hierarchy里的Obstacle点击duplicate, 或者直接Ctrl+D,调整你想要的障碍物的位置。
然后点击game play按钮,观察小车撞飞障碍物吧!
操控小车
为小车设置速度-Scripts里的public变量
在脚本里对Update方法做如下修改:
1 | // Update is called once per frame |
可以看到我们为小车设置了一个public浮点数变量叫做speed
,然后再Inspector里面,我们可以看到在PlayerController
区域多出来了一个speed变量。这样的变量允许我们在开发时实时调整其数值,方便观察最终效果。
让摄像机跟随小车移动
为了让摄像机跟随小车移动,我们需要实时获取小车的位置,并且将摄像机的位置与小车的位置绑定。为摄像机main camera创建脚本,名为FollowPlayer
. 修改MonoBehaviour
内容为:
1 | public class FollowPlayer : MonoBehaviour |
然后将Vehicle拖到摄像机属于player的公有变量内。试运行便可以得到跟随小车移动的摄像机。注意到我们这里使用了LateUpdate
而非普通的Update
这是因为如果小车的位置更新与摄像机的位置更新都发生在Update
方法内,则两者顺序的时候不一定是固定的,这时会观察到画面会有抖动等不稳定现象。而LateUpdate
方法在所有Update
调用完之后才调用,可以避免此类问题。
用键盘控制小车移动
Unity提供了Input Manager来作为用户与游戏交互的操作接口。在 Edit > Project Settings可以找到.
这里我们会用到默认的 Horizontal 和 Vertical 两个按钮。同时,可以自定义按钮,以及修改size调整 Input Manager 的按钮个数。在PlayerController
脚本内,将代码修改为
1 | public class PlayerController : MonoBehaviour |
这里我们定义前进速度speed
和旋转速度turn_speed
,并且由上下左右键或者wasd键控制。