塔防游戏十分受欢迎,没有什么比看着你的防护消灭邪恶的入侵者更令人满意的了!在这个由两部分组成的教程中,您将运用 Unity 构建一个塔防游戏!

您将学习怎么…

  • 制作一波又一波的敌人
  • 让他们遵从路点移动
  • 制作和晋级塔,让它们将你的敌人削减直至消失

最终,您将具有该类型的框架,能够对其进行扩展!

留意:您需求了解 Unity 基础知识,例如怎么增加游戏资源和组件、了解预制件并了解一些基本的 C#

塔防的全貌

在本教程中,您将构建一个塔防游戏,其间敌人(小虫子)爬向归于您和您的喽啰的饼干,这些喽啰当然是怪物!您能够在战略要点放置和晋级怪物,以取得一点金币。

玩家必须在虫子吃你的饼干之前杀死它们。每一波敌人都更难被打败。当你在一切浪潮中幸存下来(胜利!)或五个敌人抵达饼干时,游戏完毕。(失败!)

以下是已完结游戏的屏幕截图:

【Unity小游戏】游戏开发案例,轻松打造一款塔防游戏!(上)

怪物联合起来!保护饼干!

开端

在 Unity 中翻开 TowerDefense-Part1-Starter 项目。

入门项目包括美术和声响资源,以及预构建的动画和一些有用的脚本。这些脚本与塔防游戏没有直接关系,因而此处不再解释。可是,假如您想了解有关创立 Unity 2D 动画的更多信息,请查看此 Unity 2D 教程。

该项目还包括预制件,稍后您将对其进行扩展以创立人物。最终,该项目包括一个场景及其布景和用户界面设置。

翻开_“Scenes”_文件夹中的 GameScene,并将游戏视图的纵横比设置为 4:3,以保证标签与布景正确对齐。您应该在“游戏”视图中看到以下内容:

【Unity小游戏】游戏开发案例,轻松打造一款塔防游戏!(上)

学分:

  • 该项意图艺术来自Vicki Wenderlich的免费艺术包!你能够在gameartguppy上找到更多很棒的图形。
  • 很帅的音乐来自BenSound,他有一些很棒的配乐!
  • 感谢Michael Jasper的震撼。

入门项目 – 查看!
资源 – 查看!
迈向统治国际的第一步…嗯,我是说你的塔防游戏…功德圆满!

X 标记点:放置

怪物只能在标有_x_的当地粘贴。

要将它们增加到场景中,请将“Images\Objects\Openspot从“项目浏览器”拖放到“场景_”视图中。现在,职位并不重要。

在“层次结构”中挑选_“Openspot_”后,单击__Inspector_中的Add Component”,然后挑选“Box Collider 2D”。Unity 在场景视图中显现带有绿线的框磕碰体。您将运用此磕碰体来检测该方位上的鼠标单击。

【Unity小游戏】游戏开发案例,轻松打造一款塔防游戏!(上)

Unity 会自动检测磕碰体的适宜尺寸。这有多酷?

依照相同的进程,将Audio\Audio Source组件增加到Openspot。将音频源的_音频编排_设置为 tower_place,您能够在“Audio”文件夹中找到该文件夹,然后停用_“Play On Awake_”。

您需求再创立 11 个点。虽然重复一切这些进程很诱人,但 Unity 有一个很好的处理方案:预制件

Openspot 从“层次结构”拖放到“项目浏览器”的_“预制件_”文件夹中。然后,它的称号在层次结构中变为蓝色,以显现它已连接到预制件。像这样:

【Unity小游戏】游戏开发案例,轻松打造一款塔防游戏!(上)

现在您现已有了预制件,您能够根据需求创立恣意数量的副本。只需将 Openspot 从_项目浏览器中_的_预制件_文件夹拖放到_场景_视图中即可。执行此操作 11 次,即可在场景中一共创立 12 个 Openspot 目标。

