技术标签: Unity
CharacterSkillManager 角色技能管理器 挂载在角色 持有SkillData与释放器 通过释放器进行技能释放
SkillDeployer 技能释放器基类 持有选取类型与影响效果两个接口 抽象函数释放方式
SkillData 技能数据类 保存技能基本信息、攻击基本信息、影响效果、选择类型等
IImpactEffects 影响效果接口 持有效果执行方法Execute(SkillDeployer deployer)
IAttackSelector 选区算法接口 持有选区算法 SelectTarget(SkillData data)
DeployerConfigFactory 释放器算法工厂返回具体类方法
Enum SkillAttackType 攻击类型 群体/单体
Enum SelectorType 选择类型 扇形/矩形
MeleeSkillDeployer 近战释放器 继承自 SkillDeployer
CostSPImpact 消耗法力值 实现IImpactEffects接口
HurtHPImpact 伤害生命
AddSPImapact 增加蓝耗
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);
}
}
}
文章浏览阅读2.5w次,点赞6次,收藏50次。官方解释是,docker 容器是机器上的沙盒进程,它与主机上的所有其他进程隔离。所以容器只是操作系统中被隔离开来的一个进程,所谓的容器化,其实也只是对操作系统进行欺骗的一种语法糖。_docker菜鸟教程
文章浏览阅读5.7k次,点赞3次,收藏14次。该如何避免的,今天小编给大家推荐两个下载Windows系统官方软件的资源网站,可以杜绝软件捆绑等行为。该站提供了丰富的Windows官方技术资源,比较重要的有MSDN技术资源文档库、官方工具和资源、应用程序、开发人员工具(Visual Studio 、SQLServer等等)、系统镜像、设计人员工具等。总的来说,这两个都是非常优秀的Windows系统镜像资源站,提供了丰富的Windows系统镜像资源,并且保证了资源的纯净和安全性,有需要的朋友可以去了解一下。这个非常实用的资源网站的创建者是国内的一个网友。_msdn我告诉你
文章浏览阅读1.2k次。vue2封装对话框el-dialog组件_
文章浏览阅读4.7k次,点赞5次,收藏6次。MFC 文本框换行 标签: it mfc 文本框1.将Multiline属性设置为True2.换行是使用"\r\n" (宽字符串为L"\r\n")3.如果需要编辑并且按Enter键换行,还要将 Want Return 设置为 True4.如果需要垂直滚动条的话将Vertical Scroll属性设置为True,需要水平滚动条的话将Horizontal Scroll属性设_c++ mfc同一框内输入二行怎么换行
文章浏览阅读832次。检查Linux是否是否开启所需端口,默认为6379,若未打开,将其开启:以root用户执行iptables -I INPUT -p tcp --dport 6379 -j ACCEPT如果还是未能解决,修改redis.conf,修改主机地址:bind 192.168.85.**;然后使用该配置文件,重新启动Redis服务./redis-server redis.conf..._redis-server doesn't support auth command or ismisconfigured. try
文章浏览阅读4.9k次。济大数电实验报告_数据选择器及其应用
文章浏览阅读236次。1研究内容消费在生产中占据十分重要的地位,是生产的最终目的和动力,是保持省内经济稳定快速发展的核心要素。预测河南省社会消费品零售总额,是进行宏观经济调控和消费体制改变创新的基础,是河南省内人民对美好的全面和谐社会的追求的要求,保持河南省经济稳定和可持续发展具有重要意义。本文建立灰色预测模型,利用MATLAB软件,预测出2019年~2023年河南省社会消费品零售总额预测值分别为21881...._灰色预测模型用什么软件
文章浏览阅读1.2k次。12.4-在Qt中使用Log4Qt输出Log文件,看这一篇就足够了一、为啥要使用第三方Log库,而不用平台自带的Log库二、Log4j系列库的功能介绍与基本概念三、Log4Qt库的基本介绍四、将Log4qt组装成为一个单独模块五、使用配置文件的方式配置Log4Qt六、使用代码的方式配置Log4Qt七、在Qt工程中引入Log4Qt库模块的方法八、获取示例中的源代码一、为啥要使用第三方Log库,而不用平台自带的Log库首先要说明的是,在平时开发和调试中开发平台自带的“打印输出”已经足够了。但_log4qt
文章浏览阅读786次。全局观思维模型,一个教我们由点到线,由线到面,再由面到体,不断的放大格局去思考问题的思维模型。_计算机中对于全局观的
文章浏览阅读330次。一、CountDownLatch介绍CountDownLatch采用减法计算;是一个同步辅助工具类和CyclicBarrier类功能类似,允许一个或多个线程等待,直到在其他线程中执行的一组操作完成。二、CountDownLatch俩种应用场景: 场景一:所有线程在等待开始信号(startSignal.await()),主流程发出开始信号通知,既执行startSignal.countDown()方法后;所有线程才开始执行;每个线程执行完发出做完信号,既执行do..._countdownluach于cyclicbarrier的用法
文章浏览阅读508次。Prometheus 算是一个全能型选手,原生支持容器监控,当然监控传统应用也不是吃干饭的,所以就是容器和非容器他都支持,所有的监控系统都具备这个流程,_-自动化监控系统prometheus&grafana实战
文章浏览阅读4.7k次。输入关键字,可以通过键盘的搜索按钮完成搜索功能。_react search