Menu

关于BOSSAI的实现,技能框架的实现

2018年6月24日 - 游戏开发

skill接口的设计:

ISkil ISkillLongDistanceable ISkillHoldable 接口的设计

using Entity;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Skill
{
internal interface ISkillHoldable : ISkill
{
void OnHoldEnter(EntityBase self, Animator ani);
void OnHold(EntityBase self, Animator ani);
void OnHoldExit(EntityBase self, Animator ani);

}
}

using Entity;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Skill
{
internal interface ISkill
{
/// <summary>
/// AnimationName与Animation节点名保存一致
/// </summary>

string[] AnimationNames { get; }
float CoolingTime { get; }
int Level { get; }
int Hit { get; }

void OnReset(Animator ani);
void OnUse(EntityBase self, Animator ani);
void OnHit(EntityBase self, EntityBase target);

}
}

 

using Entity;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Bullet;

namespace Skill
{
internal interface ISkillLongDistanceable
{
float GetInitialVelocity();

/// <summary>
/// 子弹碰到怪物时被调用
/// </summary>
/// <param name=”bullet”></param>
/// <param name=”target”></param>
void OnBulletHit(BulletBase bullet,EntityBase self,EntityBase target);
}
}

 

 

SkillBase

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Entity;
using System;
using Skill.Formula;

namespace Skill
{
internal abstract class SkillBase : ISkill
{
private string[] m_animation_names;
/// <summary>
/// 动画名称
/// </summary>
public string[] AnimationNames {
get { return m_animation_names; }
protected set { m_animation_names = value; }
}

private float m_coolint_time = 0.0f;
/// <summary>
/// 技能冷却时间
/// </summary>
public float CoolingTime {
get { return m_coolint_time; }
protected set { m_coolint_time = value; }
}
/// <summary>
/// 打击感
/// </summary>
private int m_hit=1;
public int Hit {
get { return m_hit; }
protected set { m_hit = value; }
}

private int m_level = 1;
public int Level {
get { return m_level; }
protected set { m_level = value; }
}

private IFormula m_formula;
/// <summary>
/// 技能公式
/// </summary>
/// <param name=”formula”></param>
public void SetFormula(IFormula formula)
{
m_formula = formula;
}
/// <summary>
///
/// </summary>
/// <param name=”self”></param>
/// <param name=”target”></param>
protected void ApplyFormula(EntityBase self, EntityBase target)
{
int h=m_formula.TakeDamge(self, target, this);
int s=m_formula.CostShield(self, target, this);
target.TakeDamage(h);
target.CostShield(s);
}

public virtual void OnHit(EntityBase self, EntityBase target) { throw new NotImplementedException(); }
public abstract void OnReset(Animator ani);
public abstract void OnUse(EntityBase self, Animator ani);
}
}

 

BossAI代码的实现:

using Game.Path;
using Skill.Context;
using Skill.Monster;
using Skill.Monster.BossQ01c;
using UnityEngine;
using System;

namespace Entity.Monster
{
internal class BossEnemy : MonsterBase
{
private SkillContext[] m_attContext=new SkillContext[2];
private SkillContext[] m_skillContext=new SkillContext[3];

[NonSerialized]
public AudioSource AudioSource;

public AudioClip StatusAStandSound, StatusBStandSound;

protected override void Awake()
{
AudioSource = GetComponent<AudioSource>();
AudioSource.clip = StatusAStandSound;
base.Awake();
}

protected override void Start()
{
m_attContext[0] = SkillManager.RegisterSkill<BossAtt01>();
m_attContext[1] = SkillManager.RegisterSkill<BossAtt02>();
m_skillContext[0] = SkillManager.RegisterSkill<BossSkill01>();
m_skillContext[1] = SkillManager.RegisterSkill<BossSkill02>();
m_skillContext[2] = SkillManager.RegisterSkill<BossSkill03>();

InitFSM();

base.Start();
}

private void InitFSM()
{
FSMState chaseState = new ChaseState(FSM, this.gameObject);
FSM.AddState(chaseState);
FSMState BossAttackState = new BossAttackState(FSM, this, m_attContext, m_skillContext);
FSM.AddState(BossAttackState);
chaseState.AddTransition(Transition.CanAttack, StateID.Attack);
BossAttackState.AddTransition(Transition.SeePlayer, StateID.Chase);
//BossAttackState.AddTransition(Transition.LostPlayer, StateID.Patrol);
}

private void ShakeCamera()
{
Camera.main.GetComponent<ShakeCamera>().shake();
}
}
}

 

using Entity;
using Entity.Monster;
using Other;
using Skill.Context;
using UnityEngine;

internal class BossAttackState : FSMState
{
private Status _status = Status.Attack;

private enum Status
{
Idle,
Attack,
skill_01,
skill_02,
}

private Vector3 tall = new Vector3(0, 2, 0);
private Transform playerTransform;
private Animator m_animator;
private CharacterController m_controller;
private MonsterBase m_entity;

private SkillContext[] m_att;
private SkillContext[] m_skill;

public BossAttackState(FSMSystem fsm, MonsterBase obj, SkillContext[] att, SkillContext[] skill) : base(fsm)
{
m_animator = obj.GetComponent<Animator>();
m_controller = obj.GetComponent<CharacterController>();
stateID = StateID.Attack;
playerTransform = GameObject.Find(“Player”).transform;
m_att = att;
m_skill = skill;
m_entity = obj;

obj.OnHealthPointChanged += (self,last,cur)=>
{
int n=self.MaxHealthPoint/10;
if (last == self.MaxHealthPoint) return;

int l = last / n;
int c=cur / n;
if (l != c)
{
if (c >= 3)
skill[1].Use();
else
skill[2].Use();
}
};
}

public override void DoBeforeEntering()
{
m_entity.Move(0);
m_animator.SetFloat(“speed”, 0.0f);
}

public override void Act(MonsterBase npc, Animator ani)
{
m_att[0].Reset();
m_att[1].Reset();
m_skill[0].Reset();

if (npc.SkillManager.GetActivateSkill() != null)return;

if (_status == Status.Attack)
{
float r = Random.Range(0, 100);
if (r < 60)
m_att[0].Use();
else if (r >= 60 && r < 80)
m_att[1].Use();
else if (r >= 80 && r < 90)
m_skill[0].Use();
//else if
}
}

public override void Reason(MonsterBase npc, Animator ani)
{
if (npc.SkillManager.GetActivateSkill() != null) return;
if (Vector3.Distance(playerTransform.position, npc.transform.position) > npc.CanAttackDistance)
{
m_att[0].Reset();
m_att[1].Reset();
m_skill[0].Reset();
fsm.PerformTransition(Transition.SeePlayer);
}
}
}

 

using System.Collections;
using System.Collections.Generic;
using Entity;
using UnityEngine;
using Skill;

namespace Skill.Monster.BossQ01c
{
class BossSkill01 : SkillBase
{

private static string[] s_animiation_names = new string[] {
“A_skill01_chg”,”A_skill01_act”,”A_skill01_bak”,
“B_skill01_chg”,”B_skill01_act”,”B_skill01_bak”
};//动画状态机中对应技能的动画名

public BossSkill01()
{
AnimationNames = s_animiation_names;
}

public override void OnHit(EntityBase self, EntityBase target)//击中目标时调用
{
ApplyFormula(self, target);
}

public override void OnReset(Animator ani)//重置动画状态机参数
{
ani.ResetTrigger(“skill01”);

}

public override void OnUse(EntityBase self, Animator ani)//设置动画状态机参数
{
ani.SetTrigger(“skill01”);
}
}
}

 

using System.Collections;
using System.Collections.Generic;
using Entity;
using UnityEngine;
using Skill;
using Entity.Monster;

namespace Skill.Monster.BossQ01c
{
class BossSkill02 : SkillBase
{

private static string[] s_animiation_names = new string[] {
“A_skill02_chg”,”A_skill02_act”,”A_skill02_bak”,
“B_skill02_chg”,”B_skill02_act”,”B_skill02_bak”
};//动画状态机中对应技能的动画名

public BossSkill02()
{
AnimationNames = s_animiation_names;
}

public override void OnHit(EntityBase self, EntityBase target)//击中目标时调用
{
ApplyFormula(self, target);
}

public override void OnReset(Animator ani)//重置动画状态机参数
{
ani.ResetTrigger(“SwitchStatus”);
}

public override void OnUse(EntityBase self, Animator ani)//设置动画状态机参数
{
ani.SetTrigger(“SwitchStatus”);
bool isb = ani.GetBool(“IsBStatus”);
ani.SetBool(“IsBStatus”,!isb);

var boss = (self as BossEnemy);
if (!isb)
boss.AudioSource.clip = boss.StatusBStandSound;
else
boss.AudioSource.clip = boss.StatusAStandSound;
boss.AudioSource.Play();
}
}
}

 

using System.Collections;
using System.Collections.Generic;
using Entity;
using UnityEngine;
using Skill;
using Entity.Monster;

namespace Skill.Monster.BossQ01c
{
class BossSkill03 : SkillBase
{

private static string[] s_animiation_names = new string[] {
“A_skill03”
};//动画状态机中对应技能的动画名

public BossSkill03()
{
AnimationNames = s_animiation_names;
}

public override void OnHit(EntityBase self, EntityBase target)//击中目标时调用
{
ApplyFormula(self, target);
}

public override void OnReset(Animator ani)//重置动画状态机参数
{
ani.ResetTrigger(“SwitchStatus”);
}

public override void OnUse(EntityBase self, Animator ani)//设置动画状态机参数
{
ani.SetTrigger(“SwitchStatus”);
ani.SetBool(“IsRage”, true);
ani.SetBool(“IsBStatus”,true);

var boss = (self as BossEnemy);
boss.AudioSource.clip = boss.StatusBStandSound;
boss.AudioSource.Play();
}
}
}

using Entity;
using Skill;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Skill.Monster.BossQ01c
{
class BossAtt01 : SkillBase
{
private static string[] s_animiation_names = new string[] {
“A_att01″,”B_att01”
};//动画状态机中对应技能的动画名

public BossAtt01()
{
AnimationNames = s_animiation_names;
}

public override void OnHit(EntityBase self, EntityBase target)//击中目标时调用
{
ApplyFormula(self, target);
}

public override void OnReset(Animator ani)
{
ani.ResetTrigger(“Attack_1”);
}

public override void OnUse(EntityBase self, Animator ani)
{
ani.SetTrigger(“Attack_1”);
}
}
}

 

using Entity;
using Skill;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Skill.Monster.BossQ01c
{
class BossAtt02 : SkillBase
{
private static string[] s_animiation_names = new string[] {
“A_att02″,”B_att02”
};//动画状态机中对应技能的动画名

public BossAtt02()
{
AnimationNames = s_animiation_names;
}

public override void OnHit(EntityBase self, EntityBase target)//击中目标时调用
{
ApplyFormula(self, target);
}

public override void OnReset(Animator ani)
{
ani.ResetTrigger(“Attack_2”);
}

public override void OnUse(EntityBase self, Animator ani)
{
ani.SetTrigger(“Attack_2”);
}
}
}

发表评论

电子邮件地址不会被公开。 必填项已用*标注

%d 博主赞过: