Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释,可供学习Alex教程的人参考
此代码仅为较上一P有所改变的代码
【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili
Checkpoint.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Checkpoint : MonoBehaviour
{
private Animator anim;
public string id;
public bool activationStatus;
private void Start()
{
anim = GetComponent<Animator>();
}
[ContextMenu("Generate checkpoint id")]
private void GenerateId()//制作ID函数
{
id = System.Guid.NewGuid().ToString();//不根据path,直接生成id
}
private void OnTriggerEnter2D(Collider2D collision)
{
if(collision.GetComponent<Player>()!=null)
{
ActivateCheckpoint();
}
}
public void ActivateCheckpoint()//激活检查点函数
{
anim.SetBool("active", true);
activationStatus = true;
}
}
GameManager.cs
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.SceneManagement;//关于场景的操作
public class GameManager : MonoBehaviour, ISaveManager
{
public static GameManager instance;
[SerializeField] private Checkpoint[] checkpoints;
[SerializeField] private string closestCheckpointId;
private void Awake()
{
if (instance != null)
{
Destroy(instance.gameObject);
}
else
instance = this;
}
private void Start()
{
checkpoints = FindObjectsOfType<Checkpoint>();
}
public void RestratScene()//场景重开函数
{
SaveManager.instance.SaveGame();
Scene scene = SceneManager.GetActiveScene();//获得初始场景
SceneManager.LoadScene(scene.name);//获取的场景必须通过字符串载入
}
public void LoadData(GameData _data)
{
Debug.Log(1);
foreach (KeyValuePair<string, bool> pair in _data.checkpoints)//好像这玩意没有用啊
{
Debug.Log(2);
foreach (Checkpoint checkpoint in checkpoints)
{
Debug.Log(3);
if (checkpoint.id == pair.Key && pair.Value == true)
{
checkpoint.ActivateCheckpoint();
Debug.Log(4);
}
}
}
closestCheckpointId = _data.closestCheckpointId;
Invoke("PlacePlayerAtClosestCheckpoint", .1f);//通过延迟释放,使closestCheckpointId能够正确的被存储调用
}
private void PlacePlayerAtClosestCheckpoint()//传送至最近检查点函数
{
foreach (Checkpoint checkpoint in checkpoints)
{
if (closestCheckpointId == checkpoint.id)
{
PlayerManager.instance.player.transform.position = checkpoint.transform.position;
}
}
}
public void SaveData(ref GameData _data)
{
_data.closestCheckpointId = FindClosestCheckpoint().id;//Save后掉用
_data.checkpoints.Clear();
foreach (Checkpoint checkpoint in checkpoints)
{
_data.checkpoints.Add(checkpoint.id, checkpoint.activationStatus);
}
}
private Checkpoint FindClosestCheckpoint()//寻找最近检查点的函数
{
float closetDistance = Mathf.Infinity;
Checkpoint closestCheckpoint = null;
foreach (var checkpoint in checkpoints)//遍历检查点比较距离寻找最近的检查点
{
float distanceToCheckpoint = Vector2.Distance(PlayerManager.instance.player.transform.position, checkpoint.transform.position);
if (distanceToCheckpoint < closetDistance && checkpoint.activationStatus == true)
{
closetDistance = distanceToCheckpoint;
closestCheckpoint = checkpoint;
}
}
return closestCheckpoint;
}
}
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 SerializableDictionary<string, bool> checkpoints;
public string closestCheckpointId;
public GameData()
{
this.currency = 0;
skillTree = new SerializableDictionary<string, bool>();
inventory = new SerializableDictionary<string, int>();
equipmentId = new List<string>();
closestCheckpointId = string.Empty;
checkpoints = new SerializableDictionary<string, bool>();
}
}
UI.cs
using System.Collections;
using UnityEngine;
public class UI : MonoBehaviour
{
[Header("End screen")]
[SerializeField] private UI_FadeScreen fadeScreen;
[SerializeField] private GameObject endText;
[SerializeField] private GameObject restartButton;
[Space]
[SerializeField] private GameObject characterUI;
[SerializeField] private GameObject skillTreeUI;
[SerializeField] private GameObject craftUI;
[SerializeField] private GameObject optionsUI;
[SerializeField] private GameObject inGameUI;
public UI_itemTooltip itemToolTip;
public UI_statToolTip statToopTip;
public Ui_SkillToolTip skillToolTip;
public UI_CraftWindow craftWindow;
public void Awake()
{
SwitchTo(skillTreeUI);//修复可能出现skill没法加载成功的bug
}
public void Start()
{
SwitchTo(inGameUI);
itemToolTip.gameObject.SetActive(false);
statToopTip.gameObject.SetActive(false);
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.C))
{
SwitchWithKeyTo(characterUI);
}
if (Input.GetKeyDown(KeyCode.B))
{
SwitchWithKeyTo(craftUI);
}
if (Input.GetKeyDown(KeyCode.K))
{
SwitchWithKeyTo(skillTreeUI);
}
if (Input.GetKeyDown(KeyCode.O))
{
SwitchWithKeyTo(optionsUI);
}
}
public void SwitchTo(GameObject _menu)//切换窗口函数
{
for (int i = 0; i < transform.childCount; i++)
{
bool fadeScreen = transform.GetChild(i).GetComponent<UI_FadeScreen>() != null;//保证存在淡入淡出效果的函数时才会为真,才会使darkScreen保持存在
if (!fadeScreen)
transform.GetChild(i).gameObject.SetActive(false);
}
if (_menu != null)
{
_menu.SetActive(true);
}
}
public void SwitchWithKeyTo(GameObject _menu)//键盘切换窗口函数
{
if (_menu != null && _menu.activeSelf)//通过判断是否传入mune和mune是否激活来决定使设置为可视或不可使
{
_menu.SetActive(false);
CheckForInGameUI();
return;
}
SwitchTo(_menu);
}
private void CheckForInGameUI()//当其他UI不在时自动切换值InGameUI函数
{
for (int i = 0; i < transform.childCount; i++)
{
if (transform.GetChild(i).gameObject.activeSelf)
return;
}
SwitchTo(inGameUI);
}
public void SwitchOnEndScreen()//死亡综合效果函数
{
SwitchTo(null);
fadeScreen.FadeOut();
StartCoroutine(EndScreenCorutine());
}
IEnumerator EndScreenCorutine()//死亡显示文本函数
{
yield return new WaitForSeconds(1);
endText.SetActive(true);
yield return new WaitForSeconds(1.5f);
restartButton.SetActive(true);
}
public void RestartGameButton()//场景重开函数
{
GameManager.instance.RestratScene();//调用GameManager的重开函数
}
}