UnityCommon/Role/Role.cs
2024-12-25 20:31:40 +08:00

529 lines
14 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.UIElements;
using Debug = UnityEngine.Debug;
using Image = UnityEngine.UI.Image;
using DG.Tweening;
using UnityEngine.SocialPlatforms;
public enum Camp
{/// <summary>
/// 玩家
/// </summary>
Player,
/// <summary>
/// 怪物
/// </summary>
Enemy,
/// <summary>
/// 中立
/// </summary>
Neutral
}
public enum CharacterFlags
{
fly = 1 << 0,
land = 1 << 1,
big = 1 << 2,
min = 1 << 3,
FlyBig=fly|big,
FlyMin=fly|min,
LandBig = land | big,
LandMin = land | min,
}
/// <summary>
/// 角色基类,玩家处理事件
/// </summary>
[ExecuteInEditMode]
public class Role : Fun
{
[Header("Id")] public string id;
[Header("名称")] public string Name;
[Header("阵营")] public Camp camp ;
[Header("血量")] public float hp = 100f;//血量
//[Header("技能")] public List<Skill> Myskill;//技能
private float maxHp;
[Header(("死亡动画编号"))] public int dieIndex=-1;
[Header("hp填充直接扣")] public Image Hpfiil;
[Header("hp填充慢慢扣")] public Image HpfiilYello;
[Header("扣血填充")] public GameObject HpTextPrefab;
[Header("自己的画布")]public Canvas _Canvas;
[Header("自己的图片")] public SpriteRenderer spriteRenderers; // 存储所有的SpriteRenderer组件
[Header("被打的方向")] public int HurtDirectin;
public string Quality;//品质
public string Elements;//属性
public string Info;//详情
public string SkillId;//技能
public string AttackType;//攻击类型
public string AttackActionType;//攻击作用类型
public float AttackRange;//攻击范围
public float AttackCD;//攻击CD
public float CritRate;//暴击率
public float CriticalHitRateBonus;//暴击加成
public float Hp
{
get => hp;
set
{
//if (hp<0)
//{
// return;
//}
float temp = hp;
hp = value;
// 更新血条显示
if (Hpfiil != null)
{
Hpfiil.fillAmount = hp / maxHp;
// 使用 DOTween 动画平滑过渡血条填充
DOTween.To(() => HpfiilYello.fillAmount, x => HpfiilYello.fillAmount = x, hp / maxHp, 0.8f) // 0.5f 为过渡时间
.SetEase(Ease.InOutQuad); // 使用缓动效果,使血条变化更加平滑
}
// 更新血量文本效果
if (HpTextPrefab != null && hp < maxHp)
{
hit();
Navigation.StopPathDoTween(0.2f); // 停止任何进行中的 DoTween 动画0.2s为示例值
GameObject go = GameObject.Instantiate(HpTextPrefab, _Canvas.transform);
go.GetComponent<SnowHpControl>().direction = HurtDirectin;
go.GetComponent<SnowHpControl>().CreateText();
go.GetComponent<Text>().text = (temp - hp).ToString("F0"); // 显示伤害值
}
// 判断角色是否死亡
if (hp <= 0)
{
die(); // 执行死亡处理
}
}
}
[Header("掉落")] public float gold = 10f;
public float Gold
{
[DebuggerStepThrough]
get => gold;
[DebuggerStepThrough]
set => gold = value;
}
[Header("攻击力")] private float attack = 10f;
[Header("攻击力上限")] public float MaxAttack = 10f;
[Header("攻击力下限")] public float MinAttack = 10f;
public float Attack
{
get => attack;
set => attack = value;
}
[Header("等级")] private int level = 1;
public int Level
{
[DebuggerStepThrough] get => level;
[DebuggerStepThrough] set => level = value;
}
[Header("物理护甲")] public int physicalArmor = 10;//物理护甲
[Header("魔法护甲")] public int magicArmor = 5;//魔法护甲
[Header("导航组件")] public SimplePathfindingDoTween Navigation;
[System.Serializable ]
public class AnimationList//动画list
{
//[Header("动画是否循环")] public bool isloop = false;
[Header("动画图片")] public List<Sprite> value; // 字典的值
[Header("角色动画帧数间隔(毫秒)")] public int CharacterAnimationFrameInterval = 50;
}
[Header("角色动画")] public List<AnimationList> AnimationTree = new List<AnimationList>();
[Header("角色动画播放")] public int animationHighlight = 0;
[Header("角色精灵位置")] public SpriteRenderer spriteRenderer;
[Header("角色Image位置")] public Image image;
public delegate void AnimationItem(int AnimationItem);
public event AnimationItem OnAnimationStart;
public event AnimationItem OnAnimationIng;
public event AnimationItem OnAnimationEnd;
[Header("动画是否正常播放")] public bool isAnimationPlay = false;//动画是否正常播放
[Header("碰撞体")]public CircleCollider2D mycollider;
[Header("攻击脚本")] public Attack attackClass;
[Header("当前播放图片序列")] public int CurrentIndex;
public int hitIndex = 2;//受击动画索引
public int normalIndex = 0;//移动动画索引
public bool isHit=false;//
public List<BUff> buffList = new List<BUff>();
public CharacterFlags Tags = 0;
public bool hasfalg(CharacterFlags flag)
{
return (Tags & flag) == flag;
}
/// <summary>
/// 储存buff
/// </summary>
public List<Action<Role>> storageBuff = new List<Action<Role>>();
/// <summary>
/// 使用buff
/// </summary>
public List<Action<Role>> PlayerBuff=new List<Action<Role>>();
public virtual async void Start()
{
maxHp = hp;
SetSelfInfo();
if (Application.isPlaying)
{
if (attackClass)
{
attackClass.role = this;
}
UpdateBuff();
}
tag = Enum.GetName(typeof(Camp), camp);
updateAnimation();
//AddBuff(storageBuff,this.CreateDecelerationBuff(10f,1f));
}
/// <summary>
/// 添加Buff
/// </summary>
/// <param name="buffAction"></param>
public void AddBuff(List<Action<Role>> buffs, Action<Role> buffAction)
{
buffs.Add(buffAction);
Debug.LogError(this.name + "添加buff到"+ buffs);
}
/// <summary>
/// 执行所有当前 Buff
/// </summary>
public void ApplyBuffs()
{
foreach (var buff in PlayerBuff)
{
Debug.LogError(this.name + "进入执行buff判断");
buff.Invoke(this); // 将自己作为目标传递
}
// 清空 Buff 列表,假设 Buff 是一次性的
PlayerBuff.Clear();
}
/// <summary>
/// 角色动画更新
/// </summary>
public async void updateAnimation()
{
while (true)
{
if (AnimationTree.Count == 0)
{
isAnimationPlay = false;
return;
}
isAnimationPlay = true;
if (animationHighlight >= AnimationTree.Count)
{
animationHighlight = AnimationTree.Count - 1;
}
else if (animationHighlight < 0)
{
animationHighlight = 0;
}
List<Sprite> LightSprite = AnimationTree[animationHighlight].value;
if (LightSprite == null)
{
isAnimationPlay = false;
return;
};
OnAnimationStart?.Invoke(animationHighlight);
var lsanimationHighlight = animationHighlight;
foreach (Sprite sprite in LightSprite)
{
if (lsanimationHighlight == animationHighlight)
{
if (image != null)
{
image.sprite = sprite;
}
else if (spriteRenderer != null)
{
spriteRenderer.sprite = sprite;
}
if (animationHighlight >= 0 && animationHighlight < AnimationTree.Count)
{
OnAnimationIng?.Invoke(animationHighlight);
await Task.Delay(AnimationTree[animationHighlight].CharacterAnimationFrameInterval);
}
}
else
{
break;
}
}
OnAnimationEnd?.Invoke(lsanimationHighlight);
if (lsanimationHighlight == dieIndex)
{
SpawnPool.intance.ReturnEnemyToPool(this.gameObject); // 回收当前敌人到池中
ResetAllStatus();
}
if (lsanimationHighlight == hitIndex)
{
animationHighlight = normalIndex;
}
}
}
/// <summary>
/// 角色死亡
/// </summary>
public virtual void die()
{
if (Application.isPlaying)
{
animationHighlight = dieIndex;
Navigation.PauseAnimation();
Debug.Log("die");
}
}
/// <summary>
/// 角色受到攻击
/// </summary>
public virtual void hit()
{
if (Application.isPlaying)
{
animationHighlight = hitIndex;
}
}
/// <summary>
/// 角色减速
/// </summary>
public void SlowDown(float num)
{
Navigation.speedFactor *= num;
}
/// <summary>
/// 单位更新buff
/// </summary>
async void UpdateBuff()//单位buff更新
{
while (true)
{
List<BUff> deleteArr = new List<BUff>();
foreach (BUff buffItem in buffList)
{
if (buffItem.executionInterval <= 0)
{
buffItem.executionInterval = buffItem.executionInterval_max;
buffItem.Funaction.Invoke(buffItem.value);
}
buffItem.executionInterval -= 0.1f;
buffItem.timeLeft -= 0.1f;
if (buffItem.timeLeft <= 0)
{
deleteArr.Add(buffItem);
}
}
foreach (BUff item in deleteArr)
{
buffList.Remove(item);
}
await Task.Delay(100);//buff检测最小时间0.1秒执行一次
}
}
/// <summary>
/// 重置角色所有状态
/// </summary>
public void ResetAllStatus()
{
// 重置血量
Hp = 100f;
// 重置攻击力
Attack = 10f;
// 重置护甲
physicalArmor = 10;
magicArmor = 5;
// 重置等级
Level = 1;
// 重置金币
Gold = 10f;
// 清空 Buff 列表
buffList.Clear();
// 如果有导航组件,停止当前的导航行为
if (Navigation != null)
{
//Navigation.Stop(); // 假设你有 Stop 方法来停止导航
}
// 重置角色动画
animationHighlight = 0;
isAnimationPlay = false;
// 重置碰撞体(根据需求是否需要调整)
if (mycollider != null)
{
mycollider.enabled = true; // 启用碰撞体
}
// 如果有其他需要重置的状态,可以在这里添加
}
public void FlashRedEffect(int color = 0, float time = 0.2f)//0、1 红、蓝
{
// 如果spriteRenderer存在
if (spriteRenderer != null)
{
// 创建一个Sequence来确保动画按顺序执行
Sequence sequence = DOTween.Sequence();
// 颜色变化
if (color == 0)
{
// 变为红色并恢复白色
sequence.Append(spriteRenderer.DOColor(UnityEngine.Color.red, 0.2f))
.Append(spriteRenderer.DOColor(UnityEngine.Color.white, time));
}
else if (color == 1)
{
// 更冷的深蓝色
UnityEngine.Color frostBlueWithAlpha = new UnityEngine.Color(0.2f, 0.5f, 1f); ; // 冰冻蓝色
// 变为蓝色并恢复白色
sequence.Append(spriteRenderer.DOColor(frostBlueWithAlpha, 0.2f))
.Append(spriteRenderer.DOColor(UnityEngine.Color.white, time));
}
// 开始执行Sequence
sequence.Play();
}
}
public void StopDoTween(float stopTime)
{
// 暂停当前的动画
transform.DOPause();
// 插入一个自定义的延迟(僵直时间)
DOTween.To(() => 0f, x => { }, 0f, stopTime).OnKill(() =>
{
// 在延迟结束后恢复动画
transform.DOPlay();
});
}
// 升级逻辑
public virtual void Upgrade()
{
Debug.Log("父类的升级逻辑,空的,请在子类重写");
}
public void SetSelfInfo()
{
if (camp==Camp.Player)
{
// Debug.Log("攻击力赋值==============================" + MengyaoInfo.Instance.m_Mengyao.Count);
foreach (Character character in MengyaoInfo.Instance.m_Mengyao)
{
if (id ==character.Id)
{
Name = character.Name;
MinAttack = int.Parse(character.MinAttack);
MaxAttack = int.Parse(character.MaxAttack);
AttackCD = float.Parse(character.AttackCD);
CritRate = float.Parse(character.CritRate);
Quality=character.Quality;//品质
Elements=character.Elements;//属性
Info=character.Info;//详情
SkillId=character.SkillId;//技能
AttackType=character.AttackType;//攻击类型
AttackActionType=character.AttackActionType;//攻击作用类型
CriticalHitRateBonus = float.Parse(character.CriticalHitRateBonus);
AttackRange = float.Parse(character.AttackRange);
//Debug.Log("攻击力赋值++++++++++++++++++++++++++++++");
}
}
}
}
public float DamageCreate()//伤害生成
{
// 生成普通伤害
float num = UnityEngine.Random.Range(MinAttack, MaxAttack);
// 判断是否暴击
float critChance = UnityEngine.Random.Range(0f, 1f); // 生成一个0到1之间的随机数
if (critChance < CritRate) // 如果暴击发生
{
// 计算暴击伤害(普通伤害乘以暴击加成)
num *= (1 + CriticalHitRateBonus);
//Debug.Log("暴击发生!伤害增加:" + num);
}
return num;
}
public virtual void SlowDown(float slowFactor, float duration)
{
}
}