unity实战:狂暴机器人游戏教程(上篇)

Posted 肖尘

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了unity实战:狂暴机器人游戏教程(上篇)相关的知识,希望对你有一定的参考价值。

一、准备开始

1.创建场景

1.1打开场景

首先,在Unity中打开启动项目。在项目视图中,打开“Scenes/Battle”,如下图所示。

1.2新建标签

  • 首先,需要设置“Wall”的游戏对象,避免机器人AI撞到墙上。
    Tag是一个用来标识游戏对象的文本。每个游戏对象只能有一个标记。通过给每个墙的游戏对象分配一个标签,再为机器人设定一些寻路规则,这样它们就可以绕开墙走动。
    在层级视图中,单击“Inner Walls”游戏对象。在检视视图中,单击“Tag”下拉列表,然后选择“Add Tag”命令,

  • 单击“Tag”窗口中的加号按钮,然后新建一个“Wall”标签

1.3设置标签

通过单击层级视图中“InnerWalls”游戏对象左边的箭头展开它。选择它所有子对象 (名为“Wall”和“WallPost”)。快速的方法是选择第一个游戏对象,然后按住Shift键并单击最后一个游戏对象。选中所有子对象后,单击“Tag”下拉列表并选择刚刚创建的“Wall”标签,

注:当所有的墙壁都被标记为“Wall”时,可以开始着手为机器人添加“NavMesh”了。

1.4烘培导航

通过“Window/Navigation”打开“Navigation”视图。确保选中了所以的“Wall”和“WallPost”游戏对象,并确保选中了“Object”选项卡中的“Navigation Static”复选框。

选择“Bake”标签并单击“Bake”按钮

可以看到场景中出现了浅蓝色的面片,这个浅蓝色的面片就是被限制后的机器人可移动区域。
)

2.添加主角

2.1导入标准资源包

在层级视图中,创建一个空的游戏对象并命名为“Player”。案例将使用Unity自带的Character Controller(角色控制器),并稍作修改来实现玩家对主角的控制。选择菜单栏中的“Assets\\ImportPackage\\Characters”命令,导入标准资源。
注意:如果在ImportPackage中看不到“Character Controller”选项,说明在安装 Unity 时没有导入Standard Assets(标准资产)。要修复此问题,需要重新执行Unity安装程序,只安装Standard Assets。标准的Unity资产就像任何常规包一样。它只是一个文件的集合。
单击菜单上的Import按钮以导入Characters资产。

2.2创建脚本

创建移动脚本,包含人物移动,跳跃和转动摄像机,然后将脚本赋予Player确保各个功能的正常实现



创建好的脚本如图所示,speed表示人物移动,jump表示人物跳跃,Gravity表示重力,camera_x和camera_y表示鼠标移动时摄像机的转动倍率。
Camera摄像机需要放在Player人物下,程序会自动获取摄像机

备注:想要实现shift奔跑只需要添加
private float moveSpeed=Speed;
然后将以下代码添加进move函数中即可
if(Input.GetKeyDown(KeyCode.LiftShift))

Speed=跑步速度;
else Speed=moveSpeed;

3.创建武器

3.1添加手枪

在Unity中,枪只是另一个游戏对象。最大的区别在于视角。把它靠近镜头,立刻就能找到第一人称射击的感觉。
选择Camera游戏对象,然后右击它并选择“Create Empty”,创建一个空的子游戏对象,命名为“1Pistol”。名字前面的数字是指玩家将使用的装备ID。
将项目视图中“Models/RobotRampage_Pistol”模型拖到1Pistol 游戏对象上。
调整模型的位置大小,让枪在摄像机中正常显示,然后勾选下框,隐藏模型

根据此流程,添加猎枪和步枪。

3.2添加武器标签

接下来要为每个武器设置标签。
首先创建三个新的Tag,它们是Pistol、AssaultRifle和Shotgun。
然后给武器分配对应的标签。
1Pistol设置Tag为Pistol,2AssaultRifle设置为AssaultRifle,3Shotgun设置为Shotgun。如下图所示


