当前位置: 首页 > article >正文

Unity类银河战士恶魔城学习总结(P152 Lost Currency Save拾取掉落的灵魂)

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

教程源地址:https://www.udemy.com/course/2d-rpg-alexdev/

本章节实现了死亡后拾取掉落的灵魂,同时给右上角的灵魂做了一个逐渐增加的效果

LostCurrencyController.cs

整体流程

  1. 游戏场景中会有丢失的灵魂(或货币),每个丢失灵魂对象都挂载了这个脚本。
  2. 当玩家的角色与丢失灵魂发生触碰(即进入碰撞触发器区域)时,触发 OnTriggerEnter2D 方法。
  3. 检查碰撞物体是否是玩家,如果是,则:
    • 增加玩家的货币或灵魂数量。
    • 销毁丢失灵魂的对象,从场景中移除该物体。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class LostCurrencyController : MonoBehaviour
{
    public int currency;


    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.GetComponent<Player>()!= null) 
        {
            PlayerManager.instance.currency += currency;//捡取灵魂
                Destroy(gameObject);
        }
    }
}

GameData.cs

主要作用是初始化数据

这个构造函数初始化了所有变量的默认值。它确保在创建 GameData 对象时,所有字段都有一个初始值,从而避免了未赋值的错误。

具体的初始化内容:

  • lostCurrencyX, lostCurrencyY, lostCurrencyAmount 都初始化为 0,表示初始时没有丢失的灵魂。
  • currency 初始化为 0,表示玩家一开始没有货币。
  • skillTree, inventory, checkpoints 使用 SerializableDictionary 进行初始化,确保它们是可序列化的,并且在后续存储和加载时不会出现空引用错误。
  • equipmentId 初始化为一个空的列表,表示玩家初始没有装备。
  • closestCheckpointId 初始化为空字符串,表示玩家一开始没有最近的检查点。
  • checkpoints 被初始化为一个空的字典,表示游戏开始时没有任何检查点。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;


//2024.11.25
[System.Serializable]
public class GameData
{
    public int currency;

    public SerializableDictionary<string, bool>skillTree;
    public SerializableDictionary<string, int> inventory;//物品的名字和数量
    public List<string> equipmentId;//装备的ID

    public SerializableDictionary<string, bool> checkpoints;//检查点的ID和激活状态
    public string closestCheckpointId;//最近的检查点ID

    public float lostCurrencyX;
    public float lostCurrencyY;
    public int lostCurrencyAmount;


    public GameData()
    {
        this.lostCurrencyX = 0;
        this.lostCurrencyY = 0;
        this.lostCurrencyAmount = 0;


        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>();   
    }
}

GameManager.cs

这段 GameManager 脚本负责游戏的核心管理任务,包括:

  • 玩家位置的管理。
  • 检查点和丢失灵魂的保存与加载。
  • 游戏数据的保存和恢复。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;


//2024.11.28 17:04
public class GameManager : MonoBehaviour, ISaveManager
{
    public static GameManager instance;//单例模式,全局变量

    private Transform player;//玩家的位置


    [SerializeField] private Checkpoint[] checkpoints;
    [SerializeField] private string closestCheckpointId;

    [Header("Lost Currency")]
    [SerializeField] private GameObject lostCurrencyPrefab;
    public int lostCurrencyAmount ;
    [SerializeField] private float lostCurrencyX;//丢失灵魂的位置
    [SerializeField] private float lostCurrencyY;


    private void Awake()
    {
        if (instance != null)
            Destroy(instance.gameObject);
        else
            instance = this;

        checkpoints = FindObjectsOfType<Checkpoint>();//查找所有的检查点
    }


    private void Start()
    {
        player = PlayerManager.instance.player.transform;
    }


    public void RestartScene()
    {
        SaveManager.instance.SaveGame();//保存游戏
        Scene scene = SceneManager.GetActiveScene();
        SceneManager.LoadScene(scene.name);
    }



    public void LoadData(GameData _data)=> StartCoroutine(LoadWithDelay(_data));


