unity3d学习笔记(十八)--利用C#的代理和事件结合NGUI的按钮实现施放技能

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

http://blog.csdn.net/lzhq1982/article/details/12999381


对C#还不是很熟,在学习的过程中了解到C#有种代理和事件的机制很方便,之前用cocos2d的时候也用过代理,虽然此代理非彼代理,但他们的作用有相似之处,都是触发者只是告知事件,并不调用相关类和方法实现,而是由代理方法实现,可能有些难懂,下面我用之前的demo中英雄施放技能这里做个试验。

本篇涉及三个知识点,一个是最重要的代理,一个是NGUI的按钮,一个是施放技能特效。


1、NGUI制作技能按钮

关于NGUI我前面的文章说了好多,重复的部分我就不介绍了。我打算把技能按钮放在NGUI界面布局的右下角锚点处,先在右下角锚点处加个Panel,我起名SkillPanel,在该Panel下我建立一个按钮,选NGUI->Open the Widget Wizard,Atlas选你将图片打包的那个文件,没有的话先建立一个,不知道怎么建的看前面的文章。Template里选Button,然后会出现Background,是按钮图片,从Atlas中选一个,我的设置如下:


选择Add To后SkillPanel下新增一个按钮,我起名ZhongJiButton,布局如下:


调整位置,我的按钮截屏如下(右下角那个):



2、利用C#的代理和事件施放技能。

要施放技能,肯定要点击按钮,NGUI为按钮提供了OnClick接口。我们先创建一个脚本,我命名CastSkill,然后拖到ZhongJiButton上,CastSkill里只要实现OnClick接口就好了。一般我们会怎么实现点击施放呢,最传统的做法就是获得英雄的对象,然后利用该对象向她传递施放技能的消息,比如代码如下:

[csharp]  view plain copy
  1. void OnClick() {  
  2.     GameObject hero = GameObject.Find("Blade_Girl_Prefab");  
  3.     if (hero)  
  4.         hero.SendMessage("CastSkill", 1);  
  5. }  
像上面我通知hero的CastSkill接口,传递的参数1是SkillID,很简单,这就实现了,但你有没有想过,这又陷入了脚本之间耦合性的增加,看过我前面 单例脚本和单例类 这篇文章应该明白脚本之间大量的互相访问不是件好事。那我们就看看代理能不能帮我们解决办法。

想了解什么是代理和怎么用代理的可以看这篇文章,写的挺全的:C#中的代理与事件,重点看里面的一和三,我就偷个懒,只说明我这里是怎么实现的。现在我用代理重新改一下上面的脚本:

[csharp]  view plain copy
  1. public class CastSkill : MonoBehaviour {  
  2.     public delegate void EventHandler(int nSkillId);  
  3.     public event EventHandler OnCastSkill;  
  4.       
  5.     void OnClick() {  
  6.         if (OnCastSkill != null)  
  7.             OnCastSkill(1);  
  8.     }  
  9. }  

可以看出上面先创建了一个代理EventHandler,传递一个参数nSkillId,然后创建该代理的一个事件OnCaskSkill,在OnClick里触发这个事件OnCastSkill(1),“1”是代理传递的那个参数nSkillId。你会发现这里根本没有Hero的事,那Hero怎么接收消息呢。下面我们看看Hero相关的代码。

[csharp]  view plain copy
  1. CastSkill onCastSkill = skillBtn.GetComponent<CastSkill>();  
  2. onCastSkill.OnCastSkill += CastSkill;  
[csharp]  view plain copy
  1. void CastSkill(int nSkillId)  
  2. {  
  3.     if (curState == en_state.en_state_idel || curState == en_state.en_state_attack) {  
  4.         if (nSkillId == 1) {  
  5.             lastState = curState;  
  6.             curState = en_state.en_state_skill;  
  7.         }  
  8.     }  
  9. }  

在Hero里,我先是获得按钮的那个脚本CaskSkill对象,重点是下面那句,我为OnCastSkill这个事件挂接了实现的方法CastSkill,然后你就可以在CastSkill里实现释放技能了。所谓代理,就是触发者根本就不用关心到底是谁接收了,而接受者只要调用该代理事件,并挂接个实现方法就OK了,这样只要触发者一触发,凡是挂接过该事件的方法都会响应,这就是代理。不知道您明白了吗。


3、施放技能
如上面代码,我给英雄置了当前状态为技能状态,她会在Update的状态机里处理,调用playEffect函数。

[csharp]  view plain copy
  1. void playEffect()  
  2. {  
  3.     if (!animation.IsPlaying("ComboAttack"))  
  4.         gameObject.animation.CrossFade("ComboAttack");  
  5.   
  6.     AnimationState state = animation["ComboAttack"];  
  7.     if (state.time >= state.length-0.5f && !isCastSkill) {             
  8.         Vector3 pos = transform.position + transform.TransformDirection(Vector3.forward*3);  
  9.         Instantiate(effect, pos, transform.rotation);  
  10.         isCastSkill = true;  
  11.     }  
  12.           
  13.     if (isCastSkill && state.time >= state.length-0.1f) {  
  14.         isCastSkill = false;  
  15.         curState = lastState;  
  16.     }  
  17. }  



上面代码大致意思是先播放动作,当动作播放到一半的时候播放特效,我这里特效是个prefab,特效只播放一次,所以isCastSkill是用来控制播放次数的,因为特效要播放在角色身前,所以上面获取pos那句代码是根据角色的位置加上其朝向前方3个单位的距离获得的。最后上个图吧。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值