如何在unity中制作unity塔防游戏戏

如何在Unity中制作塔防游戏 | 敌人们需要长脑子 - 滚动_【北京联盟】
如何在Unity中制作塔防游戏 | 敌人们需要长脑子
/ 作者:小易
北京联盟摘要:
如何在Unity中制作塔防游戏 | 敌人们需要长脑子,上一篇:
下一篇: 。★ 如果你喜欢我们的教程,欢迎加入泰然网Unity交流群 ★ 欢迎来到如何在unity中制作塔防游戏的第二部分。现在正在unity中创建一个塔防游戏,而且在第一部分可以放置并升级怪兽了。还有一个敌人来袭击曲奇。 然而,敌人不知道该面向哪个方向!还有
★如果你喜欢我们的教程,欢迎加入泰然网Unity交流群★欢迎来到如何在unity中制作塔防游戏的第二部分。现在正在unity中创建一个塔防游戏,而且在第一部分可以放置并升级怪兽了。还有一个敌人来袭击曲奇。然而,敌人不知道该面向哪个方向!还有,这是进行攻击的一个可怜的理由。在这部分,将添加一波波敌人并武装怪兽以便他们可以保护珍贵的曲奇。在unity中,打开前面教程完成的项目。旋转敌人在上一篇教程的最后,敌人追踪了路径,但是不知道该面向哪边。在MonoDevelop中打开MoveEnemy.cs ,添加下边的方法来修复这个问题。privatevoid RotateIntoMoveDirection(){
Vector3 newStartPosition = waypoints [currentWaypoint].transform.
Vector3 newEndPosition = waypoints [currentWaypoint +1].transform.
Vector3 newDirection =(newEndPosition - newStartPosition);
float x = newDirection.x;
float y = newDirection.y;
float rotationAngle = Mathf.Atan2(y, x)*180/ Mathf.PI;
GameObject sprite =(GameObject)
gameObject.transform.FindChild(&Sprite&).gameO
sprite.transform.rotation=
Quaternion.AngleAxis(rotationAngle, Vector3.forward);
}RotateIntoMoveDirection 旋转了敌人以便它可以一直看向前方,像这样:通过从下一个路径点减掉当前路径点的位置来计算虫子当前的方向。用Mathf.Atan2来决定newDirection 点所朝方向的角度,在角度内,假设零点朝向右边。用结果乘以180 / Mathf.PI 将角度转换为度。最后,检索命名为Sprite 的子集并沿Z轴方向旋转rotationAngle 。注意旋转的是子对象而不是父类,这样生命条——一会儿将要添加——保持水平。在 Update()中,用下边的RotateIntoMoveDirection声明替换注释 // TODO:Rotate into move directionRotateIntoMoveDirection();保存文件并切换到unity。运行场景;现在怪兽知道他们的走向了。现在虫子看向它移动的方向只有一个敌人?太让人印象深刻了。让成群的敌人出现吧。就想每一个塔防游戏一样,成群的敌人会一波一波的来!下一期我们会制作更多波数的敌人并且告知玩家泰然网(iTyran)
如何在Unity中制作塔防游戏 | 敌人们需要长脑子
免责声明:本站文章除注明来源“北京联盟”外的文章均来自网络和网友投稿,著作权归原作者所有。北京联盟不承担任何连带责任!如何在unity中制作塔防游戏 part ii-1_百度知道
如何在unity中制作塔防游戏 part ii-1
我有更好的答案
带骨骼的模型动画是在MAYA里做好的。手动配置Avatar,肌肉设定,avatar在小兵之间retargeting。然后设置trigger控制动画播放。
采纳率:89%
来自团队:
为您推荐:
其他类似问题
您可能关注的内容
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。U3D塔防游戏案例教程
授课讲师:
软件版本:
Unity3D 4.3.4英文版
教程程度:
所需基础:
Unity3D游戏制作入门教程
交流提问:
适合人群:
游戏开发爱好者
相关素材:
课程光盘:
281 31228 22163 651 39285 16815 14682 12815 11888 10859 6222 251 9050 5851 6483 4319 3931 4297 3080 5648 4601 3931 4110 2548 4187 2850 2735 2417 2766 3071
论坛最新主题
您可能感兴趣的课程
针对全国计算机等级考试二级的一套精品视频教程
炙手可热的游戏开发工具,教大家运用Unity进行简单的游戏开发。
通过太空射击游戏等案例设计过程,使学员掌握程序设计技巧和方法。
以SQL Server2008为平台,为您系统的介绍数据库的基本理论及应用。
赞助商链接
兴趣圈成员塔防游戏非常地受欢迎,木有什么能比看着自己的防御毁灭邪恶的入侵者更爽的事了。
在这个包含两部分的教程中,你将使用Unity创建一个塔防游戏。
你将会学到如何:
创建一波一波的敌人
使敌人随着路标移动
创建和升级防御塔,并将敌人销毁
最后,你会有一个此类型游戏的框架,之后可在此基础之上进行扩展。
在本篇教程中,你将创建一个塔防游戏,敌人(小虫子)会朝着你的饼干移动,你可以在一些战略点上,使用金币放置和升级你收下的小怪兽来进行防御。
玩家必须在小虫子抵达饼干之前消灭它们,敌人会随着波数的增加而变得更加强大。 游戏将在玩家在所有波数之后存活下来(游戏胜利),或者有5个敌人抵达饼干之后结束(游戏失败)。
下面是一张完成的游戏截图:
如果你还没有Unity5,请从下载。
同时,下载这个,解压缩并且使用unity打开TowerDefense-Part1-Starter这个工程。
starter项目中包括了美术和声音资源,同时还有预设的动画以及一些帮助用的脚本,这些脚本跟塔防游戏没有直接的关系,所以不会再本教程中详细介绍。但是如果你想要更多的学习关于unity 2d动画的创建,请参考。
项目中同时包含了一些 prefab供你稍后扩展用来创建游戏角色。最后,工程中包含背景和UI设置好的场景。
在Scenes文件夹中找到并打开GameScene, 设置Game视图的显示比例为4:3来保证labels能够正确的在背景中对齐,你在Game视图中看到的应该如下所示:
注:一开始我也没弄清楚什么意思,后来理解了是在
这里所示的窗口
Starter project – check!
Assets – check!
走向征服世界的第一步(你的塔防游戏...)已经准备好了!
可放置点的 X 标记
小怪兽只能放在标记有X的地方。
从Project Brower中拖动Images\Objects\Openspot到场景中,目前来说放到哪个位置没有关系。
在Hierarchy中选中Openspot,在Inspector面板点击 Add Component并且选择 Physics 2D\Box Collider 2D。 Unity将会在场景中以绿色的线显示盒子碰撞器。你将会使用这个碰撞器来检测在某个点的鼠标点击。
使用相同的步骤,添加一个Audio\Audio Source组件到 Openspot上。并且设置Audio Source’s AudioClip 为 tower_place(可以在Audio文件夹中找到),记住不能勾选Play On Awake。
你需要再创建11个放置点,每个都得重复上面的步骤,不过不用担心,Unity有一个很好的解决办法: Prefab!
将OpenSpot从Hierarchy拖动到Project Browser里面的Prefabs文件夹,它的名字在Hierarchy将会变成蓝色,用来标示它是和一个prefab相关联的。像下面这样:
现在,你拥有了一个prefab,你就可以创建任意多的拷贝。简单的将Openspot从Prefabs文件夹中拖拽到场景中,再重复11次,一共在场景中创建12个放置点。
下面使用Inspector面板来分别设置这个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的prefab。
现在,它包含了一个空的游戏对象,由三种不同的精灵组成,和他们各自的射击动画。
每一个精灵代表了小怪兽不同的能力级别。Monster的prefab同时包含了一个Audio Source的组件,当怪兽发射激光的时候会触发播放声音。
现在你将创建一个脚本来在Openspot上放置一个小怪兽。
在Project Browser中 选择Openspot,在Inspector面板中,点击 Add Component然后选择New Script并重命名为PlaceMonster,选择C#作为脚本语言并以此点击Create和Add。因为你是向prefab添加的脚本,所以场景中所有的Openspot都将会被附件该脚本。
双击刚才创建的脚本,在编辑器中打开。然后添加下面的这两个变量
public GameObject monsterP
private GameO
你将使用monsterPrefab中的对象实例化一个拷贝来创建一个小怪兽,然后保存在monster变量中,方便之后的操作。
一个位置一个怪兽
添加下面的方法来限制一个位置只能放置一个怪兽:
private bool canPlaceMonster()
return monster ==
在canPlaceMonster方法中,我们检查monster变量是否为null,如果是的,则表示当前没有放置小怪兽,所以是允许放置一个的。
再添加下面的代码,来执行当玩家点击鼠标之后放置一个怪兽:
void OnMouseUp()
if (canPlaceMonster())
monster = (GameObject)Instantiate(monsterPrefab, transform.position, Quaternion.identity);
AudioSource audioSource = gameObject.GetComponent&AudioSource&();
audioSource.PlayOneShot(audioSource.clip);
//todo: Deduct gold
上面的代码在玩家点击或者Tap的时候放置一个怪兽,那么如何工作的呢?
当玩家点击一个游戏对象的碰撞器的时候,Unity会自动的调用OnMouseUp方法
2 . 当被调用之后,这个方法会检查是否可以放置怪兽,如果可则放置一个新的怪兽
使用 Instantiate方法创建一个怪兽对象,这个方法会根据指定的prefab和指定的位置和旋转角度创建一个对象。在本例中,我们拷贝了monsterPrefab ,并指定了当前游戏对象的位置,以及没有旋转,最后将结果转换为GameObject类型存储在monster变量中。
最后,调用PlayOneShot方法播放附加在AudioSource组件上的声音特效。
现在我们的PlaceMonster脚本已经可以放置新的怪兽了,但还需要指定prefab这个步骤。
使用正确的Prefab
在代码编辑器中保存,并返回Unity 。
下面给monsterPrefab赋值,首先在Prefabs文件夹中选中OpenSpot,在Inspector面板中,点击PlaceMonster (Script)组件的Monster Prefab属性右边的小圆圈按钮,然后在弹出来的对话框中选择Monster。
现在开始游戏,在 X 标记上点击来创建一些怪物~
升级我们的怪物
在下面的图片中,我们看到怪物在不同的等级有不同的外观
我们需要一个脚本来作为怪物升级系统实现的基础,来跟踪管理怪物在各个级别的能力大小,当然还有怪物所处的当前等级。
现在来添加这个脚本 。
在Project Browser中选中 Prefabs/Monster,添加一个新的C#脚本命名为MonsterData,在代码编辑器中打开该脚本并添加下面的代码在MonsterData 类的上面:
[System.Serializable]
public class MonsterLevel
public GameO
这里定义了一个MonsterLevel类型,包含了费用(金币)以及对于某个特定等级的视觉效果。
我们添加了[System.Serializable]这个特性来使这个类的对象可以在inspector面板中编辑。这可以使我们方便快速的改变MonsterLevel中的值,甚至在游戏运行过程中。这在调节游戏平衡性的时候特别的有用。
定义怪物的等级
我们将预先定义的MonsterLevel存储在List&T&中。
为什么不简单的使用数组MonsterLevel []呢,首先我们会经常用到某个特定MonsterLevel对象的下标,当然如果使用数组编写一点代码来做这件事也不是特别困难。我们可以直接使用List对象的IndexOf()方法,没有必要重新发明轮子了这次 :]
在MonsterData.cs文件的顶部,添加下面的引用:
using System.Collections.G
这将允许我们使用泛型的数据结构类型,所以可以在脚本代码中使用List&T&。
接下来添加下面的变量到MonsterData类中,用来存储MonsterLevel的列表:
public List&MonsterLevel&
使用泛型,可以保证levels只能存放MonsterLevel类型的对象 。
在代码编辑器中保存文件,并返回到Unity中配置每个阶段.
在Project Browser中选中Prefabs/Monster,然后在Inspector面板中我们可以在MonsterData (Script)组件看到Levels属性,设置size为3
接下来,设置每个等级的花费如下:
Element 0: 200
Element 1: 110
Element 2: 120
接下来,给visualization赋值。
在project browers中展开Prefabs/Monster来查看其子节点。拖拽子节点Monster0到visualization属性的Element 0。
重复上面的动作Monster1对Element 1,Monster2对Element 2,参考下面动图中的演示:
现在,当你选中了Prefabs/Monster,它应该看下像下面这样子:
定义当前的等级
切换回MonsterData.cs中,向MonsterData类中添加另外一个变量:
private MonsterLevel currentL
在私有变量currentLevel中,我们存放怪物当前的等级信息。
现在设置currentLevel同时将它暴露给其他脚本使用,添加下面的代码到MonsterData中:
public MonsterLevel CurrentLevel
return currentL
currentLevel =
int currentLevelIndex = levels.IndexOf(currentLevel);
GameObject levelVisualization = levels[currentLevelIndex].
for(var i = 0; i& levels.C i++)
if(levelVisualization != null)
if(i == currentLevelIndex)
levels[i].visualization.SetActive(true);
levels[i].visualization.SetActive(false);
看起来有很多C#代码,我们慢慢来看:
为私有变量currentLevel定义一个属性。当属性被定义之后,你就能像其他变量一样去调用,既可以CurrentLevel这样在类的内部调用,也可以使用monster.CurrentLevel这样在类的外部调用。然后还能自定义属性的getter和setter方法,通过只提供一个getter,只有一个setter或者都有,来控制一个属性是只读的、只写的或者读写的。
在getter方法中,直接返回私有变量currentLevel的值
在setter方法中,给currentLevel赋值。先拿到当前等级的下标,然后遍历levels数组依据currentLevelIndex的值设置外观的活动或者非活动状态,好处就在于不管什么时候谁设置了currentLevel,精灵会自动更新。
添加下面的OnEnable的一个实现:
void OnEnable()
CurrentLevel = levels[0];
这里设置了CurrentLevel的默认值,确保它只显示正确的那个精灵。
在OnEnable中而不是OnStart中初始化属性的值,是因为当prefabs被实例化时方法的调用次序问题。
OnEnable会在创建prefab时立即被调用,而OnStart会等到对象作为场景的一部反的时候才会被调用。
这里我们需要在放置一个怪兽之前就要初始化一下,所以在OnEnable中初始化。
注意OnEnable中的大小写,如果大小写不对,方法不会被调用!
保存文件返回到Unity中,运行项目并且放置一些怪兽,现在他们显示正确的,也就是最低等级的精灵,如下图:
升级小怪兽
返回到代码编辑器,增加下面的方法到MonsterData中:
public MonsterLevel getNextLevel()
int currentLevelIndex = levels.IndexOf(currentLevel);
int maxLevelIndex = levels.Count - 1;
if (currentLevelIndex & maxLevelIndex)
return levels[currentLevelIndex+1];
在getNextLevel方法中,我们首先拿到当前等级的下标以及最高等级的下标,以此判断如果当前不是最高等级时,返回下个等级,否则返回null。
我们可以使用该方法判断是否可以升级到下一个等级。
添加下面的方法增加怪兽的等级:
public void increaseLevel()
int currentLevelIndex = levels.IndexOf(currentLevel);
if (currentLevelIndex & levels.Count - 1)
CurrentLevel = levels[currentLevelIndex+1];
这里我们获取当前等级的下标,然后确保它不会大于最高等级的下标,如果不大于,则将CurrentLevel设置为下一个等级。
测试是否可以升级
保存刚才的脚本文件,返回到PlaceMonster.cs文件,增加下面的方法:
private bool canUpdateMonster()
if (monster != null)
MonsterData monsterData = monster.GetComponent&MonsterData&();
MonsterLevel nextLevel = monsterData.getNextLevel();
if (nextLevel != null)
首先,检查monster变量是否为null,如果为null则肯定不能升级了,如果不为null则获取其MonsterData组件,并检查更高的等级是否存在,如果getNextLevel方法返回的值不是null则说明更高的等级存在(返回true),否则不存在(返回false)。
使可以通过金币升级
为了能够升级,在PlaceMonster中的OnMouseUp中添加else if分支:
void OnMouseUp()
if (canPlaceMonster())
//...这里跟原来的代码一样,这里省略了
}else if (canUpdateMonster())
monster.GetComponent&MonsterData&().increaseLevel();
AudioSource audioSource = gameObject.GetComponent&AudioSource&();
audioSource.PlayOneShot(audioSource.clip);
首先我们通过canUpdateMonster检查能否升级,如果可以升级,则通过调用MonsterData组件的increaseLevel方法升级怪物,最后播放一次声音特效。
保存文件并返回到Unity,运行游戏,试试放置和升级怪物~
支付金币 - Game Manager
目前而言,可以立即的建造和升级任意数目的怪兽,但这样一来,就木有挑战了。
我们接下来就处理金币的问题,为例维护金币的信息,你不得不要在不同的游戏对象之间共享数据信息。
下面的图片显示了所有需要金币信息的游戏对象:
我们将使用一个其他对象都能访问的共享对象来存储这类数据。
在Hierarchy面板中,右键选择Create Empty,并命名为GameManager。
添加一个C#脚本组件GameManagerBehavior到刚刚创建的GameManager上,然后打开并编辑这个脚本。
因为我们需要使用一个label显示玩家所拥有的金币数,所以在文件的顶部增加下面的引用:
using UnityEngine.UI;
这将允许我们使用UI相关的类型,比如Text用做显示用的label,接下来在类中添加下面的变量:
public Text goldL
这个变量存储了对Text组件的引用,将用于显示玩家所拥有的所有金币数。
现在GameManager已经可以操作label了,但是我们如何保证变量中存储的金币数和label显示的数量同步呢,我们创建一个属性:
public int Gold
goldLabel.GetComponent&Text&().text = &GOLD: & +
是不是看起来很熟悉,这个跟我们在Monster中定义的CurrentLevel比较相像,首先我们创建一个私有的变量gold用来存储当前所有的金币数,然后定义一个名为Gold的属性,并提供getter和setter方法。
在getter方法中简单的直接返回gold,setter方法则比较有趣了,除了设置gold的值,还设置了goldLabel的显示。
这样就保持了金币数和显示的同步。
在Start()中增加下面的初始化语句,默认给玩家100金币(当然你可以给更少的)
Gold = 100;
给脚本中的Label对象赋值
保持脚本文件并返回到Unity中。
在Hierarcy中,选中GameManager,在Inspector面板,点击GoldLabel右边的圆圈按钮,在Select Text对话框中,选中Scene标签页,并选中GoldLabel
运行游戏,可以看到金币的显示如下:
检查玩家的“钱包&
打开PlaceMonster.cs文件,增加下面这行代码:
private GameManagerBehavior gameM
我们将通过变量gameManager来访问场景中GameManager的GameManagerBehavior组件,并在Start方法中初始化:
void Start ()
gameManager = GameObject.Find(&GameManager&).GetComponent&GameManagerBehavior&();
我们使用GameObject.Find方法,找到名为GameManager的游戏对象,然后定位到其GameManagerBehavior组件并存到一个私有变量中,供稍后使用。
我们还没有减少金币数,所以在OnMouseUp方法里面,将原来的TODO注释修改为下面的代码:
//todo: Deduct gold
gameManager.Gold -= monster.GetComponent&MonsterData&().CurrentLevel.
注意是两个地方,在放置和升级的逻辑里各有一处。
保存文件并返回unity,升级一些怪物并注意观察金币数目的变化。现在我们能够减少金币数了,但是。。。玩家可以一直放置怪物(只要有空位),金币数甚至可以变成负数。
这显然是不能被允许的,只有当玩家有足够的金币时,才能放置或者升级我们的怪物。
切换到PlaceMonster.cs脚本,更新canPlaceMonster和canUpdateMonster方法如下,就是加上检查剩余金币是否足够的条件。
private bool canPlaceMonster()
int cost = monsterPrefab.GetComponent&MonsterData&().levels[0].
return monster == null && gameManager.Gold &= //确保金币足够
private bool canUpdateMonster()
if (monster != null)
MonsterData monsterData = monster.GetComponent&MonsterData&();
MonsterLevel nextLevel = monsterData.getNextLevel();
if (nextLevel != null)
return gameManager.Gold &= nextLevel. //确保金币足够
保存,并运行游戏,试试还能不能无限添加怪物。
敌人、波数和路标
是时候给敌人“铺路”了。敌人首先在第一个路标的地方出现,然后向下一个路标移动并重复这个动作,知道他们抵达你的饼干。
我们将通过下面的手段使敌人行军起来:
定义敌人移动的路线
使敌人沿着路线移动
旋转敌人,使他们看起来是向前方行进
通过路标建立路线
在Hierarcy中右键,选择Create Empty创建一个新的空的游戏对象,命名为Road,并确保其位置坐标为(0, 0, 0)
接下来,右键点击Road并创建另一个空的游戏对象,命名为Waypoint0 并将其坐标设置为(-12, 2, 0),这将是敌人开始进攻的起始点。
创建另外5个路标:
Waypoint1: (7, 2, 0)
Waypoint2: (7, -1, 0)
Waypoint3: (-7, 3, 0)
Waypoint4: (-7.3, -4.5, 0)
Waypoint5: (7, -4.5, 0)
下面的截图标示出了路标的位置以及最终的路线:
现在是时候去创建一些敌人来沿着上面的路线移动了。在Prefabs的文件夹中包含了一个Enemy的prefab。 它的位置坐标是(-20,0,0) ,所以新创建的敌人对象一开始在平面外面。
跟Monster的prefab一样,Enemy的prefab同样包含了一个AudioSource,一个精灵图片(一会儿可以旋转其方向)。
使敌人沿着路线移动
向Prefabs\Enemy新建一个名为MoveEnemy的C#脚本,使用代码编辑器打开,并添加下面的变量定义:
[HideInInspector]
public GameObject[]
private int currentWaypoint = 0;
private float lastWaypointSwitchT
public float speed = 1.0f;
waypoints以数组的形式存储了所有的路标,它上面的HideInInspector特性确保了我们不会在inspector面板中不小心修改了它的值,但是我们仍然可以在其他脚本中访问。
currentWaypoint记录了敌人当前所在的路标,lastWaypointSwitchTime记录了当敌人经过路标时用的时间,最后使用speed存储敌人的移动速度。
增加下面这行代码到Start方法中:
lastWaypointSwitchTime = Time.
这里将lastWaypointSwitchTime初始化为当前时间。
为了使敌人能沿路线移动,在Update方法中添加下面的代码:
Vector3 startPosition = waypoints[currentWaypoint].transform.
Vector3 endPosition = waypoints[currentWaypoint + 1].transform.
float pathLength = Vector3.Distance(startPosition, endPosition);
float totalTimeForPath = pathLength /
float currentTimeOnPath = Time.time - lastWaypointSwitchT
gameObject.transform.position = Vector3.Lerp(startPosition, endPosition, currentTimeOnPath / totalTimeForPath);
if (gameObject.transform.position.Equals(endPosition))
if (currentWaypoint & waypoints.Length - 2)
currentWaypoint++;
lastWaypointSwitchTime = Time.
// TODO: Rotate into move direction
Destroy(gameObject);
AudioSource audioSource = gameObject.GetComponent&AudioSource&();
AudioSource.PlayClipAtPoint(audioSource.clip, transform.position);
// TODO: deduct health
让我们一步一步来看:
从路标数组中,取出当前路段的开始路标和结束路标。
计算出通过整个路段所需要的时间(使用 距离除以速度 的公式),使用Vector3.Lerp插值计算出当前时刻应该在的位置。
检查敌人是否已经抵达结束路标,如果是,则有两种可能的场景:
A. 敌人尚未抵达最终的路标,所以增加currentWayPoint并更新lastWaypointSwitchTime,稍后我们要增加旋转敌人的代码使他们朝向前进的方向。
B. 敌人抵达了最终的路标,就销毁敌人对象,并触发声音特效,稍后我们要增加减少玩家生命值的代码。
保存文件,并返回到Unity。
给敌人指明方向
现在,敌人还不知道路标的次序。
在Hierarchy中选中Road,然后添加一个新的C#脚本命名为SpawnEnemy,并在代码编辑器中打开,增加下面的变量:
public GameObject[]
我们将使用waypoints来存放路标的引用。
保存文件返回Unity, 在Hierarchy中选中Road,将WayPoints数组的大小改为6,拖拽Road的孩子节点到想用的Element位置,Waypoint0对应Element0以此类推。
现在我们已经有了路线的路标数组,注意到敌人不会退缩。。。
检查一切顺利
打开SpawnEnemy脚本,增加下面的变量:
public GameObject testEnemyP
这里使用了testEnemyPrefab保存对Enemyprefab的引用。
使用下面的代码,当脚本开始时添加一个敌人:
void Start () {
Instantiate(testEnemyPrefab).GetComponent&MoveEnemy&().waypoints =
上面的代码使用testEnemyPrefab实例化一个敌人对象,并将路标赋值给它。
保存文件返回Unity,在Hierarchy中选中Road并将Enemy prefab赋值给testEnemyPrefab。
运行游戏,可以看到敌人已经能够沿着路线移动了:
nice,但是有没有注意到敌人移动的时候没有朝向移动的方向。。没有关系,这个问题将在part2部分修复。
原文地址:
阅读(...) 评论()更多频道内容在这里查看
爱奇艺用户将能永久保存播放记录
过滤短视频
暂无长视频(电视剧、纪录片、动漫、综艺、电影)播放记录,
按住视频可进行拖动
&正在加载...
收藏成功,可进入
查看所有收藏列表
当前浏览器仅支持手动复制代码
视频地址:
flash地址:
html代码:
通用代码:
通用代码可同时支持电脑和移动设备的分享播放
用爱奇艺APP或微信扫一扫,在手机上继续观看
当前播放时间:
一键下载至手机
限爱奇艺安卓6.0以上版本
使用微信扫一扫,扫描左侧二维码,下载爱奇艺移动APP
其他安装方式:手机浏览器输入短链接http://71.am/udn
下载安装包到本机:
设备搜寻中...
请确保您要连接的设备(仅限安卓)登录了同一爱奇艺账号 且安装并开启不低于V6.0以上版本的爱奇艺客户端
连接失败!
请确保您要连接的设备(仅限安卓)登录了同一爱奇艺账号 且安装并开启不低于V6.0以上版本的爱奇艺客户端
部安卓(Android)设备,请点击进行选择
请您在手机端下载爱奇艺移动APP(仅支持安卓客户端)
使用微信扫一扫,下载爱奇艺移动APP
其他安装方式:手机浏览器输入短链接http://71.am/udn
下载安装包到本机:
爱奇艺云推送
请您在手机端登录爱奇艺移动APP(仅支持安卓客户端)
使用微信扫一扫,下载爱奇艺移动APP
180秒后更新
打开爱奇艺移动APP,点击“我的-扫一扫”,扫描左侧二维码进行登录
没有安装爱奇艺视频最新客户端?
Unity塔防游戏 VR制作
正在检测客户端...
您尚未安装客户端,正在为您下载...安装完成后点击按钮即可下载
, 可在设置中重新打开噢!
30秒后自动关闭
Unity塔防游戏 VR制作">Unity塔防游戏 VR制作
请选择打赏金额:
播放量12.7万
播放量数据:快去看看谁在和你一起看视频吧~
更多数据:
Copyright (C) 2018 & All Rights Reserved
您使用浏览器不支持直接复制的功能,建议您使用Ctrl+C或右键全选进行地址复制
正在为您下载爱奇艺客户端安装后即可快速下载海量视频
正在为您下载爱奇艺客户端安装后即可免费观看1080P视频
&li data-elem="tabtitle" data-seq="{{seq}}"& &a href="javascript:void(0);"& &span>{{start}}-{{end}}&/span& &/a& &/li&
&li data-downloadSelect-elem="item" data-downloadSelect-selected="false" data-downloadSelect-tvid="{{tvid}}"& &a href="javascript:void(0);"&{{pd}}&/a&
选择您要下载的《
色情低俗内容
血腥暴力内容
广告或欺诈内容
侵犯了我的权力
还可以输入
您使用浏览器不支持直接复制的功能,建议您使用Ctrl+C或右键全选进行地址复制

我要回帖

更多关于 unity3d塔防游戏素材 的文章

 

随机推荐