Unity技能系统(三)

Unity技能系统(一)

Unity技能系统(二)

Demo展示

六.Buff系统

buff分为增益和减益buff,应该区分开来;

/// <summary>
/// Buff类型,可叠加
/// </summary>
public enum BuffType
{
None,
Burn = 2, //点燃
Slow = 4, //减速
Light = 8, //感电
Stun = 16, //眩晕
Poison = 32, //中毒
BeatBack = 64, //击退
BeatUp = 128, //击飞
Pull = 256, //拉拽
AddDefence = 512,
RecoverHp = 1024,
}

本来计划是也用与或非来记录buff的,一个技能可能有多个buff,但是好像用list来存储也是一样的;

一个技能只能有两个buff图标,一个增益buff给自身,一个减益buff给敌人;

一个技能的增益和减益buff可能有多重效果;

比如:技能闪电——导致减速+感电+击退+自身增加狂暴(变态技能);

但是说这么说,写起来比较麻烦,就不那么细分了,一种效果一个图标单独计时;

这里面需求比较复杂,根据需求自行改写吧;

1.BuffRun

挂载在拥有buff的物体上,计算buff的效果,如减伤,掉血,减速等;

同时负责buff计时,提供buff计时刷新接口供重复buffIcon调用(也可叠加buff层数按需求);

使用了静态方法初始化和静态链表存储了buff特效的信息,用来动态加载buff特效预制体;

public class BuffRun : MonoBehaviour
{
private float durationTime;
public BuffType bufftype;
private float value; //伤害或者加成 private float interval; private float attackTimer; private float curTime; private CharacterStatus target; //添加buff时候初始化buffrun
public void InitBuff(BuffType buffType,float duration,float value,float interval)
{
bufftype = buffType; if (buffType == BuffType.BeatBack || buffType == BuffType.BeatUp || buffType == BuffType.Pull)
duration = 2f; durationTime = duration;
this.value = value;
this.interval = interval;
curTime = 0;
} //重置buff时间
public void Reset()
{
attackTimer = 0;
curTime = 0;
} void Start()
{
curTime = 0;
target = GetComponent<CharacterStatus>();
StartCoroutine(ExcuteDamage());
} private void Update()
{
curTime += Time.deltaTime; if(curTime > durationTime)
Destroy(this);
} //执行buff效果,支持多段影响
private IEnumerator ExcuteDamage()
{
attackTimer = 0; //已持续攻击的时间 do
{
//对敌人的影响
TargetImpact(); yield return new WaitForSeconds(interval);
attackTimer += interval;
//做伤害数值的计算
} while (durationTime > attackTimer); Destroy(this);
} private void TargetImpact()
{
//buff特效挂载点,有些buff挂载不在HitFxPos,所以写在上面
Transform fxPosTf = target.HitFxPos; //根据不同buff做相应的效果响应
if (bufftype == BuffType.Burn || bufftype == BuffType.Poison || bufftype == BuffType.Light)
target.OnDamage(value, gameObject, true);
else if (bufftype == BuffType.Slow)//减速
fxPosTf = target.transform;
else if (bufftype == BuffType.BeatBack)
{
Vector3 dir = -target.transform.position + GameObject.FindGameObjectWithTag("Player").transform.position;
dir.y = 0;
target.transform.DOMove(target.transform.position - dir.normalized * value,0.5f);
durationTime = 2f;
}
else if (bufftype == BuffType.BeatUp)
{
target.transform.DOMove(target.transform.position - Vector3.up * value,0.5f);
durationTime = 2f;
}
else if (bufftype == BuffType.AddDefence)
{
fxPosTf = target.transform;
target.defence += value;
}
else if (bufftype == BuffType.RecoverHp)
{
target.OnDamage(-value, gameObject, true);
} //挂载buff特效
if (buffFx.ContainsKey(bufftype))
{
GameObject go = Resources.Load<GameObject>($"Skill/{buffFx[bufftype]}");
GameObject buffGo = GameObjectPool.I.CreateObject(buffFx[bufftype], go, fxPosTf.position, fxPosTf.rotation);
buffGo.transform.SetParent(fxPosTf);
GameObjectPool.I.Destory(buffGo, interval);
}
} //存储buff特效名称和对应buff类型
private static Dictionary<BuffType, string> buffFx = new Dictionary<BuffType, string>();
//初始化buff特效信息
public static void InitAllBuff()
{
buffFx.Add(BuffType.Burn,"Skill_32_R_Fly_100");
buffFx.Add(BuffType.Light,"Skill_75_Cast");
buffFx.Add(BuffType.Slow,"Skill_21_R_Fly_100");
buffFx.Add(BuffType.Poison,"Skill_12_R_Fly_100");
buffFx.Add(BuffType.AddDefence,"FX_CHAR_Aura");
buffFx.Add(BuffType.RecoverHp,"FX_Heal_Light_Cast");
} //获取buff剩余时间接口
public float GetRemainTime()
{
return durationTime - curTime;
} //buff结束恢复目标属性
private void OnDisable()
{
if (bufftype == BuffType.Slow)
;
else if (bufftype == BuffType.AddDefence)
target.defence -= value;
}
}