4.创建常量文件

4.1创建Constants脚本

在项目视图中右击Assets文件夹,选择“Create\\Folder”命令创建一个新文件夹,命名为“Scripts”。在Scripts文件夹中,创建一个C#脚本,命名为“Constants”。
在脚本编辑器中打开Constants脚本,并将文件的内容替换为:

5.武器逻辑

5.1切换武器

保存脚本,回到Unity。在Scripts文件夹中新建一个C#脚本,将其命名为“GunEquipper”,添加以下变量。

保存脚本,回到Unity。在Scripts文件夹中新建一个C#脚本,将其命名为“GunEquipper”,添加以下变量。

保存脚本,回到Unity,并将GunEquipper 脚本添加到Player游戏物体上
选择Player游戏对象,并将1Pistol 游戏对象从层级视图拖动到 GunEquipper 脚本组件中的相应字段。以同样的方法操作2AssaultRifle 和3Shotgun。

二、子弹弹药

1.弹药的逻辑

1.1创建Gun基类

首先,需要确定了一个攻击频率。当玩家持续开枪时,每颗子弹射出之间有一个停顿。这意味着必须跟踪最后一颗子弹发射的时间,以便于判断何时可以发射下一颗子弹。
创建一个C#脚本,命名为“Gun”,并添加下面的变量:


fire Rate表示攻击的频率,而lastFireTime表示最后一次攻击的时刻。在Gun脚本中修改Start方法:

设置lastFireTime默认值为游戏开始的10秒前。10秒远远大于攻击间隔,所以当游戏开始时,玩家将能够立即发射子弹。最后,修改Update方法,代码如左。

因为每个武器在具体实现上都有细微差异,所以稍后将在子类中对这些方法进行重载。

1.2创建手枪脚本

保存脚本,切换回Unity。创建一个C#脚本,将其命名为“Pistol”,并将其内容替换为:

这将检查下一次射击是否达到攻击间隔。如果达到,将触发下一次射击动作。
保存脚本,回到Unity,并将Pistol脚本添加到1Pistol游戏物体。
选中1Pistol游戏物体,将fireRate设置为0.6。

1.3创建猎枪脚本

选择Pistol脚本,然后按下Ctrl+d键,复制脚本。把名字改成Shotgun,在代码编辑器中打开该脚本。将如下代码:


与手枪一样,这也是一个半自动武器,但因为它是一把猎枪,所以它需要更长的发射间隔。保存脚本,回到Unity,将Shotgun脚本附加到3Shotgun 游戏物体上,并将 fireRate 设置为1。

1.4 创建突击步枪脚本

最后,需要对突击步枪做同样的操作。创建一个名为“AssaultRifle”的脚本,将其附加到2AssaultRifle 游戏对象上,并将其内容替换为:


看上去这个脚本与Pistol脚本几乎相同,但有一个关键区别:该脚本使用 GetMouseButton来监听玩家是否按住鼠标左键,而不是用GetMouseButtonDown监听单次按下鼠标左键。
保存脚本,回到Unity。在检视面板中将AssaultRifle脚本的fireRate设置为0.1。

2.创建开枪动画

2.1创建动画控制器

右击“Animations”文件夹,选择“Create\\Animator Controller”命令,并将其命名为“Pistol”。右击Pistol.AnimatorController,然后单击“Open”按钮,打开Animator窗口。
在Animator窗口的网格区域中右键单击,然后选择“Create State\\Empty”创建一个新的状态。单击新状态,并在检视视图中,将其重命名为“Fire”。
单击Motion框右侧的控件,然后在搜索框中查找“Fire”。在结果列表中找到Assets/Models/RobotRampage_Pistol.fbx,然后双击它,如下图所示。

