Unity相机跟随以及子弹发射笔记

相机移动

现在还有一个问题是:主角SpaceMarine移动的时候,会走出玩家的视线,所以这里让相机跟随着SpaceMarine移动。
步骤1. 创建和设置CameraMount
在层级(Hierarchy)视图中,单击左上角的“Create”按钮,在打开的快捷菜单中选择“Create Empty”命令,将其重命名为“CameraMount”。
这里实现的基本想法是要让相机跟随CameraMount的位置,并且CameraMount的初始位置和SpaceMarine的位置是一样的。
从层级视图中选择SpaceMarine,在检视(Inspector)视图中单击Transform组件右上角的齿轮图标,在打开的快捷菜单中选择“Copy Component”命令,如图3-4-1所示:Unity相机跟随以及子弹发射笔记
选择CameraMount,在层级(Hierarchy)视图中单击Transform组件右上角的齿轮图标,在打开的快捷菜单中选择“Paste Component Values”命令:
将Main Camera拖到CameraMount里面,如图3-4-2所示。
Unity相机跟随以及子弹发射笔记
将Main Camera设置为子级GameObject
现在只需要写一些代码来实现:当主角SpaceMarine移动的时候,CameraMount会跟随主角移动。
步骤2. 创建相机移动脚本
选择CameraMount,在检视(Inspector)视图中单击“Add Component”按钮,在打开的下拉菜单中选择“New Script”命令,语言设置为C Sharp(C#语言),并将脚本组件命名为“CameraMovement”。
在项目视图中,将新建的脚本CameraMovement拖动到Scripts文件夹下。
双击打开CameraMovement。
在类定义之后(第一个“{”之后),添加以下两行代码:
public GameObject followTarget;
public float moveSpeed;

followTarget是指将要让Camera跟随哪个GameObject,moveSpeed是相机的移动速度。创建这两个变量时用到了public(公开的)来修饰,Unity可以让public修饰的变量在检视(Inspector)视图中修改其属性。所以,这里稍后可以将SpaceMarine拖到followTarget上,并指定一个moveSpeed。
在“Update()”方法里面添加以下几行代码:
if (followTarget != null) {
transform.position = Vector3.Lerp(transform.position, followTarget.transform.position, Time.deltaTime * moveSpeed);
}

这段代码的意思是:检查有没有给followTarget指定一个目标GameObject。如果没有指定,则什么都不做,相机不会移动。
“Vector3.Lerp()”是用来计算相机应该移动到什么位置的一个方法。它是一个线性插值算法。
按Ctrl+S键保存脚本,并回到Unity编辑器。从层级(Hierarchy)视图中选中CameraMount,然后查看检视(Inspector)视图,开发者会发现Follow Target和Move Speed两个属性,就像刚才写代码时说的,public修饰的变量会显示在Unity 的检视(Inspector)视图中,并且可以修改。
保持CameraMovement还是被选中的状态,从层级(Hierarchy)视图中拖动SpaceMarine到Follow Target属性对应的插槽内;将Move Speed的属性值修改为20。如图3-4-3所示。
Unity相机跟随以及子弹发射笔记

步骤3. 运行游戏
看看效果,如图3-4-4所示:
Unity相机跟随以及子弹发射笔记
相机可以跟随着SpaceMarine移动了。但是,他还不能转身,并且可以穿过墙壁等物体,这些都是小问题,这些问题会在下一章解决。
注意:Move Speed的值越大,相机跟随的速度越快;值越小,跟随速度变慢甚至延迟;试着从检视(Inspector)视图中修改CameraMovement组件的Move Speed的值,比如改成3,看看效果。

子弹发射

现在游戏里的的SpaceMarine虽然抱着一挺枪,但是他还没能力开火。接下来,来让他的枪能发射子弹。
步骤1. 创建一颗子弹
在层级(Hierarchy)视图中,单击左上角的“Create”按钮,在打开的下拉菜单中选择“3D Object”→“Sphere”命令,创建一个小球来表示子弹。如图3-5-1所示。
Unity相机跟随以及子弹发射笔记
将新创建的这个Sphere重命名为“Projectile”。从检视(Inspector)视图中,开发者会发现它有好几个组件组成。如图3-5-2所示。
Unity相机跟随以及子弹发射笔记
以下是这三个组件的描述:
Mesh Filter(网格过滤器):该组件包含模型网格数据,并将其传给渲染器。
Mesh Renderer(网格渲染器):该组件是用来显示网格的,它包含光照、投影、接受阴影等信息。
Sphere Collider(球碰撞体):下一章将详细讲解Collider(碰撞体)。
步骤2. 给子弹添加刚体
根据之前学习的内容,单击“Add Component”按钮,在下拉的快捷菜单中选择“Physics”→“Rigidbody”命令。将Use Gravity复选框的勾去掉。
因为SpaceMarine会需要很多子弹来消灭Alien,所以要将子弹Projectile变成Prefab(预置物体)。
步骤3. 制作子弹预制体
从层级(Hierarchy)视图中拖动Projectile到项目(Project)视图的“Prefabs”文件夹下。
从层级(Hierarchy)视图中删除Projectile 游戏对象。
现在,游戏需要创建一个脚本来发射子弹。
步骤4. 创建枪的脚本
选择项目(Project)视图中的Scripts文件夹,然后单击左上角的“Create”按钮,选择“C# Script”(C#脚本)命令,并将其命名为“Gun”。
双击脚本在代码编辑器里打开,在类定义的下方添加如下两行代码:
public GameObject bulletPrefab;
public Transform launchPosition;

再次加强说明一下,public修饰的变量可以显示在检视(Inspector)视图中,并且可以修改或者给其赋值。“bulletPrefab”将会接受刚刚创建的Projectile Prefab(预置物体);“launchPosition”将会接受一个指定的子弹发射的位置。
添加如下方法:
void fireBullet() {
// 1
GameObject bullet = Instantiate(bulletPrefab) as GameObject;
// 2
bullet.transform.position = launchPosition.position;
// 3
bullet.GetComponent().velocity = transform.parent.forward * 100;
}

解释一下这个方法:
1.“Instantiate()”是Unity的内置方法,用来实例化一个Prefab。该方法的返回值是Object类型,所以使用“as”关键字将其强制转换为GameObject。
2. 将实例化之后的子弹放置到指定的子弹发射位置。
3. 由于子弹有一个刚体组件,这里可以给刚体组件一个速度,使子弹以恒定的速率移动,移动的方向由子弹发射的位置决定。稍后会将子弹发射的位置添加在SpaceMarine上,并确保子弹的发射方向是SpaceMarine面对的方向。
按Ctrl+S键保存脚本并回到Unity。
在层级(Hierarchy)视图中,展开SpaceMarine游戏对象,并选择BobbleMarine-Body游戏对象,在检视(Inspector)视图中,单击“Add Component”按钮,在打开的快捷菜单中,选择“Scripts”→“Gun”命令。如图3-5-3所示。
Unity相机跟随以及子弹发射笔记
开发者将发现Gun脚本组件已经添加在了BobbleMarine-Body游戏对象上了,同时开发者应该也注意到了两个空着的属性插槽:“Bullet Prefab”和“Launch Position”。
步骤5. 给枪设置子弹
单击Bullet Prefab 后边的小圆圈,在打开的快捷菜单中选择Projectile。如图3-5-4所示。现在已经指定了发射的子弹,还需要指定发射的位置。
Unity相机跟随以及子弹发射笔记
步骤6. 设置子弹的位置
在层级(Hierarchy)视图中,按住Alt键(Mac上是Option键),并单击BobbleMarine-Body旁边的小三角形。从这一堆子级GameObject中找到Gun。如图3-5-5所示。
Unity相机跟随以及子弹发射笔记
选择Gun这个游戏对象,单击“Create”按钮,在打开的菜单中选择“Create Empty Child”命令,并将其重命名为“Launcher”,如图3-5-6所示。这个新的游戏对象的位置是在枪筒的中心,代表子弹要从这个地方生成并且发射出来。开发者可以随意调整这个位置来看一下效果。
Unity相机跟随以及子弹发射笔记
保持所有的游戏对象都是展开的状态,选择BobbleMarine-Body,然后将新创建的Launcher游戏对象拖到Gun组件的Launch Position插槽内。
当开发者将一个GameObject拖到Transform类型的插槽里面时,Unity会自动从拖动的GameObject上寻找相应的组件来匹配。对于Transform类型的插槽,会寻找Transform组件;如果是Light类型的插槽,就会从GameObject上寻找Light组件。
现在,子弹有了,发射位置也准备好了。如图3-5-7所示。就差实现开火的代码了。
Unity相机跟随以及子弹发射笔记
步骤7. 实现发射子弹的脚本
回到代码编辑器里面,打开Gun.cs。
这里想要在按下鼠标键时发射子弹,鼠标松开时停止发射子弹。
这种想法可以简单的在“Update()”方法中判断鼠标键是否按下,如果按下就调用“fireBullet()”方法。但是这样做的话,有个小问题,“Update()”方法是每一帧都会调用,一般情况下每秒调用60次左右,这就意味着按下鼠标时,每秒会发射60发子弹。这样,SpaceMarine会很快地发射子弹,但每秒60发也太快了。
所以,这里需要这么做。
添加如下代码到“Update()”方法里面:
if (Input.GetMouseButtonDown(0)) {
if (!IsInvoking(“fireBullet”)) {
InvokeRepeating(“fireBullet”, 0f, 0.1f);
}
}

首先,通过Input Manager(输入管理器)检查鼠标左键是否被按下了。
注意:如果要判断鼠标右键,使用“1”作为参数;鼠标中键,使用“2”作为参数。
如果鼠标左键被按下,再次判断“fireBullet()”方法是否正在被调用执行,如果没有,使用“InvokeRepeating()”方法来执行“fireBullet()”,这将会持续不断地调用“fireBullet()”方法,直到使用“CancelInvoke()”方法将其停止。
“InvokeRepeating()”方法有三个参数,第一个是需要执行的方法的名称;第二个是什么时候开始执行,“0”代表马上开始执行,若是“5”就5秒后执行;第三个参数是指定多长时间执行一次。这个方法是MonoBehaviour类的方法。
在上面的代码之后,再添加两行代码:
if (Input.GetMouseButtonUp(0)) {
CancelInvoke(“fireBullet”);
}

这两行代码的意思是:如果鼠标左键被松开了,就停止发射子弹。
步骤8. 运行游戏
按Ctrl+S键保存代码,并返回到Unity编辑器。
单击“Play”按钮来运行游戏。如图3-5-8所示。
Unity相机跟随以及子弹发射笔记
按下鼠标左键,现在就可以持续地发射子弹了。

上一篇:引擎入门 | 创建双杆射击游戏(组件 1)


下一篇:Robot常用Library安装