您现在的位置是:首页 > 数码 > 

unity怪物攻击玩家减血

2025-07-27 13:33:11
unity怪物攻击玩家减血 本系列文章由Aimar_Johnny编写,欢迎转载,转载请标明出处,谢谢。 我们的世界有了怪物,那么你怎么忍心不去虐他们一下,勇士,挥舞你的大刀,去砍他们吧。呃,有点血腥,少儿不宜。 如上一篇所说,我这里的交互全是在单例脚本中

unity怪物攻击玩家减血

本系列文章由Aimar_Johnny编写,欢迎转载,转载请标明出处,谢谢。

我们的世界有了怪物,那么你怎么忍心不去虐他们一下,勇士,挥舞你的大刀,去砍他们吧。呃,有点血腥,少儿不宜。

如上一篇所说,我这里的交互全是在单例脚本中实现的。命名为BattleScene,单例脚本负责事件的分发和传递,Hero和Mter脚本负责触发和接收处理消息,设计理念是在Hero脚本中你绝对看不到Mter,同样,Mter脚本中,你也看不到Hero,他们都在单例脚本中,单例脚本中有这么一段核心的消息传递代码:

publicvoidSendGameMessage(MESSAGE_TYPE type, T t)

{

switch(type) {

caseMESSAGE_TYPE.MESSAGE_HERO_RU_AT_TARGET:

_hero.SendMessage(RunAtTarget, t);

break;

caseMESSAGE_TYPE.MESSAGE_HERO_BE_HURT:

_hero.SendMessage(ReduceHp, t);

break;

caseMESSAGE_TYPE.MESSAGE_EEMY_BE_HURT:

if(_enemy)

_enemy.SendMessage(BeHurt);

break;

caseMESSAGE_TYPE.MESSAGE_EEMY_REDUCE_HP:

if(_enemy)

_enemy.SendMessage(ReduceHp, t);

break;

}

}

每一条消息传递一个交互,现在看不懂没关系,下面我再细细讲解,只是这里的,如果有人不清楚,可以说一下,它是C#里的泛型的概念,C里也有类似的模板,说白了,就是可以代替你想要的类型,用处很广,这里用来传递数值,因为不知道数值会是什么类型,所以泛型就大显神威了。

言归正传,我的英雄和怪物的交互流程是这样的,点击一个怪->英雄跑过去->英雄发起攻击->怪物受击->怪物反击->英雄受击->英雄继续攻击->如此反复,直到一方死去。下面就按照这个流程看看我是怎么实现的。

1、点击一个怪

voidOnMouseDown()

{

BattleScene.GetInstance().SendGameMessage(BattleScene.MESSAGE_TYPE.MESSAGE_HERO_RU_AT_TARGET, gameObject);

}

这是怪物脚本上的响应鼠标点击的函数,就一句,向单例脚本发消息,第一个参数是消息类型,第二个参数是传递的数值,这里传的是怪物的gameobject。然后你可以对照上面的消息传递代码,向hero脚本的RunAtTarget()这个函数传递消息,意思是英雄啊,你该向那个怪跑了。

2、英雄跑过去

voidRunAtTarget(GameObject obj)

{

BattleScene.GetInstance().Enemy = obj;

curState = en__state_run;

isHunting = true;

}

caseen__state_run:

curAnimClip = animation[Run].clip;

gameObject.animation.CrossFade();

Vector forward = transform.TransformDirection(Vector.forward);

_controller.SimpleMove(forward * runSpeed);

if(BattleScene.GetInstance().Enemy) {

smoothRotate(BattleScene.GetInstance().position);

} elseif(runTarget != Vector.zero) {

。。。

}

break;

RunAtTarget的参数传递的是怪物的gameobject,但我不会将这个怪物存在hero脚本中,我把它传给了单例脚本,以后想要获得这个怪物信息,单例脚本要去,这里粘一下单例脚本的Enemy代码

publicGameObject Enemy

{

get{return_enemy;}

set{_enemy = value;}

}

C#的这种get和set方式挺简便的,我就给试上了。然后在update的状态机里处理奔跑,把以前单纯的奔跑改了一下,如果有Enemy,就向Enemy平滑转身,smoothRotate是处理平滑转身的,不清楚的可以在我前面的文章里到详细代码。

、英雄发起攻击

if(isHunting) {

if(BattleScene.GetInstance().IsInAttackArea()) {

curState = en__state_attack;

BattleScene.GetInstance().SendGameMessage(BattleScene.MESSAGE_TYPE.MESSAGE_EEMY_BE_HURT,0);

isHunting = false;

}

}

caseen__state_attack:

if(BattleScene.GetInstance().Enemy) {

AnimationState state = animation[];

if( >= state.length-0.1f) {

intrand = Random.Range(0,);

if(rand == 0)

curAttackState = attack_state.attack_state_0;

elseif(rand == 1)

curAttackState = attack_state.attack_state_1;

elseif(rand == 2)

curAttackState = attack_state.attack_state_2;

isReduceEnemyHp =  true;

}

if( >= state.length/2 &&  

if(isReduceEnemyHp) {

isReduceEnemyHp = false;

BattleScene.GetInstance().SendGameMessage(BattleScene.MESSAGE_TYPE.MESSAGE_EEMY_REDUCE_HP, 20);

}

}

if(curAttackState == attack_state.attack_state_0)

curAnimClip = animation[Attack].clip;

elseif(curAttackState == attack_state.attack_state_1)

curAnimClip = animation[Attack00].clip;

elseif(curAttackState == attack_state.attack_state_2)

curAnimClip = animation[Attack01].clip;

animation.CrossFade();

transform.Translate(Vector.zero);

} else{

curState = en__state_idel;

curAnimClip = animation[Attack].clip;

}

break;

代码有点长,前面的代码是在update里随时判断英雄是否跑到怪物身边,也就是是否在攻击范围内,如果是,置攻击状态,在状态机里处理,同时给怪物发消息,你受到攻击了,不要再悠闲的溜达了,赶紧还击吧。判断攻击范围代码如下:

publicboolIsInAttackArea()

{

if(_hero && _enemy) {

CharacterController enemyController = _enemy.GetComponent();

CharacterController heroController = _hero.GetComponent();

floatdist = Vector.Distance(_position, _position);

if(dist <= enemyController.radiusheroController.radius1.0f)

returntrue;

}

returnfalse;

}

注意这段代码是在单例脚本里的,因为要用到hero和enemy,原理就是用他们的CharacterController得到他们的半径,如果他们的距离小于这两个半径之和,就说明发生碰撞了,就可以攻击了,加1是不想他们太近而已,哈哈。

接着说状态机里处理攻击的部分,先获得攻击动画的属性,如果该攻击动画要播完了,就随机出下一个攻击动画,我这里有三个攻击动作用来随机,如果攻击动作播了一半了,大概就是刀落在怪身上了,向怪发出掉血消息,如果怪物没了,则重置英雄为休息状态。这里插播一下怪物掉血,当英雄砍到怪物身上后,发出怪掉血信息,怪接收到掉血信息,如上面单例脚本的消息传递部分,执行ReduceHp代码。

voidReduceHp(intnHp)

{

curHP -= nHp;

if(curHP <= 0) {

BattleScene.GetInstance().Enemy = null;

Destroy(gameObject);

}

}

代码很简单,怪物累积减血,当血量小于等于零时,怪物死亡,删除掉该怪物,其实如果有死亡动画,播动画更好,我这里没有,就直接删了。

4、怪物受击

#感谢您对电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格的认可,转载请说明来源于"电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格

本文地址:http://www.dnpztj.cn/shuma/707462.html

相关标签:无
上传时间: 2023-11-21 20:50:15

上一篇:el

下一篇:CodeForces 360A

留言与评论(共有 18 条评论)
本站网友 顶风作案
28分钟前 发表
2
本站网友 方正同花顺完美版
7分钟前 发表
本站网友 充电kiss
15分钟前 发表
unity怪物攻击玩家减血 本系列文章由Aimar_Johnny编写,欢迎转载,转载请标明出处,谢谢
本站网友 长沙万国城moma
23分钟前 发表
 _position); if(dist <= enemyController.radiusheroController.radius1.0f) returntrue; } returnfalse; } 注意这段代码是在单例脚本里的,因为要用到hero和enemy,原理就是用他们的CharacterController得到他们的半径,如果他们的距离小于这两个半径之和,就说明发生碰撞了,就可以攻击了,加1是不想他们太近而已,哈哈
本站网友 胎菊的功效
29分钟前 发表
 _position); if(dist <= enemyController.radiusheroController.radius1.0f) returntrue; } returnfalse; } 注意这段代码是在单例脚本里的,因为要用到hero和enemy,原理就是用他们的CharacterController得到他们的半径,如果他们的距离小于这两个半径之和,就说明发生碰撞了,就可以攻击了,加1是不想他们太近而已,哈哈
本站网友 维卫洁具
27分钟前 发表
然后在update的状态机里处理奔跑,把以前单纯的奔跑改了一下,如果有Enemy,就向Enemy平滑转身,smoothRotate是处理平滑转身的,不清楚的可以在我前面的文章里到详细代码
本站网友 武汉凡谷电子
3分钟前 发表
接着说状态机里处理攻击的部分,先获得攻击动画的属性,如果该攻击动画要播完了,就随机出下一个攻击动画,我这里有三个攻击动作用来随机,如果攻击动作播了一半了,大概就是刀落在怪身上了,向怪发出掉血消息,如果怪物没了,则重置英雄为休息状态
本站网友 茵陈的功效
8分钟前 发表
英雄发起攻击 if(isHunting) { if(BattleScene.GetInstance().IsInAttackArea()) { curState = en__state_attack; BattleScene.GetInstance().SendGameMessage(BattleScene.MESSAGE_TYPE.MESSAGE_EEMY_BE_HURT
本站网友 疫苗查询
17分钟前 发表
本站网友 广东省机械设备成套局
21分钟前 发表
if(_enemy) _enemy.SendMessage(ReduceHp
本站网友 刷网站流量
14分钟前 发表
英雄发起攻击 if(isHunting) { if(BattleScene.GetInstance().IsInAttackArea()) { curState = en__state_attack; BattleScene.GetInstance().SendGameMessage(BattleScene.MESSAGE_TYPE.MESSAGE_EEMY_BE_HURT
本站网友 机箱风扇
29分钟前 发表
if(_enemy) _enemy.SendMessage(BeHurt); break; caseMESSAGE_TYPE.MESSAGE_EEMY_REDUCE_HP
本站网友 减肥茶配方
17分钟前 发表
判断攻击范围代码如下: publicboolIsInAttackArea() { if(_hero && _enemy) { CharacterController enemyController = _enemy.GetComponent(); CharacterController heroController = _hero.GetComponent(); floatdist = Vector.Distance(_position
本站网友 bt爱唯侦察
11分钟前 发表
voidReduceHp(intnHp) { curHP -= nHp; if(curHP <= 0) { BattleScene.GetInstance().Enemy = null; Destroy(gameObject); } } 代码很简单,怪物累积减血,当血量小于等于零时,怪物死亡,删除掉该怪物,其实如果有死亡动画,播动画更好,我这里没有,就直接删了
本站网友 小小宝
25分钟前 发表
 t); break; } } 每一条消息传递一个交互,现在看不懂没关系,下面我再细细讲解,只是这里的,如果有人不清楚,可以说一下,它是C#里的泛型的概念,C里也有类似的模板,说白了,就是可以代替你想要的类型,用处很广,这里用来传递数值,因为不知道数值会是什么类型,所以泛型就大显神威了
本站网友 石玺彤
2分钟前 发表
命名为BattleScene,单例脚本负责事件的分发和传递,Hero和Mter脚本负责触发和接收处理消息,设计理念是在Hero脚本中你绝对看不到Mter,同样,Mter脚本中,你也看不到Hero,他们都在单例脚本中,单例脚本中有这么一段核心的消息传递代码: publicvoidSendGameMessage(MESSAGE_TYPE type
本站网友 河南省建筑职业技术学院
13分钟前 发表