现在运用_Inspector_将这 12 个 Openspot 目标的方位设置为以下坐标:

  • (X:-5.2, Y:3.5, Z:0)
  • (X:-2.2, Y:3.5, Z:0)
  • (X:0.8, Y:3.5, Z:0)
  • (X:3.8, Y:3.5, Z:0)
  • (X:-3.8, Y:0.4, Z:0)
  • (X:-0.8, Y:0.4, Z:0)
  • (X:2.2, Y:0.4, Z:0)
  • (X:5.2, Y:0.4, Z:0)
  • (X:-5.2, Y:-3.0, Z:0)
  • (X:-2.2, Y:-3.0, Z:0)
  • (X:0.8, Y:-3.0, Z:0)
  • (X:3.8, Y:-3.0, Z:0)

完结后,场景应如下所示。

【Unity小游戏】游戏开发案例,轻松打造一款塔防游戏!(上)

放置怪物

为了便于放置,项意图预制件文件夹包括一个_怪物__预制_件。

【Unity小游戏】游戏开发案例,轻松打造一款塔防游戏!(上)

怪物预制件 – 随时可用

此刻,它由一个空的游戏目标组成,其间包括三个不同的精灵及其子元素的射击动画。

每个精灵代表不同力气水平的怪物。预制件还包括一个_音频源_组件,每逢怪物发射激光时,您都会触发该组件来播放声响。

您现在将创立一个能够将Monster放置在Openspot上的脚本

在“项目浏览器”中,挑选“预制件”文件夹中的_“Openspot_”。在_查看器_中,点按“增加组件”,然后选取_“新建脚本_”并将其命名_为 PlaceMonster_。挑选C ​​Sharp 作为_语言_,然后单击_创立和增加_。由于您已将脚本增加到 Openspot _预制件_中,因而场景中的一切 Openspot 现在也附加了该脚本。整洁!

双击脚本以在 IDE 中将其翻开。然后增加这两个变量:

public GameObject monsterPrefab;
private GameObject monster;

您将实例化存储在其间的目标的副本monsterPrefab以创立怪物,并将其存储在其间monster以便您能够在游戏进程中对其进行操作。

每个方位一个怪物

增加以下办法,每个方位只答应一个怪物:

private bool CanPlaceMonster()
{
  return monster == null;
}

CanPlaceMonster()你查看monster变量是否仍然null.假如是的话,说明这儿现在没有怪物,放一个也能够。

现在增加以下代码,以便在玩家单击此游戏目标时实践放置怪物:

void OnMouseUp()
{
  if (CanPlaceMonster())
  {
    monster = (GameObject) 
      Instantiate(monsterPrefab, transform.position, Quaternion.identity);
    AudioSource audioSource = gameObject.GetComponent<AudioSource>();
    audioSource.PlayOneShot(audioSource.clip);
  }
}

此代码在鼠标单击或点击时放置一个怪物。那么这是怎么实现的呢?

  1. OnMouseUp当玩家点击游戏目标的物理磕碰器时,Unity 会自动调用。
  2. CanPlaceMonster()调用时,假如回来,此办法会放置一个新怪物true
  3. 您运用 来创立怪物Instantiate,该办法创立具有指定方位和旋转的给定预制件的实例。在这种状况下,您复制monsterPrefab,为其供给当时游戏目标的方位且不进行旋转,将结果转换为 aGameObject并将其存储在monster.
  4. 最终,您调用PlayOneShot播放附加到目标AudioSource组件的声响作用。

现在你的PlaceMonster脚本能够放置一个新的怪物,但你仍然必须指定预制件。

运用正确的预制件

保存文件并切换回 Unity。

要分配 monsterPrefab 变量,请先在项目浏览器的_预制件_文件夹中挑选 Openspot

在__查看器__中,单击 PlaceMonster(脚本)组件的“怪物_预制件”字段右侧的圆圈,然后从出现的对话框中挑选Monster”。

【Unity小游戏】游戏开发案例,轻松打造一款塔防游戏!(上)

就是这样。运转场景并经过单击或点击在各种x点上构建怪物。

【Unity小游戏】游戏开发案例,轻松打造一款塔防游戏!(上)

成功!你能够制作怪物。然而,它们看起来像一个古怪的糊状物,由于你的怪物的一切子精灵都被制作出来了。接下来,您将处理此问题。

晋级那些怪物

鄙人图中,你会看到你的怪物在更高层次上看起来越来越可怕。

【Unity小游戏】游戏开发案例,轻松打造一款塔防游戏!(上)

太蓬松了!可是假如你企图偷它的饼干,这个怪物可能会变成杀手。

脚本充任为怪物实现晋级体系的基础。它盯梢怪物在每个等级上应该有多强大,当然还有怪物的当时等级。

现在增加此脚本。

在_项目浏览器中_挑选_预制件/怪物_。增加一个名为 MonsterData 的新 C# 脚本。在 IDE 中翻开脚本,并在类_上方_增加以下代码。MonsterData

[System.Serializable]
public class MonsterLevel
{
  public int cost;
  public GameObject visualization;
}

这将创立 MonsterLevel.它对本钱(以金币为单位,稍后会支撑)和特定怪物关卡的视觉表明方式进行分组。

[System.Serializable]您能够在顶部增加以使类的实例可从查看器进行修改。这使您能够快速更改 Level 类中的一切值,即使在游戏运转时也是如此。它关于平衡你的游戏十分有用。

界说怪物等级

在本例中,您将预界说的怪物等级存储在列表<T>中。 为什么不简单地运用MonsterLevel[]MonsterLevel那么,您将屡次需求特定目标的索引。虽然为此编写代码并不困难,但您将运用IndexOf(),它实现了 的功能Lists。这次无需重复写一个办法。:]

MonsterData.cs 的顶部,增加以下语句:using

using System.Collections.Generic;

这使您能够拜访通用数据结构,因而能够在脚本中运用该类。List<T>

留意:泛型是 C# 的重要组成部分。它们答应您界说类型安全的数据结构,而无需提交类型。这关于列表和集合等容器类十分实用。若要了解有关泛型的详细信息,请查看 C# 泛型简介。

现在将以下变量增加到 MonsterData 中以存储 MonsterLevel 列表:

public List<MonsterLevel> levels;

运用泛型,您能够保证只能包括目标。levels``List``MonsterLevel

保存文件并切换到 Unity 以配置每个阶段。

在_项目浏览器中_挑选_预制件/怪物_。在__查看器__中,您现在能够在 MonsterData(脚本)组件中看到“等级”字段。将其_巨细_设置为 3

【Unity小游戏】游戏开发案例,轻松打造一款塔防游戏!(上)

接下来,将每个等级的_本钱_设置为以下值:

  • 元素 0200
  • 元素 1110
  • 元素 2120

现在分配可视化字段值。

在项目浏览器中翻开预_制件/怪物_,以便能够看到其子项。将子 Monster0 拖放到_元素 0_ 的_可视化_字段中。

重复此操作,将怪物 1 分配给_元素 1_,将_怪物_ 2 分配给_元素 2_。请参阅以下演示此进程的 GIF:

【Unity小游戏】游戏开发案例,轻松打造一款塔防游戏!(上)

挑选预制件_/怪物时,预制件_应如下所示:

【Unity小游戏】游戏开发案例,轻松打造一款塔防游戏!(上)

在查看器中界说怪物的等级。

界说当时等级

在 IDE 中_切换_回 MonsterData.cs并将另一个变量增加到 MonsterData

private MonsterLevel currentLevel;

在私有变量中,currentLevel您将存储……等等……怪物的当时等级。]

现在设置currentLevel并使其可供其他脚本拜访。将以下内容增加到MonsterData, 以及实例变量声明:

public MonsterLevel CurrentLevel
{
  get 
  {
    return currentLevel;
  }
  set
  {
    currentLevel = value;
    int currentLevelIndex = levels.IndexOf(currentLevel);
    GameObject levelVisualization = levels[currentLevelIndex].visualization;
    for (int i = 0; i < levels.Count; i++)
    {
      if (levelVisualization != null) 
      {
        if (i == currentLevelIndex) 
        {
          levels[i].visualization.SetActive(true);
        }
        else
        {
          levels[i].visualization.SetActive(false);
        }
      }
    }
  }
}

