Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释,可供学习Alex教程的人参考
此代码仅为较上一P有所改变的代码
【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili
GameData.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class GameData
{
public int currency;
public SerializableDictionary<string, bool> skillTree;
public SerializableDictionary<string, int> inventory;
public List<string> equipmentId;
public GameData()
{
this.currency = 0;
skillTree = new SerializableDictionary<string, bool>();
inventory = new SerializableDictionary<string, int>();
equipmentId = new List<string>();
}
}
Skill
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using UnityEngine;
public class Skill : MonoBehaviour
{
public float cooldown;
protected float cooldownTimer;
protected Player player;//拿到player
protected virtual void Start()
{
player = PlayerManager.instance.player;//拿到player
CheckUnlock();
}
protected virtual void Update()
{
cooldownTimer -= Time.deltaTime;
}
protected virtual void CheckUnlock()//再次打开游戏时读取数据文件后使技能可以使用的函数
{
}
public virtual bool CanUseSkill()
{
if (cooldownTimer < 0)
{
UseSkill();
cooldownTimer = cooldown;
return true;
}
else
{
Debug.Log("Skill is on cooldown");
return false;
}
}
public virtual void UseSkill()
{
// do some skill thing
}
//整理能返回最近敌人位置的函数
protected virtual Transform FindClosestEnemy(Transform _checkTransform)
{
Collider2D[] colliders = Physics2D.OverlapCircleAll(_checkTransform.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)
{
float distanceToEnemy = Vector2.Distance(_checkTransform.position, hit.transform.position);//拿到与敌人之间的距离
if (distanceToEnemy < closestDistance)//比较距离,如果离得更近,保存这个敌人的位置,更改最近距离
{
closestDistance = distanceToEnemy;
closestEnemy = hit.transform;
}
}
}
return closestEnemy;
}
}
UI_SkillTreeSlot
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class UI_SkillTreeSlot : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler,ISaveManager
{
[SerializeField] private int skillCost;
[SerializeField] private string skillName;
[TextArea]
[SerializeField] private string skillDescription;
[SerializeField] private Color lockedSkillColor;
private UI ui;
public bool unlocked;//一个表示是否解锁的bool值
private Image skillImage;
[SerializeField] private UI_SkillTreeSlot[] shouldBeUnlocked;
[SerializeField] private UI_SkillTreeSlot[] shouldBeLocked;//应该解锁和不该解锁的Slot组和Image
private void OnValidate()
{
gameObject.name = "SkillTreeSlot_UI - " + skillName;
}
private void Awake()
{
GetComponent<Button>().onClick.AddListener(() => UnlockSkillSlot());
}
private void Start()
{
skillImage = GetComponent<Image>();
skillImage.color = lockedSkillColor;
ui = GetComponentInParent<UI>();
if (unlocked)
skillImage.color = Color.white;
}
public void UnlockSkillSlot()//一个判断此Skill是否可以解锁的函数
{
if (PlayerManager.instance.HaveEnoughMoney(skillCost) == false)
return;
Debug.Log("Slot unlocked");
for (int i = 0; i < shouldBeUnlocked.Length; i++)
{
if (shouldBeUnlocked[i].unlocked == false)
{
Debug.Log("Cannot unlock skill");
return;
}
}
for (int i = 0; i < shouldBeLocked.Length; i++)
{
if (shouldBeLocked[i].unlocked == true)
{
Debug.Log("Cannot unlock skill");
return;
}
}
unlocked = true;
skillImage.color = Color.white;
}
public void OnPointerEnter(PointerEventData eventData)
{
ui.skillToolTip.ShowToolTip(skillDescription, skillName,skillCost.ToString());
}
public void OnPointerExit(PointerEventData eventData)
{
ui.skillToolTip.HideToolTip();
}
public void LoadData(GameData _data)
{
if(_data.skillTree.TryGetValue(skillName,out bool value))
{
unlocked = value;
}
}
public void SaveData(ref GameData _data)
{
if (_data.skillTree.TryGetValue(skillName, out bool value))//这应该是跟clear一样的,但是为什么不直接用clear?
//因为clear会调用24次,每一次都把前面保存的删了,最后只剩下一个
{
_data.skillTree.Remove(skillName);
_data.skillTree.Add(skillName, unlocked);
}
else
{
_data.skillTree.Add(skillName, unlocked);
}
//_data.skillTree.Clear();
//_data.skillTree.Add(skillName, unlocked);
}
}
Dogge_Skill
using UnityEngine;
using UnityEngine.UI;
public class Dogge_Skill : Skill
{
[Header("Dodge")]
[SerializeField] private UI_SkillTreeSlot unlockDoggeButton;
[SerializeField] private int evasionAmount;
public bool doggeUnlocked;
[Header("Mirage dodge")]
[SerializeField] private UI_SkillTreeSlot unlockMirageDoggeButton;
public bool dodgemirageUnlocked;
protected override void Start()
{
base.Start();
unlockDoggeButton.GetComponent<Button>().onClick.AddListener(UnlockDodge);
unlockMirageDoggeButton.GetComponent<Button>().onClick.AddListener(UnlockMirageDogge);
}
protected override void CheckUnlock()
{
UnlockDodge();
UnlockMirageDogge();
}
private void UnlockDodge()
{
if (unlockDoggeButton.unlocked && !doggeUnlocked)
{
player.stats.evasion.AddModifier(evasionAmount);
Inventory.instance.UpdateStatsUI();
doggeUnlocked = true;
}
}
private void UnlockMirageDogge()
{
if (unlockMirageDoggeButton.unlocked)
dodgemirageUnlocked = true;
}
public void CreateMirageOnDoDogge()
{
if (dodgemirageUnlocked)
SkillManager.instance.clone.CreateClone(player.transform, Vector3.zero);
}
}