如何在unity中制作塔防游戏——敌人来了

到了为敌人“铺路”的时候啦。敌人出现在第一个路径点,然后向下一个移动并重复执行直到它们到达曲奇。

可以通过以下让敌人游行:

  1. 定义一个敌人追踪的路径
  2. 沿路移动敌人
  3. 旋转敌人以便他们看起来是向前的

用路径点创建一条路

在Hierarchy 右键选择Create Empty 来创建一个新的空游戏对象。命名为Road,并确认它的位置是(0, 0, 0)。

现在,在hierarchy 中右键点击Road 并创建另一个空游戏对象作为Road的子集。命名为Waypoint0 并将它的位置设置为 (-12, 2, 0) ——这就是敌人发起攻击的起始点。

用下边的名字和位置同样再创建五个路径点:

Waypoint1: (7, 2, 0)
Waypoint2: (7, -1, 0)
Waypoint3: (-7.3, -1, 0)
Waypoint4: (-7.3, -4.5, 0)
Waypoint5: (7, -4.5, 0)

下边的屏幕截图点亮了路径点位置和路径结果。

产生敌人

现在制作一些敌人来追踪线路。Prefabs 文件夹包含了一个Enemy 预制件。它的位置是(-20, 0, 0),因此新的实例可以在屏幕中大量产生。

另外,它的设置和Monster预制件很相似,有一个AudioSource 和一个子集Sprite,并且它是一个精灵因此可以不用现成的健康条就可以旋转它。

沿路移动怪兽

为Prefabs\Enemy 添加一个名为MoveEnemy 的 C# 脚本。在MonoDevelop中打开脚本,并添加以下变量:

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

waypoints 将路径点存储到一个数组中,waypoints 上方的[HideIninspector] 用来确保不会一不小心改变了inspector中的字段,不过仍然可以通过其他脚本访问它。currentWaypoint 监测敌人当前走过的路径点,lastWaypointSwitchTime存储通过它的时长。最后,存储敌人的speed。

将下边这行添加到Start():

lastWaypointSwitchTime=Time.time;

这个将 lastWaypointSwitchTime 初始化为当前时间。

为了让敌人沿着路径移动,将下边代码添加到Update():

// 1 
Vector3 startPosition= waypoints [currentWaypoint].transform.position;
Vector3 endPosition= waypoints [currentWaypoint+1].transform.position;
// 2 
float pathLength= Vector3.Distance(startPosition, endPosition);
float totalTimeForPath=pathLength/ speed;
float currentTimeOnPath=Time.time-lastWaypointSwitchTime;
gameObject.transform.position= Vector3.Lerp(startPosition, endPosition, currentTimeOnPath/totalTimeForPath);
// 3 
if(gameObject.transform.position.Equals(endPosition)){
if(currentWaypoint<waypoints.Length-2){
// 3.a 
currentWaypoint++;
lastWaypointSwitchTime=Time.time;
// TODO: Rotate into move direction
}else{
// 3.b 
    Destroy(gameObject);
AudioSource audioSource=gameObject.GetComponent<AudioSource>();
AudioSource.PlayClipAtPoint(audioSource.clip, transform.position);
// TODO: deduct health
}
}

一步一步做:

  1. 从路径点数组中检索当前路径段的起始点和终点位置。
  2. 用time = distance / speed公式计算整个距离需要的时间,然后决定当前路径上的时间。使用Vector3.Lerp来差值计算位于路径段起始点和终点位置间的当前位置。
  3. 检查敌人是否到达了endPosition。如果是,处理这两种情形:
    • 敌人还没有到达最后一个路径点,因此增加currentWaypoint 并更新lastWaypointSwitchTime,之后,需要添加代码来旋转敌人因此它也会指向它移动的方向。
    • 敌人到达了最后一个路径点,所以销毁它并触发一个声音效果。之后,还需要添加代码来减少玩家的生命值。

保存文件并切换到unity。

给敌人一个方向感知

在它的当前状态,敌人不知道路径点的顺序。在Hierarchy中选择 Road ,添加一个名为SpawnEnemy的C# 脚本。在MonoDevelop中打开并添加以下变量:

public GameObject[] waypoints;

用waypoints 来存储场景中正确次序路径点的引用。

保存文件并切换到unity。在Hierarchy 中选择Road 并将Waypoints 数组的Size 设置为6。

将Road的子集拖拽到区域内,将Waypoint0 放在Element 0,Waypoint1放在Element 1并以此类推。

现在有了一个包含整齐路径点的数组,由此形成一个路径——注意他们永远不会撤退;它们将在视图接近糖块是死掉。

检查一切顺

回到MonoDevelop中的SpawnEnemy 并添加以下变量:

public GameObject testEnemyPrefab;

这个存放了testEnemyPrefab中Enemy 预制件的引用。
当游戏开始时为了创建敌人,在Start()中添加以下代码:

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

这个实例化了一个存储在testEnemy 中的预制件副本,并为它分配追踪的路径点。

保存文件并切换到unity。在Hierarchy 中选择Road 并为Test Enemy 设置Enemy 预制件。

运行项目观察敌人追踪线路。

注意到他们并不是看着他们走的方向了吗?有趣!不过你想尝试更专业一些,对吧?继续看第二部分来学习怎样使他们有最好的朝向。

何去何从?

现在已经完成很多了并且在制作属于自己的塔防游戏的路上做的很好。

玩家可以创建怪兽,不过并不是没有限制的,而且还有敌人向着曲奇奔去。玩家拥有金币并且还可以升级怪兽。

下一期将会学习制作产生一大波的敌人并吹散它们。


转至:游戏蛮牛

标签: unity, unity2d, unity制作塔防游戏

?>