那里有相当多的 C#脚本,嗯?把一切都看一遍:

  1. 界说私有_变量的特点currentLevel。_界说特点后,您能够像调用任何其他变量相同调用:asCurrentLevel(从类内部)或 as monster.CurrentLevel(从类外部)。您能够在特点的 getter 或 setter 办法中界说自界说行为,而且经过仅供给 getter、setter 或两者,您能够操控特点是只读、只写还是读/写。
  2. 在 getter 中,回来currentLevel的值。
  3. 在资源库中,将新值分配给currentLevel 。接下来,您将取得当时等级的索引。最终,循环拜访一切_等级_,并将可视化设置为活动或非活动,详细取决于currentLevelIndex .这很棒,由于这意味着每逢有人设置currentLevel 时,子画面都会自动更新。特点肯定会派上用场!

增加以下 实现OnEnable

void OnEnable()
{
  CurrentLevel = levels[0];
}

这CurrentLevel将在放置时设置,保证它只显现正确的精灵。

留意:在 OnEnable初始化特点而不是OnStart 十分重要,由于您能够在实例化预制件时调用 order 办法。

创立预制件时,将当即调用 OnEnable(假如预制件以启用状态保存),但直到目标开端作为场景的一部分运转后才会调用 OnStart

在放置怪物之前,您需求查看此数据,因而您能够在 OnEnable 中对其进行初始化。

保存文件并切换到 Unity。运转项目并放置怪物;现在,它们显现正确和最低等级的精灵。

【Unity小游戏】游戏开发案例,轻松打造一款塔防游戏!(上)

晋级那些怪物

切换回您的 IDE,并将以下办法增加到 MonsterData

public MonsterLevel GetNextLevel()
{
  int currentLevelIndex = levels.IndexOf (currentLevel);
  int maxLevelIndex = levels.Count - 1;
  if (currentLevelIndex < maxLevelIndex)
  {
    return levels[currentLevelIndex+1];
  } 
  else
  {
    return null;
  }
}

GetNextLevel中,您能够取得当时等级的索引和最高等级的索引,前提是怪物没有抵达最大等级以回来下一个等级。否则,回来 null

您能够运用此办法来确定是否能够晋级怪物。

增加以下办法以提高怪物的等级:

public void IncreaseLevel()
{
  int currentLevelIndex = levels.IndexOf(currentLevel);
  if (currentLevelIndex < levels.Count - 1)
  {
    CurrentLevel = levels[currentLevelIndex + 1];
  }
}

在这儿,您能够取得当时等级的索引,然后经过查看它是否小于 来保证它不是最大等级。假如是这样,请设置为下一个等级。levels.Count - 1``CurrentLevel

测验晋级才能

保存该文件,然后在 IDE 中切换到 PlaceMonster.cs 并增加以下新办法:

private bool CanUpgradeMonster()
{
  if (monster != null)
  {
    MonsterData monsterData = monster.GetComponent<MonsterData>();
    MonsterLevel nextLevel = monsterData.GetNextLevel();
    if (nextLevel != null)
    {
      return true;
    }
  }
  return false;
}

首要查看是否有能够晋级的怪物,办法是查看怪物变量是否为 null。假如是这种状况,您能够从怪物数据中获取怪物的当时等级。

然后测验是否有更高等级可用,即 GetNextLevel() 不回来 null 时。假如能够晋级,则回来 true,否则回来 false

启用金牌晋级

要启用晋级选项,请将 else if 分支增加到 OnMouseUp

if (CanPlaceMonster())
{
}
else if (CanUpgradeMonster())
{
  monster.GetComponent<MonsterData>().IncreaseLevel();
  AudioSource audioSource = gameObject.GetComponent<AudioSource>();
  audioSource.PlayOneShot(audioSource.clip);
}