需要为动画创建默认状态。和之前一样,在动画窗口中创建另一个空状态,命名为“Base”。
右击“Fire”,然后选择“Make Transition”命令。从Fire拖到Base,如图2-2-2所示。

Fire动画播放后,动画应该回到Base状态。右键单击Base状态,然后选择“Set as Layer Default State ”,使其成为基本动画,如下图所示。

2.2用代码控制动画播放

打开Gun脚本,并将以下代码添加到Fire ()方法:

GetComponentInChildren<Animator>().Play("Fire");

这需要在代码中获取Animator,并告诉它何时播放Fire动画。在这之前,需要先在游戏对象上添加Animator组件。
当然,目前只创建一个手枪动画控制器,还需要创建猎枪和突击步枪的动画控制器。
在项目视图中,选择Animations文件夹下的Pistol动画控制器。按下Ctrl+D两次,复制出两个动画控制器。其中一个命名为“Shotgun”,另一个命名为“AssaultRifle”。
打开Shotgun动画控制器,并选择Fire状态。在检视视图中,设置Motion为Grip|Fire,来源于Assets/Models/ RobotRampage_Shotgun.fbx 模型。
最后,打开 AssaultRifle 动画控制器,并选择Fire状态。在检视视图中,设置Motion为Grip|Fire,来源于Assets/Models/RobotRampage_AssaultRifle.fbx模型。
所有的动画已经设置到位,下面需要将它们添加到武器上。

2.3设置Animator组件

回到Unity,选择1Pistol 游戏对象,单击Add Component按钮,输入Animator,在搜索结果中选择Animator。单击刚才添加的动Animator的Controller栏,然后从弹出窗口中选择Pistol动画控制器,如下图所示。

接下来点击Animator的Avatar框,并设置为 RobotRampage_PistolAvatar。如图2-2-5所示。

Avatar告诉动画系统如何在动画过程中变换模型。导入模型时,需要配置Avatar。为了简单起见,Avatar已经被提前配置好
对于突击步枪,选择2AssaultRifle 游戏对象,并将AssaultRifle动画控制器拖到检视视图,在所有现有组件之下。Unity会自动将Animator添加到游戏对象上。把Avatar设置为RobotRampage_AssaultRifleAvatar。

对3Shotgun做同样的操作,拖动它的Shotgun动画控制器,并设置Avatar为 RobotRampage_ShotgunAvatar,如下图所示。

运行游戏,测试武器,通过键盘上的1键、2键或3键在它们之间切换。

3.添加准心

3.1绘制手枪准心

原理很简单,只是一个放置在摄像机前的简单的2D图像。这不是什么很高明的技术,但是很实用。
在开始放置UI元素前,首先需要一个画布。Unity提供了几种类型的画布。本游戏将使用叠加画布,即overlay canvas。
在层级视图中的空白处,右击选择“UI\\Canvas”命令创建一个画布,重命名为“GameUI”。右击Canvas游戏对象,选择“UI\\Image”命令创建一个图片,并重命名为“Reticle”。
在检视视图中,单击Source Image右侧的控件,然后选择reticleRed。

可以看到屏幕中央的红色准心。

3.2创建GameUI脚本

当切换成猎枪和突击步枪时,应该更新颜色。
创建一个新脚本,命名为“GameUI”。将GameUI脚本附加到GameUI游戏对象上。
在代码编辑器中打开GameUI,并将以下内容添加到脚本的顶部。

using UnityEngine.UI;

这使脚本可以访问Unity基本的UI 类。接下来,在类中添加以下变量

[SerializeField] Sprite redReticle; 
[SerializeField] Sprite yellowReticle;
[SerializeField] Sprite blueReticle; 
[SerializeField] Image reticle;

SerializeField 属性允许开发者向 C# 运行时传递有关特定类的信息。Sprite(精灵)代表了一个导入的纹理,可以被使用在2D游戏或用户界面。通过将纹理类型设置为Sprite,可以将其添加到用户界面中。

