开启辅助访问
 找回密码
 注册帐号

扫一扫,访问微社区

蛮牛译馆

关注:592

当前位置:游戏蛮牛 技术专区 蛮牛译馆

查看: 1825|回复: 15

[外文翻译] Unity 宝塔对战教程

[复制链接]  [移动端链接]
3偶尔光临
192/300
排名
21083
昨日变化
45

17

主题

24

帖子

192

积分

Rank: 3Rank: 3Rank: 3

UID
129264
好友
3
蛮牛币
324
威望
0
注册时间
2015-11-18
在线时间
75 小时
最后登录
2017-11-21

蛮牛译员

发表于 2017-1-8 23:57:19 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?注册帐号

x
本帖最后由 Brittany89 于 2017-1-8 23:57 编辑


这个教程详细介绍了如何在unity中制作一个漂亮的小的宝塔对战游戏。我们会一步步介绍使得每个人都可以理解。

序言
教程中我们会用完全独一无二的图像风格来创建一个小的三维宝塔对战游戏。这个游戏很容易做,不需要任何三维建模技巧,没有动画,且没有任何复杂的。很简单,我们所需要的是90行代码。

必要条件
知识
我们的教程不需要任何特殊的技巧。如果你之前了解unity并听过Gameobjects(游戏主体),Prefabs(预设)以及转变,然后你就可以准备开始了。如果你没有,不用太担心。

去阅读我们简单的Unity教程比如Unity2D乒乓球游戏来学会使用这个引擎。
不用担心,没有恐怖的数学!
Unity 版本
我们的宝塔对战游戏是用Unity 5.3.1f1制作完成。新的版本应该可以,老的版本有的可以,有的不行。
我们不需要任何高级的特效,因此Unity的免费版本就可以了
游戏机制
对于那些从来没听过宝塔对战的人,这儿有些基本常识:
怪兽每几秒孵化的地方是个点
怪兽跑遍整个世界向着它们想摧毁的城堡
玩家可以建立城堡来攻击怪兽
另外,我们用Buildplaces.Buildplaces是在地图上预先设置好的地方,那里玩家可以建立宝塔。我们会用到它们。因为它会使得我们更容易活下来(作为对比,在地图上到处可以建立宝塔)
艺术风格
我们有两个操作:我们可以找现实主义的东西,会耗费几百个高质量的3D模型,纹理和着色器,或者我们可以找些简单但独一无二的东西。

我们的格言是跟我谈谈,比如我很厉害!因此我们不用深入到CAD工具的世界里来创建现实主义的3D模型。相反,我们会用到一个完全抽象的风格,会省去我们的许多工作,但看起来很有趣。我们会使用Unity的原件(立方体,球形,圆柱体,...)与仅有的一些颜色结合(大部分是绿色,黄色和灰色)。
这种艺术风格的好处是每个人都可以在少于一个小时的时间内创建它没有任何3D建模或动画知识。
项目建立
我们命名为towerdefense,选择任意位置比如C:\,选择3D并点击创建项目:
如果我在Hierarchy中选择Main Camera,然后我们可以设置背景色为黑色,调整位置和旋转如下图所示:
注意,这会使照相机以45度角向下俯视整个游戏场景。
灯光

我们为游戏添加些灯光,以至于场景不至于太黑暗。我们通过选择GameObject->light->Directional Light来添加光源在顶部菜单中。我们可以用下面的设置来确保灯光在我们的场景中处于一个更好的角度:
注意:我们基本可以用任何我们想要的设置,但上面那个看着比较好。
地面

我们需要某种地面使得怪兽能够行走。我们通过从顶部菜单来选择GameObject->3D Object->Plane来添加平面。我们命名为Ground并在Inspector中设置为如图所示的位置(Position)和大小(Scale).
注意,这个大小是最合适的大小,适合于所有的Buildplaces和城堡.

我们打开我们选择的绘画工具并创建一个小的有基本绿色色调的40*40px的纹理。通过用基本色来填充来创建你自己的纹理,然后用稍微明亮或暗沉的绿色调来绘制一些随意的线条。这是我们得到的
注意:右击这个图片,选择Save As...,导航到项目的Assets文件夹并保存它到新的纹理文件夹。


现在我们可以从项目区域的纹理文件夹内拖动纹理到地面(Ground):
如果我们现在靠近看地面,我们可以看到纹理看起来是多么光滑
对大多数游戏来说是好的,但对我们的宝塔对战教程,我们想纹理看起来像素化来获得一个更独一无二的风格。我们在Project Area中选择纹理并在Inspector中改变Import Settings如下图所示:
现在看起来完全像素化了:
注意:我们在游戏中会对所有的纹理使用这个风格。
地点
立方体地点
好了,我们需要一些地方用来给玩家建立宝塔(与其在整个场景中到处建造它,那样会更复杂)。我们会通过创建一个地点来开始然后复制它几个以至于我们能用地点来设计一些怪兽行走的迷宫。

我们选择GameObject->3D Object->立方体从顶部菜单。我们放置它于(-14,0.5,-14)并命名为Buildplace:
注意:x,z坐标应该是四舍五入为整数比如14(而不是13.99)。Y的位置是0.5,以至于立方体能准确待在地面上,而不是嵌入到地面中。

看起来场景是这样的:
Buildplace的纹理
我们画一个简单的8*8像素的纹理,我们可以穿上它:
tex_buildplace.png
注意:右击链接,选择Save as...保存它到项目的assets/textures文件夹

我们用下面的导入设置:
毕竟我们可以从项目区域拖动它到Buildplace以至于纹理看起来更漂亮:
Buildplace 脚本

我们想在用户点击Buildplace的时候就建立宝塔。这种行为总是用脚本来继承。我们通过在Inspector中选择Add Component->New Script来创建新的脚本。我们命名为Buildplace并选择CSharp作为语言:
现在我们的Buildplace有一个脚本:
我们在项目区域创建一个新的脚本文件夹并移动脚本到文件夹中,以至于看起来干净整洁:
然后我们双击项目区域里的脚本并打开:
[C#] 纯文本查看 复制代码
using UnityEngine;
using System.Collections;
 
public class Buildplace : MonoBehaviour {
 
    // Use this for initialization
    void Start () {
    
    }
    
    // Update is called once per frame
    void Update () {
    
    }
}

首先,我们不需要Start或Update方法,因此我们移除它们:
[C#] 纯文本查看 复制代码
using UnityEngine;
using System.Collections;
 
public class Buildplace : MonoBehaviour {
    
}

我们将需要一些公共的变量来具体化将要建立的宝塔:
[C#] 纯文本查看 复制代码
using UnityEngine;
using System.Collections;
 
public class Buildplace : MonoBehaviour {
    // The Tower that should be built
    public GameObject towerPrefab;
    
}

注意:因为towerPrefab变量是公共的,我们一会儿可以在Inspector中具体化它。
下一步是点击Buildplace后,用Instantiate函数来建立宝塔。通常,Unity使得我们的生活更同意因为已经提供了OnMouseUpAsButton函数,我们可以用:
[C#] 纯文本查看 复制代码
using UnityEngine;
using System.Collections;
 
public class Buildplace : MonoBehaviour {
    // The Tower that should be built
    public GameObject towerPrefab;
    
    void OnMouseUpAsButton() {
        // TODO build stuff...
    }
}

现在我们能做的就是在Buildplace上面建立Tower:
[C#] 纯文本查看 复制代码
void OnMouseUpAsButton() {
    // Build Tower above Buildplace
    GameObject g = (GameObject)Instantiate(towerPrefab);
    g.transform.position = transform.position + Vector3.up;
}

注意:首先我们通过使用Instantiate来导入towerPrefab到游戏中。然后我们修改位置成为现在Buildplace's的位置往上移一个单位。

如果我们保存脚本并观察Inspector,我们也可以看到TowerPrefab 槽,那儿我们可以拖动宝塔到里面:
创建更多的Buildplaces

既然一个Buildplace已经完成,我们右击Hierarchy并选择Duplicate:
然后我们放置它到(-13,0.4,-14)以至于准确与之前那个相邻:
我们重复这个过程几次为了给怪兽创建行走的迷宫。我们在城堡顶部留一个空白的区域:
城堡
城堡立方体

对了,我们创建一个城堡以致于怪兽有可以攻击的地方。我们通过从顶部菜单选择GameObject->3D Object->Cube开始。我们命名为城堡(Castle),放置它到我们迷宫的空的区域并通过缩放,使它变大点:
城堡纹理

我们再创建一个简单的16*16像素的纹理:
注意:右击图片,选择Save As..并保存它到项目的Assets/Textures文件夹

这儿有我们城堡纹理的导入设置:
我们从项目区域中拖动纹理到城堡并收到一个很简单但独一无二的视角:
健康值条柱
好了,我们在城堡上添加健康值条柱。有许多种不同的方法来做,我们选个简单的做。我们为城堡添加一个3D纹理,它包括文字比如‘-’是1个健康值,‘--’是2个健康值,‘---’是3个健康值等等。

我们通过右击Hierarchy并选择创建空的并添加3D纹理到城堡:
然后我们重命名新的游戏主体到健康柱并在Inspector选择Add Component->Mesh->TextMesh;
我们放置它在城堡上方一个单位,然后修改TextMesh 组件来获得更好的结果:
注意:Text属性已经包含了7x'-',相当于7个健康值。其他属性大部分被改变了,来改变字体大小和尖锐性。放置Arial到字体属性很重要。我们通过点击字体属性右边的小圈来做这个。然后Unity展现目前可用的字体列表,我们从列表中可以选择一个。

场景看起来是这样的:
很简单。现在我们需要一个健康简本准确得做三个事情:
通过数‘-’来返回现在的健康值
通过移除‘-’来减少现在的健康
一直使得TextMesh面对照相机

我们想TextMesh来面对照相机为了避免奇怪的角度比如这个:
对了,我们选择Add Component->New Script,命名为Health并选择CSharp。我们移动它到项目区域的脚本文件夹并打开它:
[C#] 纯文本查看 复制代码
using UnityEngine;
using System.Collections;
 
public class Health : MonoBehaviour {
 
    // Use this for initialization
    void Start () {
    
    }

[C#] 纯文本查看 复制代码
   // Update is called once per frame
    void Update () {
    
    }
}

首先我们需要获得TextMesh组件:
[C#] 纯文本查看 复制代码
using UnityEngine;
using System.Collections;
 
public class Health : MonoBehaviour {
    // The TextMesh Component
    TextMesh tm;
 
    // Use this for initialization
    void Start () {
        tm = GetComponent<TextMesh>();
    }
    
    // Update is called once per frame
    void Update () {[/align][align=left]}
    

现在我们用Update功能,使它一直面对计算机:
[C#] 纯文本查看 复制代码
using UnityEngine;
using System.Collections;
 
public class Health : MonoBehaviour {
    // The TextMesh Component
    TextMesh tm;
 
    // Use this for initialization
    void Start () {
        tm = GetComponent<TextMesh>();
    }
    
    // Update is called once per frame
    void Update () {
        // Face the Camera
        transform.forward = Camera.main.transform.forward;
    }
}

注意:没有复杂的数学。我们能做的是使得我们的游戏主体进入准确的照相机对着的方位。

现在我们添加current()和decrease()函数:
[C#] 纯文本查看 复制代码
// Return the current Health by counting the '-'
public int current() {
    return tm.text.Length;
}
 
// Decrease the current Health by removing one '-'
public void decrease() {
    if (current() > 1)
        tm.text = tm.text.Remove(tm.text.Length - 1);
    else
        Destroy(transform.parent.gameObject);
}

注意,这是唯一一件看着有点奇怪的事情。通常我们有些整型变量来表展现我们现在的健康值。相反,我们利用包含这些‘-’的字符串的TextMesh的文字。我们自动摧毁健康柱的父对象(这个是城堡)直到健康值变为0。我们使得这些函数公共以致于其他脚本能用它们。
是的,我们游戏最简单的健康柱。好事是我们也能够为怪兽用。
怪兽
我们为我们的游戏添加怪兽。通常我们需要用CAD工具比如blender,maya或3dsmax来创建怪兽。但因为我们想把事情简单化,我们会用Unity原件来创建看起来像怪兽的圆柱体。

我们从顶部菜单选择GameObject->3D Object->Cube开始。我们命名为Monster并检查碰撞器的Is Trigger 操作以至于 怪兽之后不会互相碰撞:
我们绘制很小的8*8的纹理来给它赋予颜色:
tex_monster.png
注意:右击链接,选择Save As..保存到项目的Assets/Textures文件夹

我们用下面的Import Settings来设置:
从项目区域(Project Area)中拖拽到怪兽上,看起来是这个样子的:
详情页

我们在Hierarchy中右击怪兽并选择3D Object->Cube。我们命名新的立方体为Eye,放置它到立方体的左中心并使它变小以至于看起来像个眼睛。我们再检查下IsTrigger:
这是场景中看起来的样子:
我们为眼睛画一个简单的白色的纹理:
-tex_eye.png
注意:右击链接并选择Save As..并保存到项目的Assets/Textures文件夹。

我们用下面的导入设置(Import Settings):
然后拖拽它到我们的EyeGameObject上。

我们重复这个步骤制作另一个眼睛,像这样:
像你所想的那样为怪兽添加更多细节。我们简单地添加两只脚:
怪兽物理
我们的怪兽已经有了一个碰撞器,使得它已经成为了物理世界。还有一件事需要添加。假设通过物理世界的每个东西需要有一个刚体赋予它。刚体拥有引力,速度和其他力使得物体移动。

我们首先选择怪兽游戏主体(不是眼睛也不是脚)来添加刚体,然后点击AddComponent->Physics->Rigidbody 在Inspector中。我们使用下面的设置:
注意:我们使用默认设置。
路径寻找
我们想要怪兽能够通过迷宫并进入城堡。我们不得不做两件事来实现它:
烘焙一个导航网格(来告诉Unity哪个区域是可走的)
添加导航网格代理给怪兽
我们告诉Unity那些部分是可走的来开始。好消息是Unity实际上自己绘制出来了。我们不得不做的事情是告诉Unity我们哪部分世界是静态的(例如::绝不移动)

我们选择地面(Ground)和所有的BuildPlaces在Hierarchy中然后使得检查器中的Static(静态) 属性可用:
现在unity知道这些东西绝不能移动,因此会用它们来计算可移动的区域。

现在我们从顶部菜单选择Window->Navigation并使用下面的属性:
然后我们点击底部的Bake按钮。几秒之后,我们能看到Unity怎么计算场景中的可移动区域:
注意:最重要的部分是通过迷宫的路径。Unity也认为Buildplaces是可移动的,但因为没有为怪兽提供阶梯来爬,所以没关系的。

对了,我们现在再次选择怪兽并点击AddComponent->Navigation->Nav Mesh Agent.这个组件被所有的东西所需要,通过我们刚刚我们烘焙过的的导航网格。我们为我们的代理使用下面的设置:
注意:我们仅仅修改了移动的速度和大小使其适合我们的怪兽。如果你对设置还不满意还可以修改。
既然我们的导航网格被烘焙并且怪兽有个导航网格代理,我们能做的就是使它移动到一个地方比如:
[C#] 纯文本查看 复制代码
GetComponent<NavMeshAgent>.destination = new Vector3(1, 2, 3);

注意:当我们之后创建怪兽脚本的时候我们来做这个。
健康柱

我们添加一个健康柱到怪兽,以至于宝塔可以攻击它。我们用准确相同的工作流,我们为我们城堡的健康柱用的,一些不同的设置使得它更小并变红:
注意:我们改变Text属性为4x"-"以至于怪兽仅能攻击4个宝塔。

这个是怪兽的健康柱在场景中看起来的样子:
怪兽脚本
好了正如前面我们提到的,我们想要创建怪兽脚本,使它移动到城堡然后当它到达城堡后就受到一点的伤害。

我们在Hierarchy中选择怪兽,然后点击Add Component->New Script,命名为怪兽(Monster)并选择C#作为编程语言。我们移动它到脚本文件夹并打开:
[C#] 纯文本查看 复制代码
using UnityEngine;
using System.Collections;
 
public class Monster : MonoBehaviour {
 
    // Use this for initialization
    void Start () {
    
    }[/align][align=left]

[C#] 纯文本查看 复制代码
    // Update is called once per frame
    void Update () {
    
    }
}

我们移除Update方法因为我们不需要它:
[C#] 纯文本查看 复制代码
using UnityEngine;
using System.Collections;
 
public class Monster : MonoBehaviour {
 
    // Use this for initialization
    void Start () {
    
    }
}

我们用Start函数来找到场景中的城堡游戏主体,然后使用怪兽的导航网格代理来移动它:
[C#] 纯文本查看 复制代码
// Use this for initialization
void Start () {
    // Navigate to Castle
    GameObject castle = GameObject.Find("Castle");
    if (castle)
        GetComponent<NavMeshAgent>().destination = castle.transform.position;
}

像这样简单。

现在我们想要怪兽走近城堡的时候就减少城堡的健康值。我们怪兽的碰撞器有IsTrigger可用,意味着Unity自动通知我们OnTriggerEnter函数中有多种碰撞器。我们所能做的是找出我们碰撞的是不是城堡,然后减少它的健康柱:
[C#] 纯文本查看 复制代码
void OnTriggerEnter(Collider co) {
    // If castle then deal Damage
    if (co.name == "Castle") {
        co.GetComponentInChildren<Health>().decrease();
    }
}

当它处理完城堡的伤害值后就不再需要怪兽了,然后我们来摧毁怪兽:
[C#] 纯文本查看 复制代码
void OnTriggerEnter(Collider co) {
    // If castle then deal Damage, destroy self
    if (co.name == "Castle") {
        co.GetComponentInChildren<Health>().decrease();
        Destroy(gameObject);
    }
}

这是我们的怪兽脚本,Unity使得我们的生活更简单。
注意,别忘了保存脚本。
怪兽预设
现在从开始我们在游戏中不需要怪兽了。相反我们想要保存它为预设以至于我们可以导入它到游戏中,在我们想的任何时候。

我们所能做的是创建一个预设,从Hierarchy中拖动我们的怪兽到新的项目区域的预设文件夹中:
现在我们任何时间就可以导入它到场景中,我们可以从项目区域中拖它到场景或者在脚本中使用实例化(Instatiate)函数(我们马上就做)。
因为我们现在有预设,我们在Hierarchy中右击怪兽并选择删除(Delete)。
产生器

好了,我们创建一个产生器每几秒就导入新的怪兽到游戏中。我们从顶部菜单选择GameObject->CreateEmpty开始。我们重新命名为产生器(Spawn)并放置它到迷宫入口处:
我们看下Inspector并选择一个Gizmo:
注意:A Gizmo是一个可视化指示器。能被空的游戏主体使用以至于他们看起来容易点。Gizmo只在场景视图中出现,不在最后的游戏中。

现在产生器能被轻易看到:
我们选择Add Component->New Scrupt,命名为Spawn并选择C#编程语言。我们移动它到我们的项目区域脚本文件夹中并打开:
[C#] 纯文本查看 复制代码
using UnityEngine;
using System.Collections;
 
public class Spawn : MonoBehaviour {
 
    // Use this for initialization
    void Start () {
    
    }
    
    // Update is called once per frame
    void Update () {
    
    }
}

我们不需要Update方法,所以我们移除它:
[C#] 纯文本查看 复制代码
using UnityEngine;
using System.Collections;
 
public class Spawn : MonoBehaviour {
 
    // Use this for initialization
    void Start () {
    
    }
}

现在我们可以添加一个公共的MonsterPrefab变量以至于我们能具体化可以产生的怪兽:
[C#] 纯文本查看 复制代码
using UnityEngine;
using System.Collections;
 
public class Spawn : MonoBehaviour {
    // The Monster that should be spawned
    public GameObject monsterPrefab;
 
    // Use this for initialization
    void Start () {
    
    }
}

我们为interval添加另一个变量,用来表示产生怪兽之间的延迟:
[C#] 纯文本查看 复制代码
using UnityEngine;
using System.Collections;
 
public class Spawn : MonoBehaviour {
    // The Monster that should be spawned
    public GameObject monsterPrefab;
    
    // Spawn Delay in seconds
    public float interval = 3;
 
    // Use this for initialization
    void Start () {
    
    }
}

现在我们能做的是创建一个函数,用来产生一个新的怪兽,然后用InvokeRepeating每几秒来调用函数:
[C#] 纯文本查看 复制代码
using UnityEngine;
using System.Collections;
 
public class Spawn : MonoBehaviour {
    // The Monster that should be spawned
    public GameObject monsterPrefab;
    
    // Spawn Delay in seconds
    public float interval = 3;
    
    // Use this for initialization
    void Start() {
        InvokeRepeating("SpawnNext", interval, interval);
    }
    
    void SpawnNext() {
        Instantiate(monsterPrefab, transform.position, Quaternion.identity);
    }
}

很容易。我们保存脚本并观察Inspector,我们从项目区域中拖动我们的怪兽预设到脚本的怪兽预设槽:
如果我们点击Play,然后我们现在看到一个新的怪兽是怎么每隔3秒产生的。怪兽向着城堡前进:
子弹

我们创建一个简单的子弹预设,以至于之后我们创建一个宝塔。我们通过顶部菜单选择GameObject->3Dobject->Cube来开始。我们命名为子弹,缩放它小点并使得IsTrigger可用:
注意:我们使得IsTrigger可用以至于子弹能够穿透墙并击中怪兽。
我们画一个简单的8*8像素的纹理,我们用来赋予子弹:
tex_bullet.png
注意:右击链接,选择Save As并保存到项目的Assets/Textures文件夹

我们用下面的导入设置:
然后我们从项目区域中拖动纹理到我们的子弹:
好了,子弹假设飞过整个游戏场景直到它击中怪兽。正如我们所知,物理世界中的事想移动需要一个刚体。我们选择Add Component->Physics->Rigidbody在Inspector并设置下面的属性:
现在我们用刚体来飞向怪兽。我们选择Add Component->NewScript在Inspector中,命名为Bullet并选择C#。我们移动脚本到脚本文件夹并打开:
[C#] 纯文本查看 复制代码
using UnityEngine;
using System.Collections;
 
public class Bullet : MonoBehaviour {
 
    // Use this for initialization
    void Start () {
    
    }
    
    // Update is called once per frame
    void Update () {
    
    }
}

我们不需要Start或者Update函数。相反,我们用FixedUpdate,有点像Update,在相同的间隔期内被调用,那里是做了物理计算的。因为子弹是物理世界的一部分,我们使用FixedUpdate:
[C#] 纯文本查看 复制代码
using UnityEngine;
using System.Collections;
 
public class Bullet : MonoBehaviour {
    
    void FixedUpdate() {
    
    }
}

子弹需要一个目标来击中,以及一个速度变量:
[C#] 纯文本查看 复制代码
using UnityEngine;
using System.Collections;
 
public class Bullet : MonoBehaviour {
    // Speed
    public float speed = 10;
    
    // Target (set by Tower)
    public Transform target;    
    
    void FixedUpdate() {
    
    }
}

注意:目标是子弹想击中的怪兽。宝塔发射子弹时,目标会被设置好。

我们来修改下我们的FixedUpdate函数使得子弹能够飞向目标。我们简单使用刚体的速度属性。速度被定义为移动方向乘以速度,我们这么做:
[C#] 纯文本查看 复制代码
void FixedUpdate() {    
    // Fly towards the target           
    Vector3 dir = target.position - transform.position;
    GetComponent<Rigidbody>().velocity = dir.normalized * speed;
}

注意:我们通过从怪兽的位置抽取现在的位置来计算方位,这是基本的向量数学。然后我们诚意速度的方向。我们用向量化的方向来确保有一个长度。

就这么简单。现在可能会发生怪兽跑进城堡然后死亡,当子弹尝试到达它的时候,我们来准备:
[C#] 纯文本查看 复制代码
void FixedUpdate() {    
    // Still has a Target?
    if (target) {
        // Fly towards the target        
        Vector3 dir = target.position - transform.position;
        GetComponent<Rigidbody>().velocity = dir.normalized * speed;
    } else {
        // Otherwise destroy self
        Destroy(gameObject);
    }
}

好极了,还有一件事需要做。我们想让子弹碰到怪物的时候对怪兽形成伤害。子弹对怪兽形成伤害后会自行消失。我们仅仅用unity的OnTriggerEnter函数就知道子弹什么时候会遇到怪兽:
[C#] 纯文本查看 复制代码
void OnTriggerEnter(Collider co) {
    Health health = co.GetComponentInChildren<Health>();
    if (health) {
        health.decrease();
        Destroy(gameObject);
    }
}

这是我们的子弹。但是我们从开始确实不需要在场景中让它第一时间出现,我们从Hierarchy拖它到预设文件夹在我们的项目区域中:
然后我们从Hierarchy删除它,因为我们还不需要它。
宝塔
我们已经创建了很多Buildplaces,我们可以往上放宝塔,是时候来创建一个宝塔。

我们将从顶部菜单通过选择GameObject->3DObject->Cube来开始。我们重命名为宝塔(Tower),缩放它小点儿并旋转它,为了更好看:
我们为我们的宝塔用16*16像素的纹理:
注意:右击图像,选择另存为,并保存它到项目的Assets/Textires文件夹。

现在是导入设置:
我们从项目区域拖动纹理到宝塔上,现在是它看起来的样子:
我们的宝塔模型已经完成了。现在我们不得不添加逻辑来发现靠近宝塔的怪兽,然后向它发射子弹。有许多不同的方式来完成。最明显的方式是写个脚本来发现所有的怪兽然后向最近的那个怪兽进行射击。这个运行得很好,但运算可能会很消耗很多性能。
在宝塔周围添加一个大的球形触发器很聪明并用Unity的OnTriggerEnter函数。不论什么时候怪兽进入宝塔的‘意识’区域,Unity都会自动通知我们。

我们首先移除宝塔的盒子碰撞器:
然后我们选择AddComponent->Physics->Sphere Collider并赋予下面的属性:
如果我们看场景,我们看到了球。这是宝塔看到的区域并攻击怪兽:
我们需要脚本来实行宝塔攻击。我们选择Add Component->NewScript,命名为宝塔并选择C#作为编程语言。我们移动脚本到脚本文件夹并打开它:
[C#] 纯文本查看 复制代码
using UnityEngine;
using System.Collections;
 
public class Tower : MonoBehaviour {
 
    // Use this for initialization
    void Start () {
    
    }
    
    // Update is called once per frame
    void Update () {
    
    }
}

我们不需要Start函数,我们移除它:
[C#] 纯文本查看 复制代码
using UnityEngine;
using System.Collections;
 
public class Tower : MonoBehaviour {
    
    // Update is called once per frame
    void Update () {
    
    }
}

我们添加一个公共的BulletPrefab变量具体定义哪个子弹预设可以用:
[C#] 纯文本查看 复制代码
using UnityEngine;
using System.Collections;
 
public class Tower : MonoBehaviour {
    // The Bullet
    public GameObject bulletPrefab;
    
    // Update is called once per frame[mw_shl_code=csharp,true]void OnTriggerEnter(Collider co) {
    // Was it a Monster? Then Shoot it
    if (co.GetComponent<Monster>()) {
        GameObject g = (GameObject)Instantiate(bulletPrefab, transform.position, Quaternion.identity);
        g.GetComponent<Bullet>().target = co.transform;
    }
}

    void Update () {
   
    }
}
[/mw_shl_code]
现在我们用OnTriggerEnter函数并发现是否进入到触发器的是怪兽,在这个例子中我们对它发射子弹:
[C#] 纯文本查看 复制代码
void OnTriggerEnter(Collider co) {
    // Was it a Monster? Then Shoot it
    if (co.GetComponent<Monster>()) {
        GameObject g = (GameObject)Instantiate(bulletPrefab, transform.position, Quaternion.identity);
        g.GetComponent<Bullet>().target = co.transform;
    }
}

注意:我们用GetComponent来发现进入触发器的是否是怪兽。如果这个例子中我们用实例来导入子弹到游戏世界中,在宝塔的现在的位置及默认的选择(Quaternion,identity).毕竟我们通过了子弹组件并设置目标为怪兽。

我们用我们的Update功能来添加一个简单的选择给我们的宝塔,这样看起来更好点:
[C#] 纯文本查看 复制代码
using UnityEngine;
using System.Collections;
 
public class Tower : MonoBehaviour {
    // The Bullet
    public GameObject bulletPrefab;
    
    // Rotation Speed
    public float rotationSpeed = 35;
    
    void Update() {
        transform.Rotate(Vector3.up * Time.deltaTime * rotationSpeed, Space.World);
    }
    
    void OnTriggerEnter(Collider co) {
        // Was it a Monster? Then Shoot it
        if (co.GetComponent<Monster>()) {
            GameObject g = (GameObject)Instantiate(bulletPrefab, transform.position, Quaternion.identity);
            g.GetComponent<Bullet>().target = co.transform;
        }
    }
}

我们的宝塔旋转在游戏中看起来是这样的:
别忘记从项目区域的拖子弹预设到宝塔的子弹预设槽:
有个小修改我们一会儿做。宝塔有一个漂亮的大的球形碰撞器环绕着它。这个碰撞器重叠一个Buildplace's 碰撞器,阻止OnMouseUpAsButton函数被调用。我们所有能做的使它准确运行来告诉Unity忽略宝塔的碰撞器当鼠标点击的时候。我们通过选择Ignore Raycast 层来做这个:
现在我们通过从Hierarchy拖动宝塔到我们的预设文件夹来创建预设:
然后我们从Hierarchy删除它:

我们在Hierarhcy中选择所有的Buildplaces,看下检查器并拖动宝塔预设到宝塔预设槽:
如果我们按下Play然后我们现在通过点击Buildplaces来创建宝塔。宝塔甚至会攻击怪兽:
意味着我们的unity宝塔对抗游戏完成了:
总结
这是我们的很长的Unity宝塔对抗教程。通常,现在是读者的游戏时间,有多种事情可以被添加:
分数
金牌
不同怪兽
不同宝塔
不同子弹
不同水平
背景音乐
带动画的更好的3D模型
菜单
存档
以及更多
下载源码及项目文件
Unity宝塔对抗教程的源码及项目的文件能够被下载。

原文链接:https://noobtuts.com/unity/tower-defense-game



回复

使用道具 举报

5熟悉之中
515/1000
排名
4911
昨日变化
2

0

主题

104

帖子

515

积分

Rank: 5Rank: 5

UID
36520
好友
0
蛮牛币
101
威望
0
注册时间
2014-7-27
在线时间
186 小时
最后登录
2017-11-10
发表于 2017-1-9 10:40:29 | 显示全部楼层
这不就是siki老师刚出的视频的原型吗~

回复 支持 反对

使用道具 举报

7日久生情
2035/5000
排名
973
昨日变化
1

3

主题

414

帖子

2035

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
46577
好友
1
蛮牛币
2450
威望
0
注册时间
2014-9-24
在线时间
716 小时
最后登录
2017-11-22
发表于 2017-1-9 14:38:04 | 显示全部楼层
你确定你这些加起来就90行?!

回复 支持 反对

使用道具 举报

5熟悉之中
607/1000
排名
3638
昨日变化
4

2

主题

126

帖子

607

积分

Rank: 5Rank: 5

UID
189765
好友
0
蛮牛币
1993
威望
0
注册时间
2016-12-5
在线时间
161 小时
最后登录
2017-11-16
发表于 2017-1-9 15:18:39 | 显示全部楼层
没事可以看一看

回复

使用道具 举报

0

主题

24

帖子

43

积分

Rank: 1

UID
51218
好友
0
蛮牛币
24
威望
0
注册时间
2014-10-26
在线时间
19 小时
最后登录
2017-2-28
发表于 2017-1-9 16:14:43 | 显示全部楼层
基础教学 不错不错!

回复 支持 反对

使用道具 举报

排名
25989
昨日变化
47

1

主题

15

帖子

36

积分

Rank: 1

UID
199641
好友
0
蛮牛币
15
威望
0
注册时间
2017-1-7
在线时间
10 小时
最后登录
2017-1-19
发表于 2017-1-9 18:32:34 | 显示全部楼层
受教了 感謝教學

回复

使用道具 举报

排名
39649
昨日变化
13

0

主题

5

帖子

10

积分

Rank: 1

UID
828
好友
0
蛮牛币
19
威望
0
注册时间
2013-7-12
在线时间
1 小时
最后登录
2017-1-10
发表于 2017-1-10 11:23:12 | 显示全部楼层
有时间看看

回复

使用道具 举报

6蛮牛粉丝
1300/1500
排名
2499
昨日变化
3

1

主题

463

帖子

1300

积分

Rank: 6Rank: 6Rank: 6

UID
171030
好友
4
蛮牛币
1587
威望
0
注册时间
2016-9-22
在线时间
346 小时
最后登录
2017-9-9

活力之星

发表于 2017-1-10 21:10:39 | 显示全部楼层
挺有意思的哈

回复

使用道具 举报

3偶尔光临
201/300
排名
11039
昨日变化
8

3

主题

88

帖子

201

积分

Rank: 3Rank: 3Rank: 3

UID
117120
好友
1
蛮牛币
3976
威望
0
注册时间
2015-8-8
在线时间
68 小时
最后登录
2017-6-1
发表于 2017-1-10 21:44:43 | 显示全部楼层
好教程要学习!!!!

回复

使用道具 举报

排名
53168
昨日变化
21

0

主题

13

帖子

31

积分

Rank: 1

UID
194879
好友
0
蛮牛币
11
威望
0
注册时间
2016-12-21
在线时间
16 小时
最后登录
2017-1-24
发表于 2017-1-10 23:37:50 | 显示全部楼层
灰常好好

回复

使用道具 举报

3偶尔光临
236/300
排名
12220
昨日变化
9

0

主题

161

帖子

236

积分

Rank: 3Rank: 3Rank: 3

UID
95669
好友
0
蛮牛币
480
威望
0
注册时间
2015-4-27
在线时间
21 小时
最后登录
2017-5-16
发表于 2017-1-11 09:41:49 | 显示全部楼层
感謝分享這麼好的資源!

回复 支持 反对

使用道具 举报

5熟悉之中
796/1000
排名
2197
昨日变化
12

0

主题

82

帖子

796

积分

Rank: 5Rank: 5

UID
188322
好友
0
蛮牛币
2376
威望
0
注册时间
2016-11-30
在线时间
198 小时
最后登录
2017-11-22
发表于 2017-1-13 10:25:39 | 显示全部楼层
xiexie louz .........

回复

使用道具 举报

4四处流浪
372/500
排名
4847
昨日变化
5

0

主题

58

帖子

372

积分

Rank: 4

UID
188477
好友
0
蛮牛币
687
威望
0
注册时间
2016-12-1
在线时间
84 小时
最后登录
2017-11-21
发表于 2017-1-16 10:12:49 | 显示全部楼层
66666666666666666666666

回复 支持 反对

使用道具 举报

6蛮牛粉丝
1217/1500
排名
1542
昨日变化
3

4

主题

198

帖子

1217

积分

Rank: 6Rank: 6Rank: 6

UID
81888
好友
2
蛮牛币
6758
威望
0
注册时间
2015-3-19
在线时间
353 小时
最后登录
2017-11-21
发表于 2017-1-16 16:51:30 | 显示全部楼层
66666666666666666666666
[发帖际遇]: a601014006 在网吧通宵,花了 3 蛮牛币. 幸运榜 / 衰神榜

回复 支持 反对

使用道具 举报

5熟悉之中
966/1000
排名
3765
昨日变化
25

0

主题

480

帖子

966

积分

Rank: 5Rank: 5

UID
156480
好友
0
蛮牛币
1584
威望
0
注册时间
2016-7-12
在线时间
178 小时
最后登录
2017-11-22
发表于 2017-1-17 16:30:02 | 显示全部楼层
666666666666

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册帐号

本版积分规则

关闭

站长推荐 上一条 /1 下一条

快速回复 返回顶部 返回列表