    private void LoadCheckpoint(GameData _data)//加载检查点
    {
        foreach (KeyValuePair<string, bool> pair in _data.checkpoints)//遍历数据中的检查点
        {
            foreach (Checkpoint checkpoint in checkpoints)//遍历场景中的检查点
            {
                if (checkpoint.id == pair.Key && pair.Value == true) //如果检查点的ID和数据中的ID相同且激活状态为真
                    checkpoint.ActivateCheckPoint();

            }
        }
    }



    private void LoadLostCurrency(GameData _data)//加载丢失的灵魂
    {
        lostCurrencyAmount = _data.lostCurrencyAmount;
        lostCurrencyX = _data.lostCurrencyX;
        lostCurrencyY = _data.lostCurrencyY;

        

        if (lostCurrencyAmount > 0)
        {
            GameObject newlostCurrency = Instantiate(lostCurrencyPrefab, new Vector3(lostCurrencyX, lostCurrencyY), Quaternion.identity);
            newlostCurrency.GetComponent<LostCurrencyController>().currency = lostCurrencyAmount;


        }

        lostCurrencyAmount = 0;//重置丢失的灵魂数量
    }



    private IEnumerator LoadWithDelay(GameData _data)//延迟加载,防止其他数据未加载
    {
        yield return new WaitForSeconds(.5f);

        LoadCheckpoint(_data);
        LoadClosetCheckpoint(_data);
        LoadLostCurrency(_data);       
    }




    public void SaveData(ref GameData _data)
    {
        _data.lostCurrencyAmount = lostCurrencyAmount;
        _data.lostCurrencyX = player.position.x;
        _data.lostCurrencyY = player.position.y;

        

        if (FindClosestCheckpoint() != null)//如果最近的检查点不为空
            _data.closestCheckpointId = FindClosestCheckpoint().id;//将最近的检查点ID存入数据


        _data.checkpoints.Clear();

        foreach (Checkpoint checkpoint in checkpoints)
        {
            _data.checkpoints.Add(checkpoint.id, checkpoint.activationStatus);//将检查点的ID和激活状态存入数据
        }

        
    }



    private void LoadClosetCheckpoint(GameData _data)//将玩家放在最近的检查点
    {
        if(_data.closestCheckpointId == null)
            return;


        closestCheckpointId = _data.closestCheckpointId; ;//将最近检查点ID存入变量

        foreach (Checkpoint checkpoint in checkpoints)
        {
            if (closestCheckpointId == checkpoint.id)
                player.position = checkpoint.transform.position;
        }
    }


    private Checkpoint FindClosestCheckpoint()//找到最近的检查点
    {
        float closestDistance = Mathf.Infinity;//正无穷
        Checkpoint closestCheckpoint = null;

        foreach (var checkpoint in checkpoints)//遍历所有的检查点
        {
            float distanceToCheckpoint = Vector2.Distance(player.position, checkpoint.transform.position);//计算玩家和检查点之间的距离

            if (distanceToCheckpoint < closestDistance && checkpoint.activationStatus == true)//如果距离小于最近距离且检查点激活
            {
                closestDistance = distanceToCheckpoint;//更新最近距离
                closestCheckpoint = checkpoint;//更新最近检查点
            }

        }
        return closestCheckpoint;
    }
}

UI_InGame.cs

增加了更新灵魂值得效果,可以更改增加得速率

using UnityEngine;
using UnityEngine.UI;
using TMPro;


//2024年11月22日
public class UI_InGame : MonoBehaviour
{
    [SerializeField] private PlayerStats playerStats;//存储玩家的状态信息
    [SerializeField] private Slider slider;//显示玩家血量

    [SerializeField] private Image dashImage;
    [SerializeField] private Image parryImage;
    [SerializeField] private Image crystalImage;
    [SerializeField] private Image swordImage;
    [SerializeField] private Image blackholeImage;
    [SerializeField] private Image flaskImage;

    private SkillManager skills;


    [Header("Souls info")]
    [SerializeField] private TextMeshProUGUI currentSouls;
    [SerializeField] private float soulsAmount;
    [SerializeField] private float increaseRate ;//灵魂值增长速度