现在有三个精灵作为图像的源数据。但是只有一个会被显示,所以只需要一个Image。
在最后一个变量下面添加以下方法:

public void UpdateReticle() 
switch (GunEquipper.activeWeaponType) 
 
  case Constants.Pistol:
       reticle.sprite = redReticle;
       break;
  case Constants.Shotgun: 
       reticle.sprite = yellowReticle;
       break;
  case Constants.AssaultRifle:
       reticle.sprite = blueReticle;
       break;
   defaultreturn;

选中GameUI游戏物体,添加适当的精灵。拖动Reticle游戏对象到Reticle栏,如下图所示。

3.3修改GunEquipper脚本

在代码编辑器中打开 GunEquipper 脚本。为其添加一个GameUI 变量,创建对 GameUI 的引用,代码如下。

[SerializeField] GameUI gameUI;

保存脚本,回到Unity。在层级视图中选择Player游戏对象,并将 GameUI 对象拖拽到GunEquipper组件中的GameUI字段,如下图所示。

在代码编辑器中打开GunEquipper 脚本,并在 Update () 方法中的每个 if 语句的末尾添加以下代码。

gameUI.UpdateReticle();

Update()现在应该如下所示,每次玩家改变武器将更新准心。

void Update() 
  if (Input.GetKeyDown("1"))  
     loadWeapon(pistol);
     activeWeaponType = Constants.Pistol; 
     gameUI.UpdateReticle();
  else if (Input.GetKeyDown("2"))  
     loadWeapon(assaultRifle);
     activeWeaponType = Constants.AssaultRifle; 
     gameUI.UpdateReticle();
  else if (Input.GetKeyDown("3"))  
     loadWeapon(shotgun);
     activeWeaponType = Constants.Shotgun; 
     gameUI.UpdateReticle();

4.弹药管理

4.1创建Ammo类

游戏中应该提供一些声音的反馈,使玩家知道什么时候快没子弹了。如果玩家有足够的弹药,在开火时播放开火的声音。如果没有足够弹药,播放空弹夹的声音,并且不播放开火动画。
创建一个C#脚本,命名为“Ammo”。在代码编辑器中打开它,在顶部添加如下代码。

using System.Collections.Generic;

这里可以使用字典类型。添加以下变量。

[SerializeField] GameUI gameUI; 
[SerializeField]private int pistolAmmo = 20; 
[SerializeField]private int shotgunAmmo = 10; [SerializeField]private int assaultRifleAmmo = 50;
 public Dictionary<stringint> tagToAmmo;

变量 pistolAmmo、shotgunAmmo、assaultRifleAmmo表示三种枪各自的弹药数。

tagToAmmo是一个由字符串映射int类型的字典,可以通过枪的类型找到其对应弹药计数。
在游戏开始时初始化Dictionary,添加如下代码。

void Awake() 

   tagToAmmo = new Dictionary<stringint>
    
       Constants.Pistol ,pistolAmmo,
       Constants.Shotgun ,shotgunAmmo,
       Constants.AssaultRifle ,assaultRifleAmmo
    ;

Awake方法是在Start方法之前调用的一种特殊方法。在本例中,为了防止null 访问错误,需要在所有Start方法执行之前对字典进行初始化。
该方法只是简单地让每支枪在字典中键入一个键,并将值设置为适当的弹药类型。如果希望添加另一个弹药类型,可以简单地扩展字典。
添加如下方法:

public void AddAmmo(string tag,int ammo) 
 
    if (!tagToAmmo.ContainsKey(tag)) 
       
          Debug.LogError("Unrecognized gun type passed: " + tag);
       
          tagToAmmo[tag] += ammo;

这个方法将增加特定类型的弹药。如果字典中不存在tag传入的类型,则会报错。

接下来添加以下方法:

// Returns true if gun has ammo 
public bool HasAmmo(string tag) 

    if (!tagToAmmo.ContainsKey(tag)) 
        
          Debug.LogError("Unrecognized gun type passed: " + tag);
       
    return tagToAmmo[tag] > 0;

这个方法将会判断是否还存在某类型的子弹,如果有,返回true。

同时添加以下方法:

public int GetAmmo(string tag) 
   if (!tagToAmmo.ContainsKey(tag)) 
       Debug.LogError("Unrecognized gun type passed:"   
           + tag);
       return tagToAmmo[tag];

这个方法只是简单地返回某种类型的枪的弹药数量。
最后,需要一个方法来实现弹药的消耗。添加如下代码。

public void ConsumeAmmo(string tag)  
    if (!tagToAmmo.ContainsKey(tag)) 
        Debug.LogError("Unrecognized gun type passed:" + 
    tag);
        tagToAmmo[tag]--;

与所有其他方法一样,首先会检查弹药名是否正确。如果正确,它将会找到对应的弹药,并减去一颗子弹。

保存脚本,回到Unity,并将Ammo脚本添加到Player游戏对象上。点击Player游戏物体,将 GameUI 游戏物体拖拽到Ammo组件中的 GameUI 字段上。如下图所示。

4.2添加声音

在代码编辑器中打开Gun脚本,并添加如下变量。

public Ammo ammo;public AudioClip liveFire; 
public AudioClip dryFire;

这将跟踪枪的弹药数量和保存开火和空弹的音效。修改Fire方法,代码如下。

protected void Fire() 
if (ammo.HasAmmo(tag)) 
 GetComponent<Audiosource>().PlayOneShot(liveFire); 
ammo.ConsumeAmmo(tag); 
else
  GetComponent<AudioSource>().PlayOneShot(dryFire);
GetComponentInChildren<Animator>().Play("Fire");

这将检查玩家是否有剩余的弹药。如果有,播放liveFire的声音;否则,播放dryFire的声音。如果开枪成功,花费一颗子弹。
接下来需要为每支枪单独设置弹药和音效。
单击1Pistol游戏物体,并拖动Player游戏物体到Ammo属性栏,表示对玩家Ammo脚本的引用。单击LiveFire字段右侧的控件,然后选择pistolShot音频文件。单击dryFire字段右侧的控件并旋转dryFire音频,如下图所示。

对3Shotgun和2Assaultrifle做同样的操作。
剩下的就是添加AudioSource组件。选中1Pistol、2AssaultRifle和3Shotgun游戏对象。在检视视图中单击AddComponent,键入AudioSource并选择AudioSource组件,如下图所示。

运行游戏,检查每只枪的射击音效。

突击步枪有一个问题,枪的射击速度比动画播放速度快,这使运动与动作不同步。为了解决这个问题,需要回到Animator那里。
如果动画窗口已关闭,可以通过单击“Window\\Animator”重新打开它。在层级视图中,选择2AssaultRifle 游戏物体,将会在Animator视图中看到它的动画状态。
默认情况下,动画在过渡过程中会有一段混合过程。这种混合过程被称为退出时间。选择从Fire到Base的转换。在检视视图中,可以看到退出时间的可视化效果。如下图所示

有两种方法可以取消退出时间。第一种,取消选中“Has Exit Time”属性。但是只有在有过渡条件时才能这样做。第二种,将时间轴中的右边的蓝色箭头拖到左侧,然后按Enter键将其保存。



这将导致新的动画会中断任何正在播的放动画。运行游戏,切换到突击步枪。测试修改过的内容。


总结

共同学习

以上是关于unity实战:狂暴机器人游戏教程(上篇)的主要内容,如果未能解决你的问题,请参考以下文章

unity实战:狂暴机器人游戏教程(上篇)

unity实战:狂暴机器人游戏教程(上篇)

unity实战:狂暴机器人游戏教程(下篇)

unity实战:狂暴机器人游戏教程(下篇)

unity实战:狂暴机器人游戏教程(下篇)

Unity5新特性----实战2D游戏