【GAD翻译馆】VR100天教程:第五天Survival Shooter教程I
译者:刘鸿(lewis2012,251423807) 审校:王玥亭(玥亭)
好的,我们次回来, 开始Unity VR的第五天学习。在第2-4天我们完成了Unity的 Space Shooter游戏教程,现在我们来看下一个教程: Survival Shooter教程!
根据我们在工具包中已经学到的知识,我们将进一步了解:
1)设置环境
2)使用Unity内置的AI系统
安装
就像上一个教程一样,在创建新项目时,通过Unity Store或通过Learn 选项卡下载资源。
一旦我们获得了包,就像我们以前做过的一样,创建一个新项目并导入 Survival Shooter项目,以便我们可以进行初始设置。
环境设置
首先要做的是通过点击ctrl S创建一个场景。
我们把新建的场景命名为main,它可以是任何你想要的东西。
之后,转到预制文件夹并将环境 预制对象拖到 游戏hierarchy 中,你将看到如下所示:
如果你实际扩展了环境预制,你将看到它只是一个容器游戏对象,其中包含多个子游戏对象,如墙壁,椅子和其他游戏对象。
下一步是为我们的玩家创建一个楼梯,类似于上一个教程,我们创建了一个 四边形(Quad ) ,并将其设置为如下:
我的设置是:
位置:0,0,0
旋转:90,0,0
比例:70,70,1
禁用网格渲染器
最后一部分是去四边形的网格渲染器(Mesh Renderer)组件,并禁用它。
我们只需要在地板碰撞器检测我们的鼠标点击。我们不需要渲染地板。
把布局(Layout )设置为Floor
另一件重要的事情是去inspector 面板把我们的四边形(Quad )和布局(Layout )选择Floor。
我们稍后可以看到这一点的作用,它的主要目的是让我们能够优化我们的cod搜索。
添加背景音乐
我们在这个视频中做的最后一件事就是创建一个空的Music GameObject并附加一个 AudioSource 组件,并将Background Music设置 为 AudioClip。
通常我们将音乐设置为 Play On Awake和Loop ,但是一开始就会令人烦恼,我们现在就禁用它。
玩家角色
太棒了!现在我们有了环境设置,接下来我们做的是创建玩家对象。本教程拥有模型文件夹中的所有模型。将玩家模型拖到hierarchy面板中。
你会看到这样的东西:
太酷了!我们有一个角色。确保为我们的角色设置玩家标志。
接下来,我们为我们的角色创建一个称为动画控制器(Animator Controller) 的东西,通过右键单击项目面板创建一个动画控制器(Animator Controller)
动画控制器(Animator Controller)被描述为有限状态机。一个状态可以是步行(walking )或空闲(idle)。当你处于一个状态时,你只能进入一个不同的状态:
1)你现在的状态有一个转变,让你进入另一个状态。
2)你满足转换中的标准。
我们会在视频中继续了解更多内容。
但首先,我们要看一下动画?
Unity为每个角色模特提供自己的动画!
例如,如果你在项目面板中单击Player的Character模型并查看inspector面板,你将看到与模型相连的动画剪辑:
正如你看到的,我们有一个移动(Move),空闲(Idle),死亡(Death)的动画。
创建动画控制器
他们首先要做的是去动画文件夹,右键单击并创建一个新的动画控制器(Animator Controller)。
我们称之为PlayerAC。在我们创建它之后,我们双击它来打开它。
这将打开Animator面板供我们使用。
我们想为我们的角色动画片段创建一个状态。
我们可以很容易地将动画从角色模型拖放到Animator中。你会看到这样的东西:
创建状态过渡
现在注意,我们有一个从入口(Entry)到空闲(Idle)的箭头。入口(Entry)表示我们的初始状态。如果你的空闲(Idle)状态不是橙色,这意味着它不是动画将进入的默认状态。右键单击空闲,将其设置为默认状态,你将看到类似于上面的内容。
创建要在状态之间切换的参数
注意到上述图像中圈出来的参数?
在“参数”选项卡中,我们可以创建必须从一个状态转换到下一个状态的条件。我们创建了两个参数:
IsWalking:一个布尔值(Boolean),布尔值(Boolean)就像你想的那样, true 和 false两种值。
Die:一个触发器,触发器类似于布尔值(Boolean),触发为true或触发为false。
用我们的参数创建第一个过渡
现在,当我们开始游戏时,我们的角色只会是空闲(Idle)状态的。
玩家从空闲(Idle)状态转换到哪些状态?移动(Move )状态!(理论上讲,他们也可以过渡到死亡(Death)状态,但是我们会做一些其他事情)
单击空闲(Idle) 并创建一个过渡,然后选择移动(Move )作为选择目标。
接下来我们点击我们创建的转换箭头。在Conditions 选项卡下的inspector 面板中 ,选择IsWalking 并选择 true 。
接下来,从移动(Move )做同样的事情 ,选择空闲(Idle)并将 条件IsWalking设置为false,这意味着如果我们走路并决定停止,我们返回并播放 空闲(Idle)动画。
完成后,你会看到如下:
使用任何 状态(Any State)
现在,当玩家死亡了应该怎么办?
我们可以创造从空闲 和 移动到死亡的过渡 ,但是因为我们可以在任何状态死亡,所以我们使用任何状态(Any State)。
你可以想像,任何状态 (Any State) 允许我们创建转换,无论我们目前处于什么状态。
创建从任何状态(Any State)到死亡状态的过渡并设置Die作为参数。
将刚体添加到玩家容器中
接下来,我们向玩家的GameObject添加一个刚体组件。我们设置阻力和角度设到正无穷,我不是很确定这是什么,但根据 文档,就像摩擦力减慢了玩家的速度。
我们还希望设置约束,固定位置,防止它们移动:
1)约束Y位置,防止玩家上下起跳(如跳跃)
2)约束X和Z旋转,防止玩家以奇怪的角度旋转
添加刚体后,我们还添加了一个 胶囊碰撞器 和一个 音频源 与 玩家伤害 作为Audio Clip
玩家动作脚本
接下来要做的是把PlayerMovement 脚本添加到玩家对象上。代码有注释,所以我不会太深入地研究它们所做的事情。
然而,我想指出的一些关键点是:
与Start()类似,在游戏开始之前调用Awake(),具体来说,你可以使用它来初始化附加脚本中的GameObject的变量,但不能与其他游戏对象进行初始化。
光线投射(Raycast)
Unity的一部分内置的物理系统,Raycast是一条直线,向前射击,如果你打中你指定的目标,函数调用将返回true。
你必须给Raycast一个RaycastHit引用来存储被击中的对象的信息。你可以认为这是碰撞器的另一种方法。在这种情况下,我们使用鼠标。
所以我们来分解一下我们的参数:
Physics.Raycast(camRay,out floorHit,camRayLength,floorMask)
camRay:正如说明中所述:“从相机方向上在屏幕上的鼠标光标创建光线”。
floorHit:存储我们命中的对象的信息的变量。当我们碰撞到碰撞机时,考虑其他 GameObject。
camRayLength:射线距离起始位置有多远。在这种情况下:从相机到玩家的鼠标在游戏中指向的位置。
floorMask:int型变量表示我们只想查找冲突的图层的。我们使用这些floormask来帮助我们只与我们想要的对象进行碰撞,帮助我们节省宝贵的处理性能。
运动标准化
在部分运动代码中,我们将我们的值标准化:
根据视频,我们进行水平或垂直运动时候,将移动1个单位,但是,如果我们进行对角线移动,我们将移动1.4个单位或更多,允许玩家利用游戏。标准化可以防止运动对角线1.4个单位。
四元数(Quarternion)
我们之前学过,但四元数是Unity中旋转的具体方法。如果你想做任何关于旋转的事情,我们就需要四元数( Quarternion)类。
旁注:
在这之后,我发现我可以移动角色,但它不会旋转鼠标。如果这发生在你身上,可能是因为你忘了设置Floor的布局。
摄像机的设置
好了,现在有了我们的角色,我们可以移动他。除了我们目前的游戏状态,游戏看起来很好。
摄像机相机
进入我们的相机GameObject并做出这些改变:
1)设置摄像机位置:1, 15, -22
2)旋转为:30, 0, 0
3)投影:Orthagaonic视角。
透视是有深度的,但是orthagonic没有
1)尺寸为:4.5
2)背景为黑色
添加摄像机脚本
现在我们设置了摄像机,接下来要做的是从脚本文件夹添加提供的相机脚本:
看看代码,上面已经做了很好的备注,所以我们不会过多讨论。
创造敌人#1
现在我们可以控制地图上的角色,接下来我们要做的是在屏幕上添加敌人。
首先要做的是将Zombunny角色模型拖入场景。
敌人也有自己的动画剪辑( animation clip)。
我们需要做的一些我们的模型
将粒子效果添加到僵尸对象上,当它被击中时播放
将Zombunny的声音设置为我们的模型,确保它不会Play On Awake。
为我们的敌人创建一个胶囊碰撞器:
为我们的僵尸设置一个层,如果它不存在的话,创建一个。
最后在我们的游戏对象上附加一个新的导航网格代理( Nav Mesh Agent)。
一个导航网格代理(Nav Mash Agent)是Unity提供给我们的人工智能,它将允许我们的僵尸智能地追逐玩家,同时避开障碍。
确保你的设置与上述相同,特别是 半径和高度。
创建一个导航网格
AI高效的原因在于,它不必计算出做什么能走或者不能走。
我们通过创建一个导航网格来实现这一点,它告诉AI,所在的地方能不能正常通行。
参考下面的图片,了解我在说什么。蓝色是敌人可以行走的空间:
你可以通过Unity > Window > Navigation来创建导航网格
在你的Inspector面板旁边的导航窗格中,选择Bake。
你需要知道其中的4个值:
1)半径,AI可以移动到墙上有多近。
2)高度,AI可以通过的高度。
3)步 高,在环境阻止AI之前,AI有多高。
4)最大斜率,一个物体的坡度有多高,使得玩家无法进入 。
你应该会有下面的值:
完成后,按下Bake,创建你的导航网格(Nav Mesh)。
重要的是,如果你想要将游戏对象包括在一起,你必须确保它们在inspector面板中是静态的。
一种简单的方法是将所有东西放到父容器中,并使父容器保持静态。这也会让所有的子元素都变成静态对象。
创建EnemyAC脚本
既然我们有了AI,我们就不必编写任何复杂的人工智能脚本来确定如何导航。
我们可以使用导航网格代理(Nav Mesh Agent )组件。然而,在我们做之前,我们必须为我们的敌人创造动画。
类似于我们的玩家模型,我们必须为我们的僵尸创建一个动画控制器。
首先我们进入动画文件夹,右击,并制作一个新的动画控制器,命名为EnemyAC。
打开EnemyAC脚本,然后将动画剪辑从僵尸模型拖放到控制器中。
我们需要做两个触发器:
1)Move
2)Idle
3)Death
移动(Move)是我们的主要过渡状态。
我们希望我们的僵尸唯一处于空闲的时候是因为僵尸赢了玩家已经死了,所以创建一个从移动到空闲的事务,这是由PlayerDead 触发器引起的。
类似于玩家的死亡,如果敌人死了,那就无所谓哪个状态,我们播放死亡动画。我们创建一个从任何状态到死亡的事务,由Dead 触发器引起的。
当我们做完的时候,我们应该有这样的东西:
敌人移动脚本
导航网格代理(Nav Mesh Agent)?检查。创建动画?检查。让我们用一切!
在脚本文件夹中,我们将找到已经完成的EnemyMovement脚本。把它附加到在敌人对象身上。
注意:在这一点上,需要注意的是,我们现在不使用代码中的所有内容。复制视频中的代码或手动注释掉行。
代码本身非常简单。我们实例化我们的玩家对象和导航代理组件,然后在Update()中设置我们的导航代理组件为玩家的位置。
在我们完成之后,如果回到游戏中,敌人就会开始追我们。
结论
我们今天取得了很大进展,我们设置了环境,添加了玩家和敌人,然后创建了一个Nav Mesh Agent来帮助我们的敌人追逐我们的玩家。
我将尝试完成本教程的其余部分,最后继续创建一个简单的游戏功能。
在那之前,我们第6天再见!
访问VR挑战100天的内容表
【版权声明】
原文作者未做权利声明,视为共享知识产权进入公共领域,自动获得授权。