unity技能系统
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了unity技能系统,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含11525字,纯文字阅读大概需要17分钟。
内容图文
unity技能系统
类类型概览
-
CharacterSkillManager 角色技能管理器 挂载在角色 持有SkillData与释放器 通过释放器进行技能释放
-
SkillDeployer 技能释放器基类 持有选取类型与影响效果两个接口 抽象函数释放方式
-
SkillData 技能数据类 保存技能基本信息、攻击基本信息、影响效果、选择类型等
-
IImpactEffects 影响效果接口 持有效果执行方法Execute(SkillDeployer deployer)
-
IAttackSelector 选区算法接口 持有选区算法 SelectTarget(SkillData data)
-
DeployerConfigFactory 释放器算法工厂返回具体类方法
-
Enum SkillAttackType 攻击类型 群体/单体
-
Enum SelectorType 选择类型 扇形/矩形
-
MeleeSkillDeployer 近战释放器 继承自 SkillDeployer
-
CostSPImpact 消耗法力值 实现IImpactEffects接口
-
HurtHPImpact 伤害生命
-
AddSPImapact 增加蓝耗
具体思路
- 将技能拆分为 数据(伤害,范围) 效果 (浮空,减速) 根据数据不同例如 范围、持续时间等 根据不同效果构建不同效果 例如: 英雄联盟中 艾希的W 技能与E技能 前者向前方一定扇形的敌人造成伤害与减速 两个效果 ,后者 向释放方向发射弹体 对沿途进行视野暴露一个效果 。
- 拿到相应技能该像哪里释放,如何获得效果对象,我们需要一个替我们处理技能释放的对象 去处理技能从初始化到释放的过程。 SkillDeployer 持有 技能数据、影响效果接口与选区算法接口 ,在具体创建时通过释放器工厂拿到相应具体实现。
代码具体流程
- 技能管理器持有技能数据 与唯一选择器 检测到相应输入 通过唯一ID获取技能数据 根据技能数据 例如蓝耗 判断是否能够释放 达到释放条件后 创建选择器
- 选择器根据传入技能数据 影响效果 通过工厂 拿到具体方法 进行释放
效果
实现
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//人物状态
public class CharacterStateData : MonoBehaviour
{
public float HP = 100;
public float SP = 100;
public float BeAttack = 10;//攻击力
void Start()
{
}
void Update()
{
}
}
using System.Collections;
using System.Collections.Generic;
using TestSkillSystem;
using UnityEngine;
using Debug = UnityEngine.Debug;
//技能管理器
public class CharacterSkillManager : MonoBehaviour
{
private Transform m_Transform;
private CharacterStateData m_PlayerData;
private SkillData m_NowSKill;
//技能列表
public List<SkillData> Skills;
private SkillDeployer m_Deployer;
private void Awake()
{
m_Transform = GetComponent<Transform>();
m_PlayerData = GetComponent<CharacterStateData>();
m_Deployer = GetComponent<SkillDeployer>();
}
private void Start()
{
for (int i = 0; i < Skills.Count; i++)
{
InitSkill(Skills[i]);
}
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.Q))
{
useSkill();
}
}
private void useSkill()
{
m_NowSKill = PrepareSkill(1001);
if (m_NowSKill == null)
{
return;
}
GenerateSkill(m_NowSKill);
}
/// <summary>
/// 生成技能
/// </summary>
public void GenerateSkill(SkillData data)
{
GameObject skill = Instantiate(data.skillPrefab, m_Transform.position, m_Transform.rotation);
SkillDeployer skillDeployer = skill.GetComponent<SkillDeployer>();
skillDeployer.skillData = data;
skillDeployer.DeploySkill();
//定时销毁
Destroy(skill, data.durationTime);
//开启cd
StartCoroutine(CoolTimeDown(data));
}
/// <summary>
/// 准备释放技能
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public SkillData PrepareSkill(int id)
{
SkillData data = Skills.Find(a => a.id == id);
if (data != null && data.coolRemain <= 0 && m_PlayerData.SP >= data.costSp)
{
return data;
}
Debug.Log("当前技能无法释放");
return null;
}
/// <summary>
/// 初始化技能
/// </summary>
/// <param name="data"></param>
private void InitSkill(SkillData data)
{
data.skillPrefab = SkillResManager.Load<GameObject>(data.prefabName);
data.owner = gameObject;
}
/// <summary>
/// 技能冷却
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
private IEnumerator CoolTimeDown(SkillData data)
{
data.coolRemain = data.coolTime;
while (data.coolRemain > 0)
{
yield return new WaitForSeconds(1);
data.coolRemain--;
}
Debug.Log("技能CD完毕over");
}
}
using System;
using System.Collections.Generic;
using UnityEngine;
namespace TestSkillSystem
{
/// <summary>
/// 技能释放器
/// </summary>
public abstract class SkillDeployer : MonoBehaviour
{
private SkillData m_SkillData;
public SkillData skillData
{
get { return m_SkillData; }
set
{
m_SkillData = value;
InitDeployer();
}
}
private IAttackSelector m_Selector;
private List<IImpactEffects> m_Effects;
private void InitDeployer()
{
m_Effects=new List<IImpactEffects>();
//选取类型
m_Selector = DeployerConfigFactory.CreateAttackSelector(skillData);
//影响效果
m_Effects = DeployerConfigFactory.CreateImpactEffects(skillData);
//Debug.Log("go");
}
//执行算法对象
//选区
public void CalculateTargets()
{
skillData.attackTargets = m_Selector.SelectTarget(skillData, transform);
}
//执行影响效果
public void ImpactTargets()
{
for (int i = 0; i < m_Effects.Count; ++i)
{
m_Effects[i].Execute(this);
}
}
//释放方式
//技能管理器调用,有子类实现,定义具体释放策略
public abstract void DeploySkill();
}
}
using System;
using System.Collections.Generic;
using UnityEngine;
namespace TestSkillSystem
{
/// <summary>
/// 攻击类型 群体/单体
/// </summary>
public enum SkillAttackType
{
Group,
Alone
}
/// <summary>
/// 选择类型 扇形/矩形
/// </summary>
public enum SelectorType
{
Sector,
Rectangle
}
//技能数据
[Serializable]
public class SkillData
{
/// <summary>技能ID</summary>
public int id;
/// <summary>技能名称</summary>
public string name;
/// <summary>技能描述</summary>
public string description;
/// <summary>冷却时间</summary>
public float coolTime;
/// <summary>冷却剩余时间</summary>
public float coolRemain;
/// <summary>魔法消耗</summary>
public float costSp;
/// <summary>攻击距离</summary>
public float attackDistance;
/// <summary>攻击角度</summary>
public float attackAngle;
/// <summary>攻击目标Tags</summary>
public List<string> attackTargetTags ;
/// <summary>攻击目标对象(数组)</summary>
public List<Transform> attackTargets;
[Tooltip("技能影响类型")]
/// <summary>技能影响类型</summary>
public List<string> impactype ;
/// <summary>连击的下一个技能ID</summary>
public int nextBatterid;
/// <summary>伤害比率</summary>
public float atkRatio;
/// <summary>持续时间</summary>
public float durationTime;
/// <summary>伤害间隔</summary>
public float atkInterval;
/// <summary>技能所属对象(OBJ)</summary>
[HideInInspector] public GameObject owner;
/// <summary>技能预制件名称</summary>
public string prefabName;
/// <summary>技能预制件对象</summary>
[HideInInspector] public GameObject skillPrefab;
/// <summary>动画名称</summary>
public string aniamtorName;
/// <summary>受击特效名称</summary>
public string hitFxName;
/// <summary>受击特效预制件</summary>
[HideInInspector] public GameObject hitFxPrefab;
/// <summary>技能等级</summary>
public int level;
/// <summary>攻击类型</summary>
public SkillAttackType attackType;
/// <summary>选择类型 扇形/矩形</summary>
public SelectorType selectorType;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace TestSkillSystem
{
//选区接口
public interface IAttackSelector
{
/// <summary>
/// 搜索目标
/// </summary>
/// <param name="data"></param>
/// <param name="skillTF"></param>
/// <returns></returns>
List<Transform> SelectTarget(SkillData data, Transform skillTF);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace TestSkillSystem
{
//影响效果接口
public interface IImpactEffects
{
//执行
void Execute(SkillDeployer deployer);
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
namespace TestSkillSystem
{
//算法工厂
public static class DeployerConfigFactory
{
//命名规则 TestSkillSystem + 枚举名 +AttackSelector
//例如扇形: TestSkillSystem
/// <summary>
/// 创建选区算法
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public static IAttackSelector CreateAttackSelector(SkillData data)
{
string name = $"TestSkillSystem.{data.selectorType}AttackSelector";
// Debug.Log(name);
return CreateObject<IAttackSelector>(name);
}
//影响效果命名规范
//同上 TestSkillSystem. + impactype[?] +Impact
/// <summary>
/// 创建影响算法
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public static List<IImpactEffects> CreateImpactEffects(SkillData data)
{
List<IImpactEffects> temp= new List<IImpactEffects>();
for (int i = 0; i < data .impactype.Count; ++i)
{
string className = $"TestSkillSystem.{data.impactype[i]}Impact";
//Debug.Log(className);
temp.Add( CreateObject<IImpactEffects>(className));
}
return temp;
}
private static T CreateObject<T>(string className) where T : class
{
Type type = Type.GetType(className);
if (type == null)
{
Debug.Log($"Type为空ClssName为:{className} ");
}
return Activator.CreateInstance(type) as T;
}
}
}
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace TestSkillSystem
{
public class SectorAttackSelector : IAttackSelector
{
/// <summary>
/// 扇形/圆形选区
/// </summary>
/// <param name="data"></param>
/// <param name="skillTF">技能所在位置</param>
/// <returns></returns>
public List<Transform> SelectTarget(SkillData data, Transform skillTF)
{
//获取目标
List<string> tags = data.attackTargetTags;
List<Transform> resTrans = new List<Transform>();
for (int i = 0; i < tags.Count; ++i)
{
GameObject[] tempGOArray = GameObject.FindGameObjectsWithTag(tags[i]);
if (tempGOArray.Length == 0)
{
Debug.Log("标签数组为空");
}
foreach (var VARIABLE in tempGOArray)
{
resTrans.Add(VARIABLE.transform);
}
}
//判断攻击范围
resTrans.FindAll(res => Vector3.Distance(res.position, skillTF.position) <= data.attackDistance
&& Vector3.Angle(skillTF.forward,res.position-skillTF.position)<=data.attackAngle/2);
//筛选出活得角色
resTrans.FindAll(res => res.GetComponent<CharacterStateData>().HP > 0);
//返回目标
//依据 单体/群体
if (data.attackType == SkillAttackType.Group||resTrans.Count==0 )
return resTrans;
//huoqu 距离最近的
int index = 0;
float min = Vector3.Distance(resTrans[0].position, skillTF.position);
for (int i=0;i<resTrans.Count;++i)
{
float temp = Vector3.Distance(resTrans[i].position, skillTF.position);
if (temp < min)
{
min = temp;
index = i;
}
}
return new List<Transform> {resTrans[index]};
}
}
}
using System.Collections.Generic;
using UnityEngine;
namespace TestSkillSystem
{
//具体影响效果
public class CostSPImpact: IImpactEffects
{
public void Execute(SkillDeployer deployer)
{
Debug.Log($"消耗法力值执行:{deployer.skillData.owner.name}");
var staus = deployer.skillData.owner.GetComponent<CharacterStateData>();
if(staus==null)
Debug.Log("状态为空");
staus.SP -= deployer.skillData.costSp;
}
}
public class HurtHPImpact : IImpactEffects
{
public void Execute(SkillDeployer deployer)
{
Debug.Log($"伤害生命执行:{deployer.skillData.owner.name}");
List<Transform> Temp = deployer.skillData.attackTargets;
for (int i = 0; i < Temp.Count; ++i)
{
Debug.Log($"{Temp[i].gameObject.name} hp执行前: {Temp[i].GetComponent<CharacterStateData>().HP}");
Temp[i].GetComponent<CharacterStateData>().HP-=deployer.skillData.owner.GetComponent<CharacterStateData>().BeAttack;
Debug.Log($"{Temp[i].gameObject.name} hp施行后: {Temp[i].GetComponent<CharacterStateData>().HP}");
}
}
}
public class AddSPImpact : IImpactEffects
{
public void Execute(SkillDeployer deployer)
{
Debug.Log($"回复法力值执行:{deployer.skillData.owner.name}");
var staus = deployer.skillData.owner.GetComponent<CharacterStateData>();
if(null==staus)
Debug.Log("状态为空");
staus.SP += deployer.skillData.owner.GetComponent<CharacterStateData>().BeAttack*0.5f;
}
}
}
using UnityEngine;
namespace TestSkillSystem
{
//近战释放器 测试
public class MeleeSkillDeployer: SkillDeployer
{
public override void DeploySkill()
{
//执行选区算法
CalculateTargets();
//执行影响算法
ImpactTargets();
//其他策略
skillData.owner.transform.position=new Vector3(skillData.owner.transform.position.x+1,skillData.owner.transform.position.y,skillData.owner.transform.position.z);
}
}
}
内容总结
以上是互联网集市为您收集整理的unity技能系统全部内容,希望文章能够帮你解决unity技能系统所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。