十四章:角色技能系統的實現
14.1添加技能的特效名稱
5001,魔法彈,skill-09,傷害 350%,SingleTarget,Attack,350,0,20,10,Magician,1,Enemy,5,Efx_CriticalStrike,Skill-MagicBall,1.1
5002,治療,skill-13,治癒30HP,Passive,HP,30,0,10,20,Magician,1,Self,0,Heal_Effect,Attack1,0.83
5003,冥想,skill-10,魔法恢復20,Passive,MP,20,0,0,30,Magician,5,Self,0,Effect_BlueHeal,Attack1,0.83
5004,法力涌動,skill-08,攻擊力爲200%持續15秒,Buff,Attack,200,15,30,30,Magician,7,Self,0,RangeMagic_Effect,Skill-GroundImpact,1.1
5005,戰鬥熱誠,skill-12,攻擊力速度爲200%持續30,Buff,AttackSpeed,200,30,30,30,Magician,8,Self,0,Efx_One-handQuicken,Skill-GroundImpact,1.1
5006,究極風暴,skill-11,攻擊力400% 所有敵人,MultiTarget,Attack,400,0,50,40,Magician,9,Position,10,MagicSphere_effect,AttackCritical,0.8
public string effectName;
public string aniName;
public float aniTime;
info.effectName = proArray[14];
info.aniName = proArray[15];
info.aniTime = proArray[16];
void Update()
{
if (type = ShortType.Skill)
{
OnDrugUse();
}
}
void OnDrugUse()
{
bool success = ps.isEnoughMP (info.mpCost); //判斷是否有足夠的MP
if(!success)
{
}
else
{
pa.UseSkill(info); //釋放技能
}
}
public bool isEnoughMP(int value)
{
if (mp_remain >= value) //是否成功獲取
{
mp_remain -= value;
FaceUI._instance.SetFaceProperty(); //更新顯示
return true;
}
else
{
return false;
}
}
public GameObject[] effectArray;
private Dictionary<string,GameObject> effectDict = new Dictionary<string,GameObject>();
void Awake()
{
foreach(GameObject go in effectArray)
{
effectDict.Add(go.name,go);
}
}
14.2 回覆技能
- 按下技能鍵
- 設置狀態爲施法,此時無法移動
- 播放特效並計時
- 計時結束改變狀態並播放動畫
- 回覆HP/MP
因此,當info.applyType爲Passive時,即
public void UseSkill(SkillsInfo.SkillInfo info)
{
if(ps.role == playerRole.Magician) //判斷當前角色是否是Magician
{
if(info.applyRole == SkillsInfo.ApplyRole.Magician) //當前技能是否適用Magician
{
switch(info.applyType) //判斷
{
case SkillsInfo.ApplyType.Passive: //爲恢復技能時
StartCoroutine(OnPassiveSkillUse(info)); //利用協程的計時功能實現技能的使用。
break;
}
}
}
}
IEnumerator OnPassiveSkillUse(SkillsInfo.SkillInfo info)
{
state = PlayerState.skillAttack; //state設置爲skillAttack,無法進行移動
animation.CrossFade (info.aniName); //播放特效,注意這裏的動畫爲擡手施法的特效,如下左圖
yield return new WaitForSeconds(info.aniTime);
state = PlayerState.normalWalk; //當技能持續時間結束後,才能進行移動等操作
int hp = 0, mp = 0;
if(info.applyProperty == SkillsInfo.ApplyProperty.HP)
{
hp = info.applyValue;
}
else if(info.applyProperty == SkillsInfo.ApplyProperty.MP)
{
mp = info.applyValue;
}
ps.GetDrug (hp, mp); //加HP或MP
GameObject prefab = null;
effectDict.TryGetValue (info.effectName, out prefab); //從字典中獲取施法動畫,如下右圖
GameObject.Instantiate (prefab, transform.position, Quaternion.identity);
}
14.3 Buff技能
- 按下技能鍵
- 設置狀態爲施法,此時無法移動
- 播放特效並計時
- 計時結束改變狀態並播放動畫
- 增加對應屬性並計時
- 持續時間結束後還原
IEnumerator OnBuffSkillUse(SkillsInfo.SkillInfo info)
{
state = PlayerState.skillAttack;
animation.CrossFade (info.aniName);
yield return new WaitForSeconds(info.aniTime);
GameObject prefab = null;
effectDict.TryGetValue (info.effectName, out prefab);
GameObject.Instantiate (prefab, transform.position, Quaternion.identity);
state = PlayerState.normalWalk;
switch(info.applyProperty) //Buff技能要考慮增加的屬性,因此用case處理
{
case SkillsInfo.ApplyProperty.Attack:
ps.attack *= (info.applyValue/100f);
break;
case SkillsInfo.ApplyProperty.AttackSpeed:
attackRate *= (info.applyValue/100f);
break;
case SkillsInfo.ApplyProperty.Defense:
ps.defense *= (info.applyValue/100f);
break;
case SkillsInfo.ApplyProperty.Speed:
pm.speed *= (info.applyValue/100f);
break;
}
yield return new WaitForSeconds (info.applyTime); //持續一段時間
switch(info.applyProperty) //取消Buff效果
{
case SkillsInfo.ApplyProperty.Attack:
ps.attack /= (info.applyValue/100f);
break;
case SkillsInfo.ApplyProperty.AttackSpeed:
attackRate /= (info.applyValue/100f);
break;
case SkillsInfo.ApplyProperty.Defense:
ps.defense /= (info.applyValue/100f);
break;
case SkillsInfo.ApplyProperty.Speed:
pm.speed /= (info.applyValue/100f); //控制PlayerMove中的移動速度
break;
}
}
14.4 單目標技能
- 按下技能鍵
- 修改鼠標爲技能鎖定圖標
- 判斷是否點擊敵人(射線檢測)
- 設置狀態爲施法,此時無法移動
- 播放特效並計時
- 計時結束改變狀態並播放動畫
- 造成傷害
public void SetSkillAttackCursor()
{
Cursor.SetCursor (cursor_lockTarget, hotspot, mode);
}
private bool isLockingTarget = false;
private SkillsInfo.SkillInfo info;
void OnSingleTargetSkillUse(SkillsInfo.SkillInfo info)
{
state = PlayerState.skillAttack;
MouseSetting._instance.SetSkillAttackCursor ();
isLockingTarget = true;
this.info = info;
}
void Update()
{
if(isLockingTarget && Input.GetMouseButtonDown(0))
{
OnLockTargetButtonDown(); //處理技能釋放功能
}
}
void OnLockTargetButtonDown()
{
isLockingTarget = false;
switch(info.applyType)
{
case SkillsInfo.ApplyType.SingleTarget:
StartCoroutine(SkillAttackSingleTarget());
break;
case SkillsInfo.ApplyType.MultiTarget:
//todo
break;
}
}
IEnumerator SkillAttackSingleTarget()
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hitInfo;
bool isCollider = Physics.Raycast(ray,out hitInfo);
if(isCollider && hitInfo.collider.tag == Tags.enemy)
{
state = PlayerState.skillAttack;
animation.CrossFade (info.aniName);
yield return new WaitForSeconds(info.aniTime);
GameObject prefab = null;
effectDict.TryGetValue (info.effectName, out prefab);
GameObject.Instantiate (prefab, hitInfo.collider.transform.position, Quaternion.identity); //使用hitInfo.collider得到怪物
hitInfo.collider.GetComponent<WolfBaby>().BeDamaged((int)(GetAttack() * (info.applyValue/100f))); //造成傷害
}
}
14.5 羣體技能
- 按下技能鍵
- 修改鼠標爲技能鎖定圖標
- 點擊一個位置
- 設置狀態爲施法,此時無法移動
- 播放特效並計時
- 計時結束改變狀態並播放動畫
- 判斷技能接觸單位(運用collider)
- 造成傷害
IEnumerator SkillAttackMultiTarget()
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hitInfo;
bool isCollider = Physics.Raycast(ray,out hitInfo);
if(isCollider) //只要發生碰撞即可
{
state = PlayerState.skillAttack;
animation.CrossFade (info.aniName);
yield return new WaitForSeconds(info.aniTime);
GameObject prefab = null;
effectDict.TryGetValue (info.effectName, out prefab);
GameObject.Instantiate (prefab, hitInfo.point + Vector3.up, Quaternion.identity); //用hitInfo.point代替hitInfo.collider.transform.position
//todo:範圍內敵人受傷效果
}
else
{
state = PlayerState.normalAttack;
}
MouseSetting._instance.SetNormalCursor ();
}
public class MagicSphere : MonoBehaviour {
public int attack = 0;
private List<WolfBaby>wolfList = new List<WolfBaby> (); //通過List判斷當前野怪是否被攻擊
public void OnTriggerEnter(Collider col)
{
if(col.tag == Tags.enemy)
{
WolfBaby baby = col.GetComponent<WolfBaby>();
int index = wolfList.IndexOf(baby);
if(index == -1) //若還未被攻擊,造成傷害,並添加到wolfList之中
{
baby.BeDamaged(attack);
wolfList.Add(baby);
}
}
}
}
GameObject go = GameObject.Instantiate (prefab, hitInfo.point + Vector3.up * 0.5f, Quaternion.identity) as GameObject; 創建技能
go.GetComponent<MagicSphere>().attack = GetAttack() * (info.applyValue/100f); //賦值給attack屬性