赞
踩
【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
-
-
-
- public enum StatType
- {
-
- strength,
- agility,
- intelligence,
- vitality,
- damage,
- critChance,
- critPower,
- maxHealth,
- armor,
- evasion,
- magicResistance,
- fireDamage,
- iceDamage,
- lightingDamage
- }
-
- [CreateAssetMenu(fileName = "BUff effect", menuName = "Data/Item effect/Buff effect")]
-
- public class Buff_Effect :ItemEffect
- {
- private PlayerStats stats;
- [SerializeField] private StatType buffType;
- [SerializeField] private float buffDuration;
- [SerializeField] private int buffAmount;
-
- public override void ExecuteEffect(Transform _respawnPosition)
- {
- stats = PlayerManager.instance.player.GetComponent<PlayerStats>();
-
- stats.IncreaseStatBy(buffAmount, buffDuration, StatToModify());
- }
-
- private Stat StatToModify()
- {
- if (buffType == StatType.strength) return stats.strength;
- else if (buffType == StatType.agility) return stats.agility;
- else if (buffType == StatType.intelligence) return stats.intelligence;
- else if (buffType == StatType.vitality) return stats.vitality;
- else if (buffType == StatType.damage) return stats.damage;
- else if (buffType == StatType.critChance) return stats.critChance;
- else if (buffType == StatType.critPower) return stats.critPower;
- else if (buffType == StatType.maxHealth) return stats.maxHealth;
- else if (buffType == StatType.armor) return stats.armor;
- else if (buffType == StatType.evasion) return stats.evasion;
- else if (buffType == StatType.magicResistance) return stats.magicResistance;
- else if (buffType == StatType.fireDamage) return stats.fireDamage;
- else if (buffType == StatType.iceDamage) return stats.iceDamage;
- else if (buffType == StatType.lightingDamage) return stats.lightingDamage;
-
- return null;
- }
- }
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
-
- public class CharacterStats : MonoBehaviour
- {
- private EntityFX fx;
-
-
- [Header("Major stats")]
- public Stat strength; // 力量 增伤1点 爆伤增加 1% 物抗
- public Stat agility;// 敏捷 闪避 1% 闪避几率增加 1%
- public Stat intelligence;// 1 点 魔法伤害 1点魔抗
- public Stat vitality;//加血的
-
- [Header("Offensive stats")]
- public Stat damage;
- public Stat critChance; // 暴击率
- public Stat critPower; //150% 爆伤
-
- [Header("Defensive stats")]
- public Stat maxHealth;
- public Stat armor;
- public Stat evasion;//闪避值
- public Stat magicResistance;
-
- [Header("Magic stats")]
- public Stat fireDamage;
- public Stat iceDamage;
- public Stat lightingDamage;
-
-
- public bool isIgnited; // 持续烧伤
- public bool isChilded; // 削弱护甲 20%
- public bool isShocked; // 降低敌人命中率
-
- [SerializeField] private float ailmentsDuration = 4;
- private float ignitedTimer;
- private float chilledTimer;
- private float shockedTimer;
-
-
- private float igniteDamageCooldown = .3f;
- private float ignitedDamageTimer;
- private int igniteDamage;
- [SerializeField] private GameObject shockStrikePrefab;
- private int shockDamage;
-
-
- public System.Action onHealthChanged;//使角色在Stat里调用UI层的函数
- //此函数调用了更新HealthUI函数
- public bool isDead { get; private set; }
-
- [SerializeField] public int currentHealth;
-
-
- protected virtual void Start()
- {
- critPower.SetDefaultValue(150);//设置默认爆伤
- currentHealth = GetMaxHealthValue();
-
- fx = GetComponent<EntityFX>();
- }
-
- protected virtual void Update()
- {
- //所有的状态都设置上默认持续时间,持续过了就结束状态
- ignitedTimer -= Time.deltaTime;
- chilledTimer -= Time.deltaTime;
- shockedTimer -= Time.deltaTime;
- ignitedDamageTimer -= Time.deltaTime;
-
- if (ignitedTimer < 0)
- isIgnited = false;
- if (chilledTimer < 0)
- isChilded = false;
- if (shockedTimer < 0)
- isShocked = false;
-
- //被点燃后,出现多段伤害后点燃停止
- if(isIgnited)
- ApplyIgnitedDamage();
- }
-
-
- public virtual void IncreaseStatBy(int _modifier, float _duration,Stat _statToModify)
- {
- StartCoroutine(StatModCoroutine(_modifier, _duration, _statToModify));
- }
- private IEnumerator StatModCoroutine(int _modifier, float _duration, Stat _statToModify)
- {
- _statToModify.AddModifier(_modifier);
- yield return new WaitForSeconds(_duration);
- _statToModify.RemoveModifier(_modifier);
- }
- public virtual void DoDamage(CharacterStats _targetStats)//计算后造成伤害函数
- {
- if (TargetCanAvoidAttack(_targetStats))设置闪避
- {
- return;
- }
-
-
-
- int totleDamage = damage.GetValue() + strength.GetValue();
-
- //爆伤设置
- if (CanCrit())
- {
- totleDamage = CalculateCriticalDamage(totleDamage);
- }
-
- totleDamage = CheckTargetArmor(_targetStats, totleDamage);//设置防御
-
- _targetStats.TakeDamage(totleDamage);
-
- DoMagicaDamage(_targetStats); // 可以去了也可以不去
-
- }
- protected virtual void Die()
- {
- isDead = true;
- }
- public virtual void TakeDamage(int _damage)//造成伤害是出特效
- {
- fx.StartCoroutine("FlashFX");//IEnumertor本质就是将一个函数分块执行,只有满足某些条件才能执行下一段代码,此函数有StartCoroutine调用
- //https://www.zhihu.com/tardis/bd/art/504607545?source_id=1001
- DecreaseHealthBy(_damage);
-
- GetComponent<Entity>().DamageImpact();
-
- if (currentHealth < 0 && !isDead)
- Die();
-
- }
- public virtual void IncreaseHealthBy(int _amount)//添加回血函数
- {
- currentHealth += _amount;
-
- if (currentHealth > GetMaxHealthValue())
- currentHealth = GetMaxHealthValue();
-
- if (onHealthChanged != null)
- onHealthChanged();
- }
- protected virtual void DecreaseHealthBy(int _damage)//此函数用来改变当前生命值,不调用特效
- {
- currentHealth -= _damage;
-
- if (onHealthChanged != null)
- {
- onHealthChanged();
- }
- }
-
- #region Magical damage and ailements
- private void ApplyIgnitedDamage()
- {
- if (ignitedDamageTimer < 0 )
- {
- DecreaseHealthBy(igniteDamage);
- if (currentHealth < 0 && !isDead)
- Die();
- ignitedDamageTimer = igniteDamageCooldown;
- }
- }被点燃后,出现多段伤害后点燃停止
- public virtual void DoMagicaDamage(CharacterStats _targetStats)//法伤计算和造成元素效果调用的地方
- {
- int _fireDamage = fireDamage.GetValue();
- int _iceDamage = iceDamage.GetValue();
- int _lightingDamage = lightingDamage.GetValue();
-
- int totleMagicalDamage = _fireDamage + _iceDamage + _lightingDamage + intelligence.GetValue();
- totleMagicalDamage = CheckTargetResistance(_targetStats, totleMagicalDamage);
-
- _targetStats.TakeDamage(totleMagicalDamage);
-
- //防止循环在所有元素伤害为0时出现死循环
- if (Mathf.Max(_fireDamage, _iceDamage, _lightingDamage) <= 0)
- return;
-
- //让元素效果取决与伤害
-
-
- //为了防止出现元素伤害一致而导致无法触发元素效果
- //循环判断触发某个元素效果
-
- AttemptyToApplyAilement(_targetStats, _fireDamage, _iceDamage, _lightingDamage);
-
- }
-
- private void AttemptyToApplyAilement(CharacterStats _targetStats, int _fireDamage, int _iceDamage, int _lightingDamage)
- {
- bool canApplyIgnite = _fireDamage > _iceDamage && _fireDamage > _lightingDamage;
- bool canApplyChill = _iceDamage > _lightingDamage && _iceDamage > _fireDamage;
- bool canApplyShock = _lightingDamage > _fireDamage && _lightingDamage > _iceDamage;
-
-
-
- while (!canApplyIgnite && !canApplyChill && !canApplyShock)
- {
- if (Random.value < .25f)
- {
- canApplyIgnite = true;
- Debug.Log("Ignited");
- _targetStats.ApplyAilments(canApplyIgnite, canApplyChill, canApplyShock);
- return;
- }
- if (Random.value < .35f)
- {
- canApplyChill = true;
- Debug.Log("Chilled");
- _targetStats.ApplyAilments(canApplyIgnite, canApplyChill, canApplyShock);
- return;
- }
- if (Random.value < .55f)
- {
- canApplyShock = true;
- Debug.Log("Shocked");
- _targetStats.ApplyAilments(canApplyIgnite, canApplyChill, canApplyShock);
- return;
- }
-
- }
-
-
- if (canApplyIgnite)
- {
- _targetStats.SetupIgniteDamage(Mathf.RoundToInt(_fireDamage * .2f));
- }
-
- if (canApplyShock)
- _targetStats.SetupShockStrikeDamage(Mathf.RoundToInt(_lightingDamage * .1f));
-
- //给点燃伤害赋值
-
- _targetStats.ApplyAilments(canApplyIgnite, canApplyChill, canApplyShock);
- }//造成元素效果
-
- public void ApplyAilments(bool _ignite, bool _chill, bool _shock)//判断异常状态
- {
- bool canApplyIgnite = !isIgnited && !isChilded && !isShocked;
- bool canApplyChill = !isIgnited && !isChilded && !isShocked;
- bool canApplyShock = !isIgnited && !isChilded;
- //使当isShock为真时Shock里的函数仍然可以调用
-
- if (_ignite && canApplyIgnite)
- {
- isIgnited = _ignite;
- ignitedTimer = ailmentsDuration;
-
- fx.IgniteFxFor(ailmentsDuration);
- }
- if (_chill && canApplyChill)
- {
- isChilded = _chill;
- chilledTimer = ailmentsDuration;
-
- float slowPercentage = .2f;
-
- GetComponent<Entity>().SlowEntityBy(slowPercentage, ailmentsDuration);
-
- fx.ChillFxFor(ailmentsDuration);
- }
- if (_shock && canApplyShock)
- {
- if(!isShocked)
- {
- ApplyShock(_shock);
- }
- else
- {
- if (GetComponent<Player>() != null)//防止出现敌人使玩家进入shock状态后也出现闪电
- return;
- HitNearestTargetWithShockStrike();
- }//isShock为真时反复执行的函数为寻找最近的敌人,创建闪电实例并传入数据
-
- }
- }
-
- public void ApplyShock(bool _shock)
- {
- if (isShocked)
- return;
-
- isShocked = _shock;
- shockedTimer = ailmentsDuration;
-
- fx.ShockFxFor(ailmentsDuration);
- }//触电变色效果
-
- private void HitNearestTargetWithShockStrike()
- {
- Collider2D[] colliders = Physics2D.OverlapCircleAll(transform.position, 25);//找到环绕自己的所有碰撞器
-
- float closestDistance = Mathf.Infinity;//正无穷大的表示形式(只读)
- Transform closestEnemy = null;
-
-
- //https://docs.unity3d.com/cn/current/ScriptReference/Mathf.Infinity.html
- foreach (var hit in colliders)
- {
- if (hit.GetComponent<Enemy>() != null && Vector2.Distance(transform.position, hit.transform.position) > 1)// 防止最近的敌人就是Shock状态敌人自己
- {
- float distanceToEnemy = Vector2.Distance(transform.position, hit.transform.position);//拿到与敌人之间的距离
- if (distanceToEnemy < closestDistance)//比较距离,如果离得更近,保存这个敌人的位置,更改最近距离
- {
- closestDistance = distanceToEnemy;
- closestEnemy = hit.transform;
- }
- }
-
- if (closestEnemy == null)
- closestEnemy = transform;
- }
-
- if (closestEnemy != null)
- {
- GameObject newShockStrike = Instantiate(shockStrikePrefab, transform.position, Quaternion.identity);
- newShockStrike.GetComponent<ShockStrike_Controller>().Setup(shockDamage, closestEnemy.GetComponent<CharacterStats>());
- }
- }//给最近的敌人以雷劈
-
- public void SetupIgniteDamage(int _damage) => igniteDamage = _damage;//给点燃伤害赋值
- public void SetupShockStrikeDamage(int _damage) => shockDamage = _damage;//雷电伤害赋值
-
- #endregion
-
- #region Stat calculations
-
- private int CheckTargetResistance(CharacterStats _targetStats, int totleMagicalDamage)//法抗计算
- {
- totleMagicalDamage -= _targetStats.magicResistance.GetValue() + (_targetStats.intelligence.GetValue() * 3);
- totleMagicalDamage = Mathf.Clamp(totleMagicalDamage, 0, int.MaxValue);
- return totleMagicalDamage;
- }
-
-
-
- private static int CheckTargetArmor(CharacterStats _targetStats, int totleDamage)//防御计算
- {
-
- //被冰冻后,角色护甲减少
- if (_targetStats.isChilded)
- totleDamage -= Mathf.RoundToInt(_targetStats.armor.GetValue() * .8f);
- else
- totleDamage -= _targetStats.armor.GetValue();
- totleDamage = Mathf.Clamp(totleDamage, 0, int.MaxValue);
- return totleDamage;
- }
-
- private bool TargetCanAvoidAttack(CharacterStats _targetStats)//闪避计算
- {
- int totleEvation = _targetStats.evasion.GetValue() + _targetStats.agility.GetValue();
-
- //我被麻痹后
- //敌人的闪避率提升
- if (isShocked)
- totleEvation += 20;
-
- if (Random.Range(0, 100) < totleEvation)
- {
- return true;
- }
- return false;
- }
-
- private bool CanCrit()//判断是否暴击
- {
- int totleCriticalChance = critChance.GetValue() + agility.GetValue();
-
- if (Random.Range(0, 100) <= totleCriticalChance)
- {
- return true;
- }
-
- return false;
- }
-
- private int CalculateCriticalDamage(int _damage)//计算暴击后伤害
- {
- float totleCirticalPower = (critPower.GetValue() + strength.GetValue()) * .01f;
-
- float critDamage = _damage * totleCirticalPower;
-
- return Mathf.RoundToInt(critDamage);//返回舍入为最近整数的
- }
- public int GetMaxHealthValue()
- {
-
- return maxHealth.GetValue() + vitality.GetValue() * 10;
-
- }//统计生命值函数
-
- #endregion
- }
-
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。