如何在unity中制作塔防游戏

来源:互联网 发布:淘宝带带店卫生带 编辑:程序博客网 时间:2024/05/18 03:33

 

塔防游戏非常流行,毫无疑问——没有什么比看着自己的防御消灭讨厌的侵略者更让人满足!在这两部分教程中,用unity来制作一个塔防游戏!
将会学习怎样......
创建一波敌人
让它们跟随线路点
创建并升级塔,让它们把敌人击碎,最后,将得到一个可以自己扩展的此类型游戏的框架!

注:这个需要unity基础,比如怎样添加游戏资源和组件,理解预制件还要知道一些基础的C#,为了学习这些内容建议去看一下Chris LaPollo的unity教程。我将使用OS X版本的unity,不过这个教程也可以用在Windows上。

从象牙塔来看

在这篇教程中创建一个塔防游戏,敌人(小虫子)向着你和你的下属的曲奇爬来,这些下属当然是怪兽!可以用一些金子来放置并升级这些怪兽。
玩家必须在虫子享用曲奇之前消灭它们。每一波敌人都会越来越难击败。当在每一波攻击中活下来(胜利!)或者是当五个敌人到达曲奇时(失败!)游戏结束。
这里有一个完成的游戏屏幕截图。


 

怪兽联盟!保护曲奇!


开始吧

如果还没有unity5或更新的版本,去Unity’s website下载吧。还有,下载起始项目(回复可见),解压并在unity中打开TowerDefense-Part1-Starter 项目。
起始项目中包含美术和声音资源,还附加了预建的动画和一些有用的脚本。脚本并不是直接关系到塔防游戏的,所以这里不会解释它们。然而,如果想学一些关于创建unity2D动画的东西,请查看Unity 2D tutorial。

项目里好包含了稍后用来创建角色的预制件,项目包括一个有背景和用户界面设置的场景。
打开GameScene,可以在Scenes文件夹中找到,将游戏视口比例设置没4:3 以确保标签队列能正确的适应背景。在游戏视口中会看到以下内容:

 


清单:
项目的美术资源来源于Vicki Wenderlich的免费美术包!可以在她的gameartguppy看到更多非常漂亮的图形.
好听的音乐来自于做过很多很棒的电影原声的BenSound!
感谢Michael Jasper有影响力的camera shake。 

起始项目——检查!
资源——检查!
统治世界的的第一步...呃,我的意思是塔防游戏完成了!

X标记点:布局

怪兽只能被放置在标记x的点。
为了将这些添加到场景中,从Project Browser 拖动Images\Objects\Openspot到场景视图。目前,位置不重要。在层级面板选择Openspot ,在监视面板点击Add Component 并选择Physics 2D\Box Collider 2D。unity会在场景视图显示一个绿色线条的盒子碰撞器。将会用这个碰撞器在该点来检测鼠标点击。



 

unity会自动检测碰撞器的合适尺寸,这是不是很酷?

按照相同的步骤,为Openspot添加Audio\Audio Source 组件。将音频源的AudioClip 设置为Audio 文件夹里的tower_place,并停用Play On Awake。
接下来还需要创建11个点。虽然重复所有的步骤很容易,不过unity有一个很伟大的解决方法:Prefabs!
将Openspot 从层级面板中拖放到项目浏览器的Prefabs 文件夹。在层级面板中它的名字会变成蓝色来显示它被关联到了一个预制件。像这样:

 

现在有了预制件,就可以根据需要创建很多数量的副本了。将Project Browser 里Prefabs文件夹中的Openspot拖放到场景视图中。重复11次以便在场景中一共做出12个位置点。
(-5.2, 3.5, 0)
(-2.2, 3.5, 0)
(0.8, 3.5, 0)
(3.8, 3.5, 0)
(-3.8, 0.4, 0)
(-0.8, 0.4, 0)
(2.2, 0.4, 0)
(5.2, 0.4, 0)
(-5.2, -3.0, 0)
(-2.2, -3.0, 0)
(0.8, -3.0, 0)
(3.8, -3.0, 0)

做完之后,场景看起来是这样的。


 

放置怪兽
为了便于放置,项目的Prefab 文件夹包含了一个Monster 预制件。



 

怪兽——已经准备好使用了

这时,它是一个由三个不同精灵和作为子集的射击动画组成的空游戏对象。每一个精灵代表怪兽在不同的能力等级。预制件还包含了一个Audio Source组件,每当怪兽发射激光时都可以触发它来播放一段音乐。

现在要创建可以在Openspot上放置Monster 的脚本了。在Project Browser中,从Prefabs 选择Openspot 。在Inspector中,点击Add Component,然后选择New Script 并命名为PlaceMonster。选择C Sharp语言并点击Create and Add。由于给Openspot预制件添加了脚本,场景中所有的Openspots都有了附加的脚本。多么整齐!
双击脚本以便在MonoDevelop中打开。然后填入下边两个变量:


[C#] 纯文本查看 复制代码
?
 
1
publicGameObject monsterPrefab;
privateGameObject monster;



要实例化存储在monsterPrefab中的对象来创建一个怪兽,并将它存储在monster以便在游戏中可以控制它。

每个位置一个怪兽
添加下边的方法来允许每个位置只放置一个怪兽:


[C#] 纯文本查看 复制代码
?
 
1
2
privatebool canPlaceMonster(){
returnmonster ==null;[/size][/font]
[font=微软雅黑][size=3]}



在canPlaceMonster()中检查monster变量是否为空。如果是,意味着目前这里没有怪兽并且可以放置一个。
现在添加下边的代码以便玩家点击这个游戏对象时实际放置一个怪兽:


[C#] 纯文本查看 复制代码
?
 
01
02
03
04
05
06
07
08
09
10
11
12
13
//1
voidOnMouseUp(){
//2
if(canPlaceMonster()){
//3
    monster =(GameObject)
      Instantiate(monsterPrefab, transform.position, Quaternion.identity);
//4
AudioSource audioSource=gameObject.GetComponent<AudioSource>();
audioSource.PlayOneShot(audioSource.clip);
 
// TODO: Deduct gold
}
}



点击鼠标时这段代码会放置一个怪兽,这是怎么实现的?
1.当玩家点击游戏对象的物理碰撞器时unity会自动呼叫OnMouseUp。
2.呼叫时,如果canPlaceMonster() 返回值为true时这个方法放置一个新的怪兽。
3.用Instantiate来创建怪兽,一个创建有特殊位置和旋转的预制件实例的方法。这种情况下,复制monsterPrefab,给它现有游戏对象的位置并且不做旋转,将结果抛给GameObject 并在 monster里存储它。
4.最后,呼叫PlayOneShot来播放附加在对象的AudioSource组件上的声音效果。
现在,PlaceMonster 脚本可以放置新的怪兽了,不过还是需要指定预制件。

使用正确的预制件

保存文件并切换到unity场景。
为了指定monsterPrefab 变量,首先在项目浏览视口的Prefabs 文件夹里选择Openspot 。
在Inspector中,点击PlaceMonster (Script) 组件的Monster Prefab 字段右边的圆圈,并从出现的对话框中选择Monster 。



 

就是那个。运行场景并且通过点击在不同的x点放置怪兽。

 
成功啦!现在可以创建怪兽了。然而它们看起来有些奇怪,因为怪兽所有的子精灵都是画出来的。以后会修复它。
升级这些怪兽
在下图中,能看到在更高级别中怪兽看起来有多恐怖。


 
它太松软了!不过如果尝试去偷它的曲奇,怪兽就会变成杀手。

脚本作为执行怪兽登记系统的基础。它追踪在每一个等级怪兽拥有的力量,当然有怪兽的当前等级。
现在创建这个脚本。
ProjectBrowser中选择Prefabs/Monster ,添加C# 脚本并命名为MonsterData。在MonoDevelop中打开脚本并在MonsterData 类上方添加以下代码。


[C#] 纯文本查看 复制代码
?
 
1
2
3
4
[System.Serializable]
publicclass MonsterLevel{
publicint cost;
publicGameObject visualization;
}



这个创建了MonsterLevel。它将花费(金币,以后将会支持)和特定怪兽级别的视觉形象归为一组。
在顶部添加 [System.Serializable] 来使类的实例可以在检视面板中编辑。这样允许快速更改Level类中的所有值——及时游戏正在运行。这个对于平衡游戏非常有用。

定义怪兽等级


这种情况下,将预先定义的MonsterLevel 存储在一个List<T>里。
为什么不仅仅用MonsterLevel[]?因为这里多次需要特定MonsterLevel 对象的索引。当然为这个写代码并不难,使用执行 Lists功能的IndexOf()。这里就不用重复工作了。



 

重组轮子通常是一个坏主意(来自Michael Vroegop)

在MonsterData.cs顶部添加下边的using声明:


[C#] 纯文本查看 复制代码
?
 
usingSystem.Collections.Generic;




这使你可以访问通用数据结构,因此可以在脚本中使用List<T> 类型。

注:泛型是C#中非常强大的一部分。它们允许你在没有指定类型的情况下定义一个类型安全的数据结构。这个对于像列表和集合这种容器类型非常实用。想学更多关于泛型的知识,看一下Introduction to C# Generics。


现在在MonsterData 中添加以下变量来存储MonsterLevel的列表:


[C#] 纯文本查看 复制代码
?
 
publicList<MonsterLevel> levels;



如果使用泛型,请确保 levels List 只包含了MonsterLevel 对象。
保存文件并切换到unity来配置每个阶段。
在Project Browser中选择Prefabs/Monster 。在 Inspector中,可以在MonsterData (Script) 组件中看到一个Levels 字段。将它的size 设置为3.

 

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


Element 0: 200
Element 1: 110
Element 2: 120


现在分配可视化区域值。
在项目浏览视口展开Prefabs/Monster 以便看到它的子集。将子集 Monster0拖拽到Element 0的visualization 区域。重复将Monster1 分配到 Element 1 并将Monster2 分配到 Element 2。看下边演示这个过程的GIF。



 



当选择 Prefabs/Monster时,预制件看起来应该是这样的:


 
监视面板中怪兽等级的定义。

定义当前等级


切换回MonoDevelop中的MonsterData.cs ,并为MonsterData添加另一个变量。


[C#] 纯文本查看 复制代码
?
 
privateMonsterLevel currentLevel;



在私有变量currentLevel 中将会存储怪兽的当前等级。我确信你没有看到那个到来:]
现在设置currentLevel 并使它可以被其他脚本访问。将下边代码随着实例变量声明加入到MonsterData中:


[C#] 纯文本查看 复制代码
?
 
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
//1
publicMonsterLevel CurrentLevel{
//2
  get{
returncurrentLevel;
}
//3
  set{
currentLevel= value;
intcurrentLevelIndex=levels.IndexOf(currentLevel);
 
GameObject levelVisualization= levels[currentLevelIndex].visualization;
for(inti=0;i<levels.Count;i++){
if(levelVisualization!=null){
if(i==currentLevelIndex){
          levels[i].visualization.SetActive(true);[/i]
}else{
[i]          levels.visualization.SetActive(false);
}
}
}
}
}

有太多的C#?按顺序看一下:


1.为私有变量currentLevel定义一个属性。随着属性的定义就,就可以像其他变量一样呼叫了:像CurrentLevel (从类的内部)或monster.CurrentLevel(从类的外部)一样。在属性的getter或 setter方法里可以定义自定义行为,通过仅仅使用一个getter,setter或者两者同时使用,可以控制属性是只读,只写,还是读写。
2.在getter中,返回currentLevel值。
3.在setter中,为currentLevel分配新的值。接下来获取现有等级的索引。最后依据currentLevelIndex迭代所有的levels 并设置可视化是否为激活状态。这样写太棒了,因为这意味着无论什么时候设置了currentLevel,精灵都会自动更新。属性确实很方便使用。
Add the following implementation of OnEnable:
添加以下OnEnable实现。


[C#] 纯文本查看 复制代码
?
 
1
2
voidOnEnable(){
CurrentLevel= levels[0];
}



根据位置设置CurrentLevel ,确保它只显示正确的精灵。

注:在OnEnable 中取代OnStart中初始化属性很重要,因为当预制件被实例化时才呼叫命令方法。创建预制件时(如果预制件被存为可用状态了)OnEnable 会被立刻呼叫,不过OnStart 只有当对象作为场景的一部分开始运行时才被呼叫。
在放置怪兽之前需要检查这个数据,所以要在OnEnable中初始化。

保存文件并切换带unity。运行项目并放置怪兽;现在他们显示正确的而且是最低级的精灵。

 


未完待续.................................如何在unity中制作塔防游戏(1-2)