查看是否能够运用 CanUpgradeMonster() 进行晋级。假如是,您能够运用 GetComponent() 拜访 MonsterData 组件并调用 IncreaseLevel(),这将增加怪物的等级。最终,你触发怪物的_音频源_。

保存文件并切换回 Unity。运转游戏,放置和晋级_恣意数量的_怪物…现在。

【Unity小游戏】游戏开发案例,轻松打造一款塔防游戏!(上)

一切怪物晋级

付出金币 – 游戏管理器

现在,能够当即制作和晋级一切怪物,但这其间的应战在哪里?

让我们深入了解黄金问题。盯梢它的问题在于您需求在不同的游戏目标之间同享信息。

下图显现了一切要参加其间的目标。

【Unity小游戏】游戏开发案例,轻松打造一款塔防游戏!(上)

杰出显现的游戏目标都需求知道,玩家具有多少金币。

您将运用其他目标可拜访的同享目标来存储此数据。

在_层次结构_中单击鼠标右键,然后挑选“创立空”。将新游戏目标命名_为游戏管理器_。

将一个名为 GameManagerBehavior 的 C# 脚本增加到 GameManager,然后在 IDE 中翻开新脚本。您将在标签中显现玩家的总金币,因而请在文件顶部增加以下行:

using UnityEngine.UI;

这使您能够拜访特定于 UI 的类,例如 ,项目将其用于标签。现在将以下变量增加到类中:Text

public Text goldLabel;

Text这将存储对用于显现玩家具有多少金币的组件的引证。

既然GameManager知道了标签,您怎么保证变量中存储的黄金数量与标签上显现的数量同步?您将创立一个特点。

将以下代码增加到GameManagerBehavior

private int gold;
public int Gold {
  get
  { 
    return gold;
  }
  set
  {
    gold = value;
    goldLabel.GetComponent<Text>().text = "GOLD: " + gold;
  }
}

好像很熟悉?它类似于您在CurrentLevel 中界说的Monster。首要,创立一个私有变量gold ,来存储当时的黄金总量。然后你界说一个名为Gold — creative的特点,对吧?– — 并实现一个 getter 和 setter。

getter 只需回来 gold的值。setter更有趣。除了设置变量的值外,它还将字段text设置为“翻开”以goldLabel显现新的黄金数量。

你觉得有多慷慨?增加以下行以Start()给玩家 1000 金币,假如您感到小气,则分配更少:

Gold = 1000;

将标签目标分配给脚本

保存文件并切换到 Unity。

Hierarchy中,挑选GameManager。在Inspector 中,单击Gold Label右侧的圆圈。在Select Text对话框中,挑选Scene选项卡并挑选GoldLabel

【Unity小游戏】游戏开发案例,轻松打造一款塔防游戏!(上)

运转场景,标签显现_Gold:1000_。

【Unity小游戏】游戏开发案例,轻松打造一款塔防游戏!(上)

查看玩家的“钱包”

在 IDE 中_.cs翻开 PlaceMonster_,然后增加以下实例变量:

private GameManagerBehavior gameManager;

您将用于gameManager拜访GameManagerBehavior场景的GameManager的组件。要分配它,请将以下内容增加到Start()

gameManager = GameObject.Find("GameManager").GetComponent<GameManagerBehavior>();

您能够运用 获取名为 GameManager 的游戏目标,该游戏目标回来它找到的第一个具有给定称号的游戏目标。然后,检索其组件并将其存储以供今后运用。GameObject.Find()``GameManagerBehavior

留意:您能够经过在 Unity 修改器中设置字段或向 GameManager 增加静态办法来实现此意图,该办法回来一个单一实例,您能够从中获取游戏管理器行为

可是,上面的块中有一个黑马办法:,它在运转时速度较慢,但方便且能够慎重运用。Find

拿钱!

你还没有扣除金币,所以在 OnMouseUp() 中增加_了两次_这一行,替换每个注释 // TODO: 扣除金币:

