• Unity类银河恶魔城学习记录14-5 p152 Lost currency save and enemy‘s currency drop


           Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释,可供学习Alex教程的人参考
    此代码仅为较上一P有所改变的代码

    【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili

    LostCurrencyController.cs
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. public class LostCurrencyController : MonoBehaviour
    5. {
    6. public int currency;
    7. private void OnTriggerEnter2D(Collider2D collision)
    8. {
    9. if(collision.GetComponent() != null)
    10. {
    11. PlayerManager.instance.currency += currency;
    12. Destroy(this.gameObject);
    13. }
    14. }
    15. }
    GameManager.cs
    1. using System.Collections.Generic;
    2. using Unity.VisualScripting;
    3. using UnityEngine;
    4. using UnityEngine.SceneManagement;//关于场景的操作
    5. public class GameManager : MonoBehaviour, ISaveManager
    6. {
    7. public static GameManager instance;
    8. private Transform player;
    9. [SerializeField] private Checkpoint[] checkpoints;
    10. [SerializeField] private string closestCheckpointId;
    11. [Header("Lost currency")]
    12. [SerializeField] private GameObject lostCurrencyPerfab;
    13. public int lostCurrencyAmount;
    14. [SerializeField] private float lostCurrencyX;
    15. [SerializeField] private float lostCurrencyY;
    16. private void Awake()
    17. {
    18. if (instance != null)
    19. {
    20. Destroy(instance.gameObject);
    21. }
    22. else
    23. instance = this;
    24. checkpoints = FindObjectsOfType();
    25. player = PlayerManager.instance.player.transform;
    26. }
    27. private void Start()
    28. {
    29. checkpoints = FindObjectsOfType();
    30. }
    31. public void RestratScene()//场景重开函数
    32. {
    33. SaveManager.instance.SaveGame();
    34. Scene scene = SceneManager.GetActiveScene();//获得初始场景
    35. SceneManager.LoadScene(scene.name);//获取的场景必须通过字符串载入
    36. }
    37. public void LoadData(GameData _data)
    38. {
    39. foreach (KeyValuePair<string, bool> pair in _data.checkpoints)
    40. {
    41. foreach (Checkpoint checkpoint in checkpoints)
    42. {
    43. if (checkpoint.id == pair.Key && pair.Value == true)
    44. {
    45. checkpoint.ActivateCheckpoint();
    46. }
    47. }
    48. }
    49. closestCheckpointId = _data.closestCheckpointId;
    50. PlacePlayerAtClosestCheckpoint();
    51. LoadLostCurrency(_data);
    52. }
    53. private void LoadLostCurrency(GameData _data)//产生可以捡到的钱尸体函数
    54. {
    55. lostCurrencyAmount = _data.lostCurrencyAmount;
    56. lostCurrencyX = _data.lostCurrencyX;
    57. lostCurrencyY = _data.lostCurrencyY;
    58. if(lostCurrencyAmount > 0)
    59. {
    60. GameObject newLostCurrency = Instantiate(lostCurrencyPerfab, new Vector3(lostCurrencyX, lostCurrencyY), Quaternion.identity);
    61. newLostCurrency.GetComponent().currency = lostCurrencyAmount;
    62. }
    63. lostCurrencyAmount = 0;
    64. }
    65. private void PlacePlayerAtClosestCheckpoint()//传送至最近检查点函数
    66. {
    67. foreach (Checkpoint checkpoint in checkpoints)
    68. {
    69. if (closestCheckpointId == checkpoint.id && checkpoint.activationStatus)
    70. {
    71. PlayerManager.instance.player.transform.position = checkpoint.transform.position;
    72. }
    73. }
    74. }
    75. public void SaveData(ref GameData _data)
    76. {
    77. _data.lostCurrencyAmount = lostCurrencyAmount;//此地方的钱是player死后stats赋值的
    78. _data.lostCurrencyX = player.position.x;
    79. _data.lostCurrencyY = player.position.y;
    80. if(FindClosestCheckpoint()!=null)
    81. _data.closestCheckpointId = FindClosestCheckpoint().id;//Save后调用
    82. _data.checkpoints.Clear();
    83. foreach (Checkpoint checkpoint in checkpoints)
    84. {
    85. _data.checkpoints.Add(checkpoint.id, checkpoint.activationStatus);
    86. }
    87. }
    88. private Checkpoint FindClosestCheckpoint()//寻找最近检查点的函数
    89. {
    90. float closetDistance = Mathf.Infinity;
    91. Checkpoint closestCheckpoint = null;
    92. foreach (var checkpoint in checkpoints)//遍历检查点比较距离寻找最近的检查点
    93. {
    94. float distanceToCheckpoint = Vector2.Distance(PlayerManager.instance.player.transform.position, checkpoint.transform.position);
    95. if (distanceToCheckpoint < closetDistance && checkpoint.activationStatus == true)
    96. {
    97. closetDistance = distanceToCheckpoint;
    98. closestCheckpoint = checkpoint;
    99. }
    100. }
    101. return closestCheckpoint;
    102. }
    103. }
    GameData.cs
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. [System.Serializable]
    5. public class GameData
    6. {
    7. public int currency;
    8. public SerializableDictionary<string, bool> skillTree;
    9. public SerializableDictionary<string, int> inventory;
    10. public List<string> equipmentId;
    11. public SerializableDictionary<string, bool> checkpoints;
    12. public string closestCheckpointId;
    13. public float lostCurrencyX;
    14. public float lostCurrencyY;
    15. public int lostCurrencyAmount;
    16. public GameData()
    17. {
    18. this.lostCurrencyX = 0;
    19. this.lostCurrencyY = 0;
    20. this.lostCurrencyAmount = 0;
    21. this.currency = 0;
    22. skillTree = new SerializableDictionary<string, bool>();
    23. inventory = new SerializableDictionary<string, int>();
    24. equipmentId = new List<string>();
    25. closestCheckpointId = string.Empty;
    26. checkpoints = new SerializableDictionary<string, bool>();
    27. }
    28. }
    UI.cs
    1. using System.Collections;
    2. using UnityEngine;
    3. public class UI : MonoBehaviour
    4. {
    5. [Header("End screen")]
    6. [SerializeField] private UI_FadeScreen fadeScreen;
    7. [SerializeField] private GameObject endText;
    8. [SerializeField] private GameObject restartButton;
    9. [Space]
    10. [SerializeField] private GameObject characterUI;
    11. [SerializeField] private GameObject skillTreeUI;
    12. [SerializeField] private GameObject craftUI;
    13. [SerializeField] private GameObject optionsUI;
    14. [SerializeField] private GameObject inGameUI;
    15. public UI_itemTooltip itemToolTip;
    16. public UI_statToolTip statToopTip;
    17. public Ui_SkillToolTip skillToolTip;
    18. public UI_CraftWindow craftWindow;
    19. public void Awake()
    20. {
    21. SwitchTo(skillTreeUI);//修复可能出现skill没法加载成功的bug
    22. }
    23. public void Start()
    24. {
    25. SwitchTo(inGameUI);
    26. itemToolTip.gameObject.SetActive(false);
    27. statToopTip.gameObject.SetActive(false);
    28. }
    29. private void Update()
    30. {
    31. if (Input.GetKeyDown(KeyCode.C))
    32. {
    33. SwitchWithKeyTo(characterUI);
    34. }
    35. if (Input.GetKeyDown(KeyCode.B))
    36. {
    37. SwitchWithKeyTo(craftUI);
    38. }
    39. if (Input.GetKeyDown(KeyCode.K))
    40. {
    41. SwitchWithKeyTo(skillTreeUI);
    42. }
    43. if (Input.GetKeyDown(KeyCode.O))
    44. {
    45. SwitchWithKeyTo(optionsUI);
    46. }
    47. }
    48. public void SwitchTo(GameObject _menu)//切换窗口函数
    49. {
    50. for (int i = 0; i < transform.childCount; i++)
    51. {
    52. bool fadeScreen = transform.GetChild(i).GetComponent() != null;//保证存在淡入淡出效果的函数时才会为真,才会使darkScreen保持存在
    53. if (!fadeScreen)
    54. transform.GetChild(i).gameObject.SetActive(false);
    55. }
    56. if (_menu != null)
    57. {
    58. _menu.SetActive(true);
    59. }
    60. }
    61. public void SwitchWithKeyTo(GameObject _menu)//键盘切换窗口函数
    62. {
    63. if (_menu != null && _menu.activeSelf)//通过判断是否传入mune和mune是否激活来决定使设置为可视或不可使
    64. {
    65. _menu.SetActive(false);
    66. CheckForInGameUI();
    67. return;
    68. }
    69. SwitchTo(_menu);
    70. }
    71. private void CheckForInGameUI()//当其他UI不在时自动切换值InGameUI函数
    72. {
    73. for (int i = 0; i < transform.childCount; i++)
    74. {
    75. if (transform.GetChild(i).gameObject.activeSelf && transform.GetChild(i).GetComponent() == null) //修复InGameUI在fadeScreen打开后,没法存在的问题
    76. return;
    77. }
    78. SwitchTo(inGameUI);
    79. }
    80. public void SwitchOnEndScreen()//死亡综合效果函数
    81. {
    82. SwitchTo(null);
    83. fadeScreen.FadeOut();
    84. StartCoroutine(EndScreenCorutine());
    85. }
    86. IEnumerator EndScreenCorutine()//死亡显示文本函数
    87. {
    88. yield return new WaitForSeconds(1);
    89. endText.SetActive(true);
    90. yield return new WaitForSeconds(1.5f);
    91. restartButton.SetActive(true);
    92. }
    93. public void RestartGameButton()//场景重开函数
    94. {
    95. GameManager.instance.RestratScene();//调用GameManager的重开函数
    96. }
    97. }

    UI_InGame.cs
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using TMPro;
    4. using UnityEngine;
    5. using UnityEngine.UI;
    6. public class UI_InGame : MonoBehaviour
    7. {
    8. [SerializeField] private PlayerStats playerStats;
    9. [SerializeField] Slider slider;
    10. [SerializeField] private Image dashImage;
    11. [SerializeField] private Image parryImage;
    12. [SerializeField] private Image crystalImage;
    13. [SerializeField] private Image swordImage;
    14. [SerializeField] private Image blackholeImage;
    15. [SerializeField] private Image flaskholeImage;
    16. [Header("Souls info")]
    17. [SerializeField] private TextMeshProUGUI currentSouls;
    18. [SerializeField] private float soulsAmount;//灵魂数量
    19. [SerializeField] private float increaseRate = 100;//增长速率
    20. private SkillManager skills;
    21. void Start()
    22. {
    23. if(playerStats != null)
    24. {
    25. playerStats.onHealthChanged += UpdateHealthUI;
    26. }
    27. skills = SkillManager.instance;
    28. }
    29. // Update is called once per frame
    30. void Update()
    31. {
    32. UpdateSoulsUI();//货币随着时间变化的特效函数
    33. if (Input.GetKeyDown(KeyCode.LeftShift) && skills.dash.dashUnlocked)//使用技能后图标变黑
    34. {
    35. SetCoolDownOf(dashImage);
    36. }
    37. if (Input.GetKeyDown(KeyCode.Q) && skills.parry.parryUnlocked)
    38. {
    39. SetCoolDownOf(parryImage);
    40. }
    41. if (Input.GetKeyDown(KeyCode.F) && skills.crystal.crystalUnlocked)
    42. {
    43. SetCoolDownOf(crystalImage);
    44. }
    45. if (Input.GetKeyDown(KeyCode.Mouse1) && skills.sword.swordUnlocked)
    46. {
    47. SetCoolDownOf(swordImage);
    48. }
    49. if (Input.GetKeyDown(KeyCode.R) && skills.blackhole.blackholeUnlocked)
    50. {
    51. SetCoolDownOf(blackholeImage);
    52. }
    53. if (Input.GetKeyDown(KeyCode.Alpha1) && Inventory.instance.GetEquipment(EquipmentType.Flask) != null)
    54. {
    55. SetCoolDownOf(flaskholeImage);
    56. }
    57. CheckCooldown(dashImage, skills.dash.cooldown);
    58. CheckCooldown(parryImage, skills.parry.cooldown);
    59. CheckCooldown(crystalImage, skills.crystal.cooldown);
    60. CheckCooldown(swordImage, skills.sword.cooldown);
    61. CheckCooldown(blackholeImage, skills.blackhole.cooldown);
    62. CheckCooldown(flaskholeImage, Inventory.instance.flaskCooldown);
    63. }
    64. private void UpdateSoulsUI()//货币随着时间变化的特效函数
    65. {
    66. //逻辑是判断目前的钱少于实际的钱,则以速率*时间的方式增加直到相同或者大于后等于实际的钱
    67. if (soulsAmount < PlayerManager.instance.GetCurrency())
    68. {
    69. soulsAmount += Time.deltaTime * increaseRate;
    70. }
    71. else
    72. soulsAmount = PlayerManager.instance.GetCurrency();
    73. currentSouls.text = ((int)soulsAmount).ToString();
    74. }
    75. private void UpdateHealthUI()//更新血量条函数,此函数由Event触发
    76. {
    77. slider.maxValue = playerStats.GetMaxHealthValue();
    78. slider.value = playerStats.currentHealth;
    79. }
    80. private void SetCoolDownOf(Image _image)//使用技能后使图标变黑的函数
    81. {
    82. if (_image.fillAmount <= 0)
    83. _image.fillAmount = 1;
    84. }
    85. private void CheckCooldown(Image _image,float _cooldown)//使图标根据cd逐渐变白的函数
    86. {
    87. if(_image.fillAmount > 0)
    88. {
    89. _image.fillAmount -= 1 / _cooldown * Time.deltaTime;
    90. }
    91. }
    92. }
    PlayerStat.cs
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. public class PlayerStats : CharacterStats
    5. {
    6. private Player player;
    7. protected override void Start()
    8. {
    9. player = GetComponent();
    10. base.Start();
    11. }
    12. public override void DoDamage(CharacterStats _targetStats)
    13. {
    14. base.DoDamage(_targetStats);
    15. }
    16. public override void TakeDamage(int _damage)
    17. {
    18. base.TakeDamage(_damage);
    19. }
    20. protected override void Die()
    21. {
    22. base.Die();
    23. player.Die();
    24. GameManager.instance.lostCurrencyAmount = PlayerManager.instance.currency;
    25. PlayerManager.instance.currency = 0;
    26. GetComponent()?.GenerateDrop();
    27. }
    28. protected override void DecreaseHealthBy(int _damage)
    29. {
    30. base.DecreaseHealthBy(_damage);
    31. ItemData_Equipment currentArmor = Inventory.instance.GetEquipment(EquipmentType.Armor);
    32. if(currentArmor != null)
    33. {
    34. currentArmor.Effect(player.transform);
    35. }
    36. }
    37. public override void OnEvasion()
    38. {
    39. player.skill.dogge.CreateMirageOnDoDogge();
    40. }
    41. public void CloneDoDamage(CharacterStats _targetStats,float _multiplier)
    42. {
    43. if (TargetCanAvoidAttack(_targetStats))设置闪避
    44. {
    45. return;
    46. }
    47. int totleDamage = damage.GetValue() + strength.GetValue();
    48. if(_multiplier > 0)
    49. {
    50. totleDamage = Mathf.RoundToInt(totleDamage * _multiplier);
    51. }
    52. //爆伤设置
    53. if (CanCrit())
    54. {
    55. totleDamage = CalculateCriticalDamage(totleDamage);
    56. }
    57. totleDamage = CheckTargetArmor(_targetStats, totleDamage);//设置防御
    58. _targetStats.TakeDamage(totleDamage);
    59. DoMagicaDamage(_targetStats); // 可以去了也可以不去
    60. }
    61. }

    EnemyStat.cs
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.WSA;
    5. public class EnemyStats : CharacterStats
    6. {
    7. private Enemy enemy;
    8. private ItemDrop myDropSystem;
    9. public Stat soulsDropAmount;//金币掉落
    10. [Header("Level details")]
    11. [SerializeField] private int leval = 1;
    12. [Range(0f, 1f)]//一个使数值设置成为一定范围的设置
    13. [SerializeField] private float percantageModifier = .4f;//设置等级和成长比例
    14. public override void DoDamage(CharacterStats _targetStats)
    15. {
    16. base.DoDamage(_targetStats);
    17. }
    18. protected override void Die()
    19. {
    20. base.Die();
    21. enemy.Die();
    22. PlayerManager.instance.currency += soulsDropAmount.GetValue();
    23. myDropSystem.GenerateDrop();
    24. }
    25. protected override void Start()
    26. {
    27. soulsDropAmount.SetDefaultValue(100);
    28. //改变伤害和生命值
    29. //解决初始血量在升级后不满
    30. ApplyLevelModifier();
    31. enemy = GetComponent();
    32. base.Start();
    33. myDropSystem = GetComponent();
    34. }
    35. private void ApplyLevelModifier()
    36. {
    37. Modify(strength);
    38. Modify(agility);
    39. Modify(intelligence);
    40. Modify(vitality);
    41. Modify(damage);
    42. Modify(critChance);
    43. Modify(critPower);
    44. Modify(Health);
    45. Modify(armor);
    46. Modify(evasion);
    47. Modify(magicResistance);
    48. Modify(fireDamage);
    49. Modify(iceDamage);
    50. Modify(lightingDamage);
    51. Modify(soulsDropAmount);
    52. }
    53. //专门对某个数值进行提升的函数
    54. private void Modify(Stat _stat)
    55. {
    56. for(int i =1;i
    57. {
    58. float modifier = _stat.GetValue() * percantageModifier;
    59. _stat.AddModifier(Mathf.RoundToInt(modifier));
    60. }
    61. }
    62. public override void TakeDamage(int _damage)
    63. {
    64. base.TakeDamage(_damage);
    65. }
    66. }

  • 相关阅读:
    Git下载安装及基本配置
    非零基础自学Java (老师:韩顺平) 第14章 集合 14.6 Vector 底层结构和源码分析
    [Usaco2015 dec]Max Flow 树上差分
    R语言在vector向量数据末尾追加新的元素(在已知向量末尾添加单个标量数据形成新的向量)
    【PyCharm】设置(风格 | 字体 | 模板)
    【Device Tree】Kernel中的gpio driver在DTS下是如何初始化的
    [Leetcode]6032. 得到要求路径的最小带权子图
    【数据结构】归并排序
    测试人生 | 从小团队的业务到独角兽的测开,涨薪超过60%,90后小哥哥凤凰涅槃了
    用人工智能压缩图像的尝试2
  • 原文地址:https://blog.csdn.net/Homura_/article/details/138215938