    void Start()
    {
        if(playerStats != null) 
            playerStats.onHealthChanged += UpdateHealthUI;

        skills = SkillManager.instance;
    }

    
    void Update()
    {
        UpdataSoulsUI();

        if (Input.GetKeyDown(KeyCode.LeftShift) && skills.dash.dashUnlocked)
            SetCooldownOf(dashImage);

        if (Input.GetKeyDown(KeyCode.Q) && skills.parry.parryUnlocked)
            SetCooldownOf(parryImage);

        if (Input.GetKeyDown(KeyCode.F) && skills.crystal.crystalUnlocked)
            SetCooldownOf(crystalImage);

        if (Input.GetKeyDown(KeyCode.Mouse1) && skills.sword.swordUnlocked)
            SetCooldownOf(swordImage);

        if (Input.GetKeyDown(KeyCode.R) && skills.blackhole.blackHoleUnlocked)
            SetCooldownOf(blackholeImage);

        if (Input.GetKeyDown(KeyCode.Alpha1) && Inventory.instance.GetEquipment(EquipmentType.Flask) != null)//必须获取药水
            SetCooldownOf(flaskImage);



        CheckCoolDownOf(dashImage, skills.dash.cooldown);
        CheckCoolDownOf(parryImage, skills.parry.cooldown);
        CheckCoolDownOf(crystalImage, skills.crystal.cooldown);
        CheckCoolDownOf(swordImage, skills.sword.cooldown);
        CheckCoolDownOf(blackholeImage, skills.blackhole.cooldown);
        CheckCoolDownOf(flaskImage, Inventory.instance.flaskCoolDown);
    }

    private void UpdataSoulsUI()//更新灵魂值
    {
        if (soulsAmount < PlayerManager.instance.GetCurrency())
        {
            soulsAmount += increaseRate * Time.deltaTime;

        }
        else
            soulsAmount = PlayerManager.instance.GetCurrency();

        currentSouls.text = ((int)soulsAmount).ToString();
    }

    private void UpdateHealthUI()//更新血条值
    {
        slider.maxValue = playerStats.GetMaxHealthValue();
        slider.value = playerStats.currentHealth;
    }


    private void SetCooldownOf(Image _image)//设置技能冷却时间动画
    {
        if (_image.fillAmount <= 0)
            _image.fillAmount = 1;
    }

    private void CheckCoolDownOf(Image _image,float _coolDown)
    {
        if (_image.fillAmount > 0)
            _image.fillAmount -= 1 / _coolDown * Time.deltaTime;//调整转的速度
    }

}


http://www.kler.cn/a/419299.html

相关文章:

  • TCP/IP 和 UDP
  • Linux网络_网络协议_网络传输_网络字节序
  • Java 解析离线 MySQL binlog 文件
  • Git命令大全(超详细)
  • Doge东哥wordpress主题
  • 系统架构:MVVM
  • 【RISC-V CPU debug 专栏 3 -- Debugging RISC-V Cores】
  • Web开发基础学习——HTML中id 和 class 标识和选择元素的属性的理解
  • HCIE IGP双栈综合实验
  • scala之全文单词统计
  • SQLServer如何导入数据库
  • Lumos学习王佩丰Excel第十七讲:数学函数
  • 如何在WPF中打印PDF文件
  • CAD深度清理工具-AVappsDrawingPurge9.0.0(2024.8.27版本) 支持版本CAD2022-2025-供大家学习研究参考
  • 挑战用React封装100个组件【007】
  • LabVIEW实现串口调试助手
  • Linux驱动开发基础(有源蜂鸣器模块)
  • 跨地域 SD-WAN 网络专线解决方案
  • RabbitMq死信队列(详解)
  • 构建鸿蒙5.0应用(一)
  • 13 设计模式之外观模式(家庭影院案例)
  • JavaScript(JS)的对象
  • 「Qt Widget中文示例指南」如何为窗口实现流程布局?(二)
  • python:windows无法使用cx_Oracle模块
  • 【k8s深入理解之 Scheme 补充-4】理解资源的内外部版本(存放位置不同、版本转换函数自动生成、版本新增字段等)
  • C++11(下)