gameManager.Gold -= monster.GetComponent<MonsterData>().CurrentLevel.cost;

保存文件并切换到 Unity,晋级一些怪物并观看黄金读数更新。现在你扣除金币,但玩家只需有空间就能够制作怪物。

【Unity小游戏】游戏开发案例,轻松打造一款塔防游戏!(上)

无限才能?棒!但你不能答应这种状况产生。只有当玩家有足够的金币时,才应该放置怪物。

怪物需求金币

在 IDE 中切换到 PlaceMonster.cs,并将 CanPlaceMonster()的内容替换为以下内容:

int cost = monsterPrefab.GetComponent<MonsterData>().levels[0].cost;
return monster == null && gameManager.Gold >= cost;

levels从其 中检索放置怪物的本钱MonsterData。然后你查看它monster不是null而且它gameManager.Gold大于本钱。

CanUpgradeMonster()应战:增加自己查看玩家是否有足够的金币。

替换此行:

return true;

有了这个:

return gameManager.Gold >= nextLevel.cost;

这将查看玩家具有的_金币_是否超过晋级本钱。

在 Unity 中保存并运转场景。来吧,试着放置无限的怪物!

【Unity小游戏】游戏开发案例,轻松打造一款塔防游戏!(上)

现在你只能制作有限数量的怪物。

塔政治:敌人、波涛和航点

是时分为你的敌人“铺路”了。敌人出现在第一个航点,向下一个航点移动并重复,直到他们抵达你的饼干。

你会让敌人行进:

  1. 为敌人确定一条路途
  2. 沿路移动敌人
  3. 旋转敌人使其向前看

创立带有航点的路途

在_层次结构_中单击鼠标右键,然后挑选创立空以创立新的_空_游戏目标。将其命名为 Road,并保证它位于方位 (0, 0, 0)。

现在,右键单击_层次结构_中的 Road,并创立另一个空游戏目标作为 Road 的子目标。将其命名为_Waypoint0_并将其方位设置为_(-12,2,0)_ – 这是敌人开端攻击的当地。

【Unity小游戏】游戏开发案例,轻松打造一款塔防游戏!(上)

运用以下称号和方位以相同的方式再创立五个航点:

  • 航点 1: (X:7, Y:2, Z:0)
  • 航点 2: (X:7, Y:-1, Z:0)
  • 航点3: (X:-7.3, Y:-1, Z:0)
  • 航点4: (X:-7.3, Y:-4.5, Z:0)
  • 航点5: (X:7, Y:-4.5, Z:0)

以下屏幕截图杰出显现了航点方位和生成的途径。

【Unity小游戏】游戏开发案例,轻松打造一款塔防游戏!(上)

生成敌人

现在要制作一些敌人来跟路。_预制件_文件夹包括_敌人_预制件。它的方位是 _(-20, 0, 0),_因而新实例将在屏幕外生成。

否则,它的设置很像Monster预制件,有一个AudioSource和一个 childSprite,而且它是一个精灵,所以你能够稍后旋转它,而无需旋转即将需求的血量条。

【Unity小游戏】游戏开发案例,轻松打造一款塔防游戏!(上)

### 把怪物移到路上

将一个名为 MoveEnemy 的新 C# 脚本增加到预制件_\Enemy 预制件_。在 IDE 中翻开脚本,然后增加以下变量:

[HideInInspector]
public GameObject[] waypoints;
private int currentWaypoint = 0;
private float lastWaypointSwitchTime;
public float speed = 1.0f;

waypoints将航点的副本存储在一个数组中,而上述内容可保证您不会意外更改__查看器__中的字段,但您仍然能够从其他脚本拜访它。[HideIn_inspector_]``waypoints

currentWaypoint盯梢敌人当时正在脱离的路点,lastWaypointSwitchTime存储敌人经过它的时刻。最终,存储敌人的speed

Start() 中增加此行:

lastWaypointSwitchTime = Time.time;

这将初始化lastWaypointSwitchTime为当时时刻。

要使敌人沿着途径移动,请将以下代码增加到 Update() 中:

Vector3 startPosition = waypoints [currentWaypoint].transform.position;
Vector3 endPosition = waypoints [currentWaypoint + 1].transform.position;
float pathLength = Vector3.Distance (startPosition, endPosition);
float totalTimeForPath = pathLength / speed;
float currentTimeOnPath = Time.time - lastWaypointSwitchTime;
gameObject.transform.position = Vector2.Lerp (startPosition, endPosition, currentTimeOnPath / totalTimeForPath);
if (gameObject.transform.position.Equals(endPosition)) 
{
  if (currentWaypoint < waypoints.Length - 2)
  {
    currentWaypoint++;
    lastWaypointSwitchTime = Time.time;
  }
  else
  {
    Destroy(gameObject);
    AudioSource audioSource = gameObject.GetComponent<AudioSource>();
    AudioSource.PlayClipAtPoint(audioSource.clip, transform.position);
  }
}

按部就班:

  1. 从路点数组中,您能够检索当时途径段的开端和完毕方位。
  2. 用公式时刻=距离/速度计算全程所需时刻,然后确定途径上的当时时刻。运用Vector2.Lerp,您能够在段的开端方位和完毕方位之间刺进敌人的当时方位。
  3. 查看敌人是否现已抵达endPosition。假如是,请处理这两种可能的状况:
    1. 敌人还没有在最终一个航路点,所以增加currentWaypoint和更新lastWaypointSwitchTime。稍后,您将增加代码来旋转敌人,使其也指向它移动的方向。
    2. 敌人抵达了最终一个路点,所以这会摧毁它并触发声响作用。稍后您还将增加代码来削减玩家的health

保存文件并切换到 Unity。

给敌人一个方向感

在现在的状态下,敌人不知路途标的顺序。

Hierarchy中挑选Road ,并增加一个名为 SpawnEnemy的新C# 脚本。然后在您的 IDE 中翻开它,并增加以下变量:

public GameObject[] waypoints;

您将运用它waypoints以正确的顺序存储场景中的路点。

保存文件并切换到 Unity。在_层次结构_中挑选_路途_,并将_航点_数组_的巨细_设置为 6

将 Road 的每个子项拖到字段中,将 Waypoint0 放入元素 0,将 Waypoint1 放入_元素 1_,依此类推。

【Unity小游戏】游戏开发案例,轻松打造一款塔防游戏!(上)

现在你有一个数组,其间包括整齐有序的航点,所以有一条途径——请留意,它们永久不会撤退;他们会死在企图得到糖的路上。

【Unity小游戏】游戏开发案例,轻松打造一款塔防游戏!(上)

查看一切是否正常

前往 IDE 中的 SpawnEnemy,并增加以下变量:

public GameObject testEnemyPrefab;

这会在 testEnemyPrefab 中保留对 Enemy 预制件的引证。

要在脚本启动时创立敌人,请将以下代码增加到 Start():

Instantiate(testEnemyPrefab).GetComponent<MoveEnemy>().waypoints = waypoints;

这将实例化存储在 testEnemy中的预制件的新副本,并为其分配要遵从的航点。

保存文件并切换到 Unity。在Hierarchy中挑选Road并将其Test Enemy设置为Enemy预制件。

运转项目,看到敌人沿着这条路走。

运转项目以查看敌人沿着路途行进。

【Unity小游戏】游戏开发案例,轻松打造一款塔防游戏!(上)

你有没有留意到他们并不总是在寻找他们要去的当地?有趣!假如你想在这个项目上更进一步,持续第二部分并完善这个项目,学习怎么令他们体现得更出色。

后续

你现已做了许多作业,而且正在具有自己的塔防游戏。

玩家能够制作怪物,但不是无限数量,而且有一个敌人跑向你的饼干。玩家具有金币,还能够晋级怪物。

在第二部分中,你将介绍生成大量敌人并将它们炸飞。第二部分见

【Unity小游戏】游戏开发案例,轻松打造一款塔防游戏!(下) – 掘金 ()