这篇,主要分析角色接收到技能释放的信号,执行技能释放的动作
1 角色的行为由状态机来划分,不同状态下,会执行不同操作,攻击敌人这一行为,是由等待状态-》发现目标状态-》攻击状态,
当达到目标附近后,切换成为攻击状态,接到攻击指令,执行攻击操作
public virtual void ActionAttack()
{
//进行健壮性判断
if (!this.enabled) return;
//进行逻辑判断,比如,停止走路
if (上次攻击没有结束) return;
//目标不存在,return
if (!TargetAlive(targetObj)) { TargetObjLost(); return; }
Vector3 targetDir = targetObj.transform.position - transform.position;
targetDir.y = 0;
transform.forward = Vector3.MoveTowards(transform.forward, targetDir.normalized, 0.5f);
//检测是否在技能施法范围中,
if (targetDir.magnitude < (gameRoleProperty.skillList[defaultSkillIndex].skillRange + gameRoleProperty.stepDistance + targetObj.GetComponent().stepDistance))
{
//判断 技能是否冷却完毕&&技能动作是否执行完毕&&上次攻击是否结束
if (roleProperty.skillList[skillIndex].skillTimeCount < 0.01f &&roleProperty.skillList[skillIndex].skillColdTimeCount < 0.01f && roleAnimator.attackEnd)
{
//进行技能执行时间的协程,在技能动作进行过程中,不会执行攻击操作
StartCoroutine(RestAffterAtaction(gameRoleProperty.skillList[skillIndex].skillColdTime));
//
roleAnimator.PlayAttack(roleProperty.skillList[skillIndex], skillIndex, targetObj);
//处理其他逻辑处理
return;
}
}
else //如果技能都不能释放,则说明不在攻击范围内,变成锁定目标状态
{
sta = GameRoleStaus.Target;
}
}
public virtual void PlayAttack(SkillProperty skillproperty, int skillIndex, GameObject targetobj)
{
//攻击没有结束,返回
if (!attackEnd) return;
//目标的赋值
targetObj = targetobj;
StartCoroutine(AttackBullteNormal(skillproperty, skillIndex, skillTargets));
}
/// 攻击特效
IEnumerator AttackBullteNormal(SkillProperty skillproperty, int skillIndex, List targetObjbullet)
{
attackEnd = false;
playSkillIndex = skillIndex;//记录下技能的索引,用来判断当前技能是普攻还是技能
//面向目标
Face2Target();
//这里怪物的攻击和角色的攻击表现形式有差别,这里作区分
if (tag == "Monster")
{
FXRoleBehitShine fxtemp = gameObject.GetComponent();
if (fxtemp != null)
{
fxtemp.Resum(Color.red, 0.5f);
}
else
{
fxtemp = gameObject.AddComponent();
fxtemp.Initialize(Color.red, 0.5f);
}
}
//根据技能index不同,播放不同的攻击动画
if (skillproperty.attackActionIndex <6 )//如果是普攻
{
ani.CrossFade("attack" + skillproperty.attackActionIndex, 0.01f, 0, 0);
}
AnimatorStateInfo aniInfo = ani.GetCurrentAnimatorStateInfo(0);
while (!aniInfo.IsName("attack" + skillproperty.attackActionIndex))
{
aniInfo = ani.GetCurrentAnimatorStateInfo(0);
yield return null;
}
//创建技能的开始的特效
CreateSkillEffect(skillproperty, skillIndex, targetObjbullet);
//开始技能冷却逻辑处理
skillproperty.BeginColdDown(aniInfo.normalizedTime);
//多段攻击处理
int damageIndex = 0;
while (aniInfo.normalizedTime < 1)
{
//当攻击阶段index超出
if (damageIndex >= skillproperty.damageList.Count) {
aniInfo = ani.GetCurrentAnimatorStateInfo(0);
if (!aniInfo.IsName("attack" + skillproperty.attackActionIndex)) break;
yield return null;
continue;
}
aniInfo = ani.GetCurrentAnimatorStateInfo(0);
//动作播放到一个时刻,处理攻击
if (skillproperty.damageList[damageIndex].damageTime <= aniInfo.normalizedTime)
{
//生成子弹,发射!
CreateDamageBullte(skillproperty, skillIndex, damageIndex, targetObjbullet);
damageIndex++;
}
yield return null;
}
//攻击结束
attackEnd = true;
ai.AttackEnd();
ani.Play("idle");
}
//生成子弹
private void CreateDamageBullte(SkillProperty skillproperty, int skillIndex, int damageIndex, List targetObjList)
{
//需要技能范围中的攻击目标
skillTargets = GetSkillTarget(skillproperty, skillIndex, targetObj);
if (skillproperty.damageList[damageIndex].damageBullet.objInstance == null) return;
//生成特效B阶段(在角色和敌人中间飞行的特效,如果是近距离攻击,就没有喽)
GameObject tempo = Instantiate(skillproperty.damageList[damageIndex].damageBullet.objInstance) as GameObject;
tempo.SetActive(true);
//使子弹附着到施法目标
tempo.SendMessage("AttachBodyPart", gameObject, SendMessageOptions.DontRequireReceiver);
FXAttachRoleBodyPart[] fs = tempo.GetComponentsInChildren();
foreach (FXAttachRoleBodyPart f1 in fs)
{
if (f1.attachToTarget)//如果是加到敌人的位置
{
//有一个问题,如果是禁锢技能,技能B阶段直接绑在目标(们)上,从而直接判断攻击到了,做C阶段的处理
}
else f1.AttachBodyPart(gameObject);///加到玩家的某部位
}
//控制特效prefab的脚本 从B阶段到C阶段 逻辑处理就是靠这个脚本,
//想要不同的处理,可以做成基类,写个初始化的方法,通过继承基类,在update中作出不同的处理,可以达到不同的效果(自己的想法)
if (tempo.GetComponent() == null) tempo.AddComponent();
tempo.GetComponent().initialize(targetObjList, this, skillIndex, damageIndex, skillproperty);
Destroy(tempo, 15f);
}
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class AttackBullteS : MonoBehaviour {
//
public float speed = 0.1f;
public bool multiTarget = false;
public GameObject ecFXObj;
public List targetObj;
public GameRoleAnimator bullteOwner;
private GameRoleAnimator targetAnimator;
Transform targetPart;
public int skillIndex, damageIndex;
public SkillProperty skillData;
public List buff = null;//攻击附带buff
public int bullteNature = 0;
void Start () {
}
public void initialize(List targetobj, GameRoleAnimator bullteowner, int skillindex, int damageindex,SkillProperty skilldata )
{
targetObj = targetobj;
bullteOwner = bullteowner;
skillIndex = skillindex;
damageIndex = damageindex;
skillData = skilldata;
if (skillData.damageList[damageindex].ecFX != null) ecFXObj = skillData.damageList[damageindex].ecFX.objInstance;
buff = skillData.damageList[damageindex].buff;
if (targetobj.Count == 0) { targetPart = null; transform.forward = bullteowner.transform.forward; return; }
if (targetobj[0] == null) { targetPart = null; transform.forward = bullteowner.transform.forward; return; }
targetAnimator = targetobj[0].GetComponent();
if (targetAnimator != null)
{
if (targetAnimator.bodyPart != null)
{
if (targetAnimator.bodyPart.bodypartBody != null) targetPart = targetAnimator.bodyPart.bodypartBody.transform;
}
}
//C阶段特效出现的部位在身体上
if (targetPart == null)
{
RoleBodyPart body1 = targetObj[0].GetComponent();
if (body1 != null) targetPart = body1.bodypartBody.transform;
else targetPart = targetObj[0].transform;
}
}
void Update()
{
if (targetPart == null) {
transform.position += transform.forward * speed * Time.deltaTime * 60;
if ((transform.position - bullteOwner.transform.position).magnitude > skillData.skillRange)
{
BullteExplode(true);
if (ecFXObj != null)
{
GameObject tempo = Instantiate(ecFXObj, transform.position, transform.rotation) as GameObject;
Destroy(tempo, 2);
}
else
{
GameObject tempo = Instantiate(SAOResources.SAOFXObj("FX_EC_ci" + Random.Range(0, 3)), transform.position, transform.rotation) as GameObject;
Destroy(tempo, 2);
}
}
return;
}
//让子弹朝物体移动
Vector3 tempdir = targetPart.position - transform.position ;
transform.forward = tempdir.normalized;
//到达攻击位置
if (tempdir.magnitude < speed * Time.deltaTime * 60) BullteExplode(true);
transform.position += tempdir.normalized * speed * Time.deltaTime * 60;
}
public void BullteExplode(bool isend)
{
//创建C阶段特效
for (int i = 0; i < targetObj.Count; i++)
{
//通知被攻击的目标 执行BeHit方法
if (targetObj[i] != null) targetObj[i].SendMessage("BeHit", this, SendMessageOptions.DontRequireReceiver);
if (targetPart != null) transform.position = targetPart.position;
if (ecFXObj != null)
{
//生成特效
GameObject tempo = Instantiate(ecFXObj,transform.position,transform.rotation) as GameObject;
Destroy(tempo, 2);
tempo.transform.rotation = Quaternion.identity;
FXAttachRoleBodyPart[] fs = tempo.GetComponentsInChildren(true);
foreach (FXAttachRoleBodyPart f1 in fs) f1.AttachBodyPart(targetObj[i].gameObject);
}
else
{
GameObject tempo = Instantiate( SAOResources.SAOFXObj("FX_EC_ci" + Random.Range(0, 3)),transform.position,transform.rotation)as GameObject;// Instantiate(ecFXObj, transform.position, transform.rotation) as GameObject;
Destroy(tempo, 2);
}
}
if (particleSystem != null) particleSystem.Play();
//销毁子弹
if (isend)
{
if (renderer != null) renderer.enabled = false;
Destroy(gameObject, 0.1f);
this.enabled = false;
}
}
}
技能从释放到攻击到目标,流程走完了。