unity3d 塔防自动unity 寻路插件 用Vector3 应该怎么实现

阅读:4511次
给怪兽子弹——很多很多的子弹!
将Images/Objects/Bullet1 从Project Browser拖拽到场景中。将z 位置设置为-2 ——x 和 y 位置不重要,因为在运行时每次实例化一个新的子弹都需要设置它们。
添加一个名为BulletBehavior的新脚本,并在MonoDevelop中添加以下变量。
Public float speed =10;
public GameO
public Vector3 startP
public Vector3 targetP
privatefloat startT
private GameManagerBehavior gameM
speed 决定子弹的飞行速度;damage 就不用说明了。target,startPosition和targetPosition 决定子弹的方向。distance 和startTime 追踪子弹当前的位置。当怪兽毁掉敌人时gameManager 用来奖励玩家。
在Start()中为这些变量赋值:
startTime = Time.
distance = Vector3.Distance(startPosition, targetPosition);
GameObject gm = GameObject.Find(&GameManager&);
gameManager = gm.GetComponent&GameManagerBehavior&();
将startTime 设置为当前时间并计算起始位置和目标位置间的距离。还要向往常一样获取GameManagerBehavior 。
在Update() 中添加以下代码来控制子弹的移动:
float timeInterval = Time.time- startT
gameObject.transform.position= Vector3.Lerp(startPosition, targetPosition, timeInterval * speed / distance);
if(gameObject.transform.position.Equals(targetPosition)){
if(target !=null){
Transform healthBarTransform = target.transform.FindChild(&HealthBar&);
HealthBar healthBar =
healthBarTransform.gameObject.GetComponent&HealthBar&();
healthBar.currentHealth-= Mathf.Max(damage, 0);
if(healthBar.currentHealth&=0){
Destroy(target);
AudioSource audioSource = target.GetComponent&AudioSource&();
AudioSource.PlayClipAtPoint(audioSource.clip, transform.position);
gameManager.Gold+=50;
Destroy(gameObject);
通过用Vector3.Lerp 获取起始位置和结束位置的差值来计算新子弹的位置。
如果子弹到达了targetPosition,要核实target 仍然存在。
检索目标的HealthBar 组件并根据子弹的伤害减掉它的生命值。
如果敌人的生命值将为零,销毁它,播放一段声音效果并为击中敌人奖励玩家。
保存文件并回到unity。
获取更大的子弹
如果怪兽在高等级发生更大的子弹是不是很酷?——是的,必须的!辛运的是,这个很容易实现。
将Bullet1 游戏对象从 Hierarchy 拖拽到Project 面板来创建一个子弹的预制件。将原来的对象从场景移除——不再需要它了。
复制Bullet1 两次。为复制件分别命名Bullet2 和Bullet3。选择Bullet2。在Inspector中,将Sprite Renderer 组件的Sprite 区域设置为Images/Objects/Bullet2。这标志着Bullet2看起来比Bullet1大一些。
重复这步来设置Bullet3 预制件的Sprite 为Images/Objects/Bullet3。
接下来,在Bullet Behavior中设置子弹带来的伤害值是多少。在Project 标签选择Bullet1 预制件。在Inspector 中可以看到Bullet Behavior (Script),并在那里为Bullet1的 Damage 设置为 10 ,为Bullet2设置为15 ,为Bullet3 设置为20——或者想要设置多少就设置多少。
注:设置好值以便在更高等级中,每次带来的伤害会更高。这抵消了升级允许玩家在最佳位置提升怪兽的事实。
子弹预制件——随着等级而变大
为不同等级的怪兽分配不同的子弹,所以更强壮的怪兽会更快的杀掉敌人。
在MonoDevelop中打开MonsterData.cs ,为MonsterLevel添加以下变量:
public GameO
public float fireR
这些会为每个怪兽等级设置子弹预制件和发射速度。保存文件并返回unity完成怪兽的设置。
在Project Browser选择Monster 预制件。在Inspector中,在Monster Data (Script) 组件扩展Levels 。为每个元素将Fire Rate 设置为1 。然后分别将Elements 0,,1 和2的Bullet 设置为Bullet1, Bullet2 和 Bullet3,
怪兽等级应该被配置为像下边显示这样:
在MonoDevelop中打开ShootEnemies.cs,添加以下变量:
Private float lastShotT
private MonsterData monsterD
正如它们名字的启示,这些变量持续跟踪什么时候怪兽做了最后一次开火,还有 MonsterData结构包括这个怪兽的子弹类型,开火速度等信息。
在Start()中为这些字段赋值:
lastShotTime = Time.
monsterData = gameObject.GetComponentInChildren&MonsterData&();
这里将lastShotTime 设置为当前时间,并可以访问这个对象的MonsterData 组件。
添加以下方法来实现开火:
void Shoot(Collider2D target){
GameObject bulletPrefab = monsterData.CurrentLevel.
Vector3 startPosition = gameObject.transform.
Vector3 targetPosition = target.transform.
startPosition.z= bulletPrefab.transform.position.z;
targetPosition.z= bulletPrefab.transform.position.z;
GameObject newBullet =(GameObject)Instantiate (bulletPrefab);
newBullet.transform.position= startP
BulletBehavior bulletComp = newBullet.GetComponent&BulletBehavior&();
bulletComp.target= target.gameO
bulletComp.startPosition= startP
bulletComp.targetPosition= targetP
Animator animator =
monsterData.CurrentLevel.visualization.GetComponent&Animator&();
animator.SetTrigger(&fireShot&);
AudioSource audioSource = gameObject.GetComponent&AudioSource&();
audioSource.PlayOneShot(audioSource.clip);
获取子弹起始位置和目标位置。为bulletPrefab设置z方向位置。之前,设置了子弹预制件的z方向位置来确保子弹出现在发射它的怪兽后边,不过要在敌人前边。
为MonsterLevel用bulletPrefab 实例化一个新的子弹。为子弹分配startPosition 和targetPosition 。
使游戏更有趣:无论什么时候怪兽射击都运行一个射击动画并播放给激光声音。
将所有汇总
现在是时候将所有都连接到一起了。确定目标并让怪兽看向它。
还是在ShootEnemies.cs中,将以下代码添加到Update()
GameObject target =
float minimalEnemyDistance =float.MaxV
foreach(GameObject enemy in enemiesInRange){
float distanceToGoal = enemy.GetComponent&MoveEnemy&().distanceToGoal();
if(distanceToGoal & minimalEnemyDistance){
minimalEnemyDistance = distanceToG
if(target !=null){
if(Time.time- lastShotTime & monsterData.CurrentLevel.fireRate){
Shoot(target.GetComponent&Collider2D&());
lastShotTime = Time.
Vector3 direction = gameObject.transform.position- target.transform.
gameObject.transform.rotation= Quaternion.AngleAxis(
Mathf.Atan2(direction.y, direction.x)*180/ Mathf.PI,
new Vector3 (0, 0, 1));
一步一步看这些代码。
确定怪兽的目标。在minimalEnemyDistance中以最大可能的距离开始。遍及范围内的所有怪兽并且如果敌人距离曲奇的距离比当前的最小值更小时将敌人作为新的目标。
如果过去的时间大于怪兽的射击速度则呼叫Shoot 并将lastShotTime 设置为当前时间。
计算怪兽和它的目标间的旋转角度。将怪兽旋转这个角度。现在它总是面向目标了。
保存文件并在unity中播放游戏。怪兽努力的保护着曲奇。现在就全部做完啦!
哇,现在已经按照两个教程做了好多事,并且还有一个酷酷的游戏可以展示。如果从这个教程创建了另一个新的游戏,我们愿意去玩——所以在评论分享一下链接和你的畅想。
在这个采访中会发现很多关于塔防游戏的有趣想法。
感谢大家花费时间来看这些教程。期盼看到你们超级棒的想法并杀掉很多怪兽。
相关文章推荐
泰然网手游开发官方群:
独立游戏人:Unity3D开发敌人自动攻击和自动寻路
Unity3D开发敌人自动攻击和自动寻路
Unity3D游戏开发
简介:当制作动作类攻击游戏时,会用到敌人的自动攻击及自动寻找攻击目标,如何实现自动攻击和自动寻路呢?下面简单的讲解我对这方面的理解。
当你已经导入了敌人的模型并制作好了敌人动画控制状态机,接下来肯定会想让敌人具备攻击和寻找目标的能力,要开发这一功能,其实只需要做两件事情:
第一:通过CharacterController控制移动,即通过调用SimpleMove(Vector3)移动。
第二:根据主角的位置和距离,判断是否进行攻击,攻击的时候利用随机数来发起攻击动画的选择。
编写脚本:Enimy.cs
using UnityE
usingSystem.C
MonoBehaviour {
// Use this for initialization
float attackDistance = 2;//这是攻击目标的距离,也是寻路的目标距离
CharacterController
float attackTime = 3;&&
//设置定时器时间
3秒攻击一次
float attackCounter = 0;
//计时器变量
voidStart () {
player = GameObject.FindGameObjectWithTag(&Player&).
cc = this.GetComponent&CharacterController&();
animator = this.GetComponent&Animator&();//控制动画状态机中的奔跑动作调用
attackCounter = attackT//一开始只要抵达目标立即攻击
// Update is called once per frame
voidUpdate () {
Vector3 targetPos =player.
targetPos.y = transform.position.y;//此处的作用将自身的Y轴值赋值给目标Y值
transform.LookAt(targetPos);//旋转的时候就保证已自己Y轴为轴心旋转
float distance =
Vector3.Distance(targetPos,transform.position);
if (distance &= attackDistance)
&&&&&&&&&&&
attackCounter += Time.deltaT
&&&&&&&&&&&
if (attackCounter &attackTime)//定时器功能实现
&&&&&&&&&&&
&&&&&&&&&&&&&&&
Random.Range(0, 2);//攻击动画有两种,此处就利用随机数(【0】,【1】)切换两种动画
&&&&&&&&&&&&&&&
if (num == 0)animator.SetTrigger(&Attack1&);
&&&&&&&&&&&&&&&
else animator.SetTrigger(&Attack2&);
&&&&&&&&&&&&&&&
attackCounter = 0;
&&&&&&&&&&&
&&&&&&&&&&&
&&&&&&&&&&&
&&&&&&&&&&&&&&&
animator.SetBool(&Walk&,
&&&&&&&&&&&
&&&&&&&&&&&
attackCounter = attackT//每次移动到最小攻击距离时就会立即攻击
&&&&&&&&&&&
if(animator.GetCurrentAnimatorStateInfo(0).IsName(&EnimyWalk&))//EnimyWalk是动画状态机中的行走的状态
&&&&&&&&&&&&cc.SimpleMove(transform.forward*speed);
&&&&&&&&&&&
animator.SetBool(&Walk &,true);//移动的时候播放跑步动画
结合上面的注释,是不是很清楚这些功能的实现原理了,至少当我忘记的时候看到这个笔记就会明白了。有问题可以留言,一起交流学习。
我的热门文章
即使是一小步也想与你分享在做一个FPS游戏时,需要敌方自动找到玩家方位并向玩家移动,在查找资料(并走了不少坑)后,我试了三个方法,经测试,这三个方法都能实现自动寻路功能。
方法一:使用Mathf.Lerp()方法
代码很简单:
//在enemy.cs(即敌方的脚本)中更新如下代码:
Transmform m_transform
//在Update()函数中插入如下代码
m_transform.position =
new Vector3(Mathf.Lerp(m_transform.position.x,m_layer.m_transform.position.x,m_speed * Time.delta)),
Mathf.Lerp(m_transform.position.z,m_layer.m_transform.position.z,m_speed * Time.delta)))
//Mathf.Lerp(float a,float b,float t)函数表示:从点a以速度t移动至点b
这个方法似乎不需要自动寻路组件NavMeshAgent,不过NavMeshAgent用得更多一些,以下的两个方法都是基于NavMeshAgent的。
设置网格自动寻路的步骤:
1.将要进行Bake(烘焙)的场景设置为static(一定要保证Navigation Static是被勾选的):
2.通过Window -& Navgaition打开Navigation界面进行烘焙:
点击右下方的Bake(我第一次打开这个的时候一直没注意到这个Bake选项,还以为是这个选项没了!!!),等待它烘焙完成。还有另外一种烘焙方式,参见另一篇文章:
3.烘焙前:
简单到不知道怎么形容这个方法&
代码如下:
//先在Start()函数中获得玩家的组件:
m_player = GameObject.FindGameObjectWithTag("Player").GetComponent&Player&()
//将自动寻路的目标设置为玩家所在位置
GetComponent&NavMeshAgent&().destination = m_player.m_transform.position
这个方法是我最初使用的,但是出了很多意想不到的问题,我在正确烘焙场景后解决了这个问题,并使该方法正确执行了。代码如下:
NavMeshAgent m_
//寻路组件
//省略中间代码
//在Start()函数中获得NavMeshAgent组件
void Start(){
m_agent = GetComponent&NavMeshAgent&();
//将敌方的速度转化为以s为单位
float speed = m_speed * Time.delta * 0.1f;
m_agent.Move(m_transform.TransformDirection(new Vector3(0,0,speed)));
注1:不管哪种方法,都要将这些代码文件和enemy绑定在一起。
注2:虽然这三种方法都可行,但由于我初学unity,对它们的性能优劣以及差别并不了解,因此这些还有待研究。
阅读(...) 评论()

我要回帖

更多关于 unity2d寻路 的文章

 

随机推荐