2.BuffIcon

buff图标类,显示倒计时数字显示;

这里写的不是很好,应该加载buffrun的同时加载bufficon,bufficon中不需要单独计时;

暂时改不动了=-=;

bufficon中添加buffRun字段,添加bufficon的同时,赋值buffrun;

通过buffrun获取buff类型和剩余倒计时;

这也用静态方法存储了bufficon的信息,用来动态加载,可以通过外部导入数据来存储;

public static Dictionary<BuffType, string> buffIconName = new Dictionary<BuffType, string>();

public static void InitBuffIconName()
{
buffIconName.Add(BuffType.Burn,"Buff_13");
buffIconName.Add(BuffType.Slow,"Buff_15");
buffIconName.Add(BuffType.Stun,"Buff_12");
buffIconName.Add(BuffType.Poison,"Buff_14");
buffIconName.Add(BuffType.BeatBack,"Buff_5");
buffIconName.Add(BuffType.BeatUp,"Buff_4");
buffIconName.Add(BuffType.Pull,"Buff_6");
buffIconName.Add(BuffType.AddDefence,"Buff_3");
buffIconName.Add(BuffType.RecoverHp,"Buff_7");
buffIconName.Add(BuffType.Light,"Buff_8");
}

这里写的不太行,参考一下吧;

public class BuffIcon : MonoBehaviour
{
public Text textCD;
public Image imgIcon; private float durationTime;
private float curTime; public BuffType buffType; public void LoadIcon(BuffType buffType, float duration)
{
durationTime = duration;
this.buffType = buffType;
Sprite[] temp = Resources.LoadAll<Sprite>("BuffIcon/Buff");
if (temp != null)
{
foreach (var sp in temp)
{
if (sp.name == SkillDeployer.buffIconName[buffType])
{
imgIcon.sprite = Instantiate(sp);
}
}
}
} private void OnEnable()
{
curTime = 0;
} void Update()
{
curTime += Time.deltaTime; textCD.text = (durationTime - curTime).ToString("F0"); if (curTime > durationTime)
{
gameObject.SetActive(false);
curTime = 0;
}
} public void Refresh()
{
//Debug.Log("已有buff刷新持续时间");
curTime = 0;
}
}

3.坑点

1.敌人uiPortrait的UI尽量不用使用延迟设置Active来控制显隐藏,Active为false时,bufficon将不再运行,等下次再显示uiPortrait时buff图标会显示错误;

2.采用每次造成伤害将当前目标的uiPortrait调整到显示位置,其他所有敌人的uiPortrait调整位置超出显示区域;

因此需要一个单例来存储所有的uiPortrait;就将它写在MonsterMgr中吧,反正也是用来管理敌人的,顺便管理一下敌人头像也没什么毛病;

提供三个方法,添加uiPortrait,删除uiPortrait,隐藏uiPortrait(移除显示区域);

private List<UIPortrait> allEnemyPortraits = new List<UIPortrait>();
public void AddEnemyPortraits(UIPortrait uiPortrait)
{
allEnemyPortraits.Add(uiPortrait);
}
public void RemoveEnemyPortraits(UIPortrait uiPortrait)
{
allEnemyPortraits.Remove(uiPortrait);
}
public void HideAllEnemyPortraits()
{
foreach (var it in allEnemyPortraits)
{
it.GetComponent<RectTransform>().anchoredPosition = hidePos;
}
}

4.扇形倒计时

UIbuff图标放置两层image组件物体,父节点设置透明度;

子物体image组件按下图设置,填充模式,填充百分比,以及顺逆时针;

代码动态设置fillAmount的百分比;

//技能倒计时举例,写在Update中
float cd = csm.skills[i].coolRemain;
skillImgs[i].fillAmount = 1 - cd / csm.skills[i].skill.coolTime;
skillTexts[i].text = cd.ToString("F0");
if (skillTexts[i].text == "0")
skillTexts[i].text = "";

效果:

Unity——技能系统(三)的更多相关文章

  1. Unity——技能系统(二)

    Unity技能系统(二) Unity技能系统(一) Demo展示: 五.技能管理和释放 1.CharacterSkillSystem 技能系统类,给外部(技能按钮,按键)提供技能释放方法: 技能释放逻 ...

  2. Unity——技能系统(一)

    技能系统(一) 一.Demo展示 二.功能介绍 集成了技能,冷却,buff,UI显示,倒计时,动画等: 技能类型:弹道技能,动画事件根据帧数采用延迟调用技能,自定义释放位置(偏移,发射点两种),buf ...

  3. Unity——射线系统

    Unity射线系统 Demo展示 UI+Physical射线测试: FPS自定义射线测试: UGUI射线工具 实现功能,鼠标点击UI,返回鼠标点击的UI对象: 需要使用到鼠标点击事件-PointerE ...

  4. 一个MMORPG的常规技能系统

    广义的的说,和战斗结算相关的内容都算技能系统,包括技能信息管理.技能调用接口.技能目标查找.技能表现.技能结算.技能创生体(buff/法术场/弹道)管理,此外还涉及的模块包括:AI模块(技能调用者). ...

  5. UGUI的优点新UI系统三效率高效果好

    UGUI的优点新UI系统三效率高效果好 通过对批处理(batching).纹理图集(texture atlasing)和新的canvas组件的支持,新UI系统提供了一个经过优化的解决方案,使得开发者添 ...

  6. python基础----以面向对象的思想编写游戏技能系统

    1. 许多程序员对面向对象的思想都很了解,并且也能说得头头是道,但是在工作运用中却用的并不顺手. 当然,我也是其中之一. 不过最近我听了我们老师的讲课,对于面向对象的思想有了更深的理解,今天决定用一个 ...

  7. Unity常见的三种数据本地持久化方案

    做游戏的时候常常会有数据配置或者存读档的需求,本文整理了常用的几种解决方案,分别是Unity自带的PlayerPrefs类,XML文件和Json文件. 一. PlayerPrefs 这是Unity自带 ...

  8. 三维软件转Unity的系统单位设置研究

    Unity的系统单位为米,其他3D软件的模型导入,而保持和Unity的比例一致是非常重要的,下面对各软件进行测试: ㈠. 3dsmax 转 Unity的比例为100:1:也就是说Unity单位是3ds ...

  9. Ubuntu Linux系统三种方法添加本地软件库

    闲着没事教教大家以Ubuntu Linux系统三种方法添加本地软件库,ubuntu Linux使用本地软件包作为安装源——转2007-04-26 19:47新手重新系统的概率很高,每次重装系统后都要经 ...

随机推荐

  1. Java8通过Function获取字段名(获取实体类的字段名称)

    看似很鸡肋其实在某些特殊场景还是比较有用的.比如你将实体类转Map或者拿到一个Map结果的时候,你是怎么获取某个map的key和value.方法一:声明 String key1="name& ...

  2. kubelet源码分析——关闭Pod

    上一篇说到kublet如何启动一个pod,本篇讲述如何关闭一个Pod,引用一段来自官方文档介绍pod的生命周期的话 你使用 kubectl 工具手动删除某个特定的 Pod,而该 Pod 的体面终止限期 ...

  3. Spring源码阅读一

    引导: 众所周知,阅读spring源码最开始的就是去了解spring bean的生命周期:bean的生命周期是怎么样的呢,见图知意: 大致流程: 首先后通过BeanDefinitionReader读取 ...

  4. FastAPI(58)- 使用 OAuth2PasswordBearer 的简单栗子

    背景 假设在某个域中拥有后端 API(127.0.0.1:8080) 并且在另一个域或同一域的不同路径(或移动应用程序)中有一个前端(127.0.0.1:8081) 并且希望有一种方法让前端使用用户名 ...

  5. LeetCode352 将数据流变为多个不相交区间

    LeetCode352 将数据流变为多个不相交区间 1 题目 给你一个由非负整数 a1, a2, ..., an 组成的数据流输入,请你将到目前为止看到的数字总结为不相交的区间列表. 实现 Summa ...

  6. 洛谷luogu3957跳房子(单调队列优化)

    QwQ被普及组的题折磨的死去活来. 硬是卡线段树,没卡过QwQ oi生涯,第一道正经的单调队列dp题 进入正题 题目大意: 其中\(n \le 500000\) 看到这个题的第一感觉就是二分金币数 很 ...

  7. C语言的return语句

    Q1:函数中的Return语句有什么用? Q2:Return 0有什么含义吗? A1:Return的作用为,跳出当前的函数,并且返回到调用当前函数的主调函数,当前函数中Return语句一下代码将不会运 ...

  8. springboot事务的传播行为和隔离级别

    springboot事务的传播行为和隔离级别 在springboot中事务的传播行为和隔离级别都是在TransactionDefinition这个接口中定义的 传播行为定义了7种,分别用0-6来表示 ...

  9. 初探JavaScript PDF blob转换为Word docx方法

    PDF转WORD为什么是历史难题 PDF 转Word 是一个非常非常普遍的需求,可谓人人忌危,为什么如此普遍的需求,却如此难行呢,还得看为什么会有这样的一个需求: PDF文档遵循iOS32000的规范 ...

  10. RogrePirates Scrum Meeting 博客汇总

    RogrePirates 博客目录 一.Scrum Meeting 1.Alpha阶段 第一次会议 第二次会议 第三次会议 第四次会议 第五次会议 第六次会议 第七次会议 第八次会议 第九次会议 第十 ...