使用ScriptableObject 打造一個卡牌存儲器

上一節中我們瞭解了ScriptableObject的用法,這一節讓我們來實現一個卡牌存儲器。
使用了我很喜歡的遊戲殺戮尖塔的設計和素材{{xieyanxiao}}。


設計理念

不知道大家有沒有玩過殺戮尖塔,示例卡牌如下。
在這裏插入圖片描述
我們可以看到,一張卡牌包括名稱消耗類型描述卡牌背景卡牌底圖等部分構成,而且在遊戲中,玩家的屬性可以影響到卡牌的強度,如玩家的力量可以提升卡牌的傷害,玩家的敏捷可以提升玩家獲得護甲的多少。
我遵從殺戮尖塔的設計,製作瞭如下的卡牌編輯器,實現了,數據可視化存儲,並且讓卡牌強度與玩家掛鉤,使用這個存儲器可以創建任意數據的卡牌。

設計思考

卡牌應當具有可加成的數值和不可加成的數值,在設計時我將用大寫字母佔位代表可加成數值,小寫字母佔位代表不可加成數值。
可加成數值需要從玩家Asset來提取數值。
不論是可加成還是不可加成佔位,都將在使用時被替換成具體的數值。

效果預覽

在這裏插入圖片描述
卡牌存儲器從上自下可以分成材質,數據,處理三個部分。

  • 材質:存儲卡牌的卡面,類型,品質等。
  • 數據:存儲卡牌的名稱,能力消耗,表達式,描述,基礎數據,玩家加成數據等。
  • 處理:讀入數據和加載入玩家數據。

代碼實現

在項目中我試用了NaughtyAttributes來對檢視面板數據做進一步處理,詳細NaughtyAttributes可查看github

PlayerAsset.cs

using System.Collections.Generic;
using System.Linq;
using NaughtyAttributes;
using UnityEngine;

namespace Asset
{
    [CreateAssetMenu(fileName = "NEW PlayerAsset", menuName = "MyAsset/PlayerAsset", order = 0)]
    public class PlayerAsset : ScriptableObject
    {

        public int maxHp;
        public int currentHp;
        public int strength;
        public int agility;
        private static PlayerAsset _instance;
        public static PlayerAsset Instance
        {
            get
            {
                if (!_instance)
                {
                   _instance = Resources.FindObjectsOfTypeAll<PlayerAsset>().FirstOrDefault();;
                }
                if (_instance) return _instance;
                _instance= CreateInstance<PlayerAsset>();
                _instance.hideFlags = HideFlags.DontSave;

                return _instance;
            }
            private set => _instance = value;
        }

    }
}

CardAsset.cs

using System;
using System.Collections.Generic;
using System.Linq;
using NaughtyAttributes;
using UnityEngine;
using UnityEngine.Serialization;

namespace Asset
{
    /// <summary>
    /// 卡牌類型
    /// </summary>
    public enum CardType
    {
        Attack,
        Skill,
    }

    public enum CardQuality
    {
        Write,
        Blue,
        Yellow
    }

    [Serializable]
    public class DictData
    {
        public char key;
        public int data;

        public DictData(char key,int data)
        {
            this.key = key;
            this.data = data;
        }
    }

    [CreateAssetMenu(fileName = "NewCard", menuName = "MyAsset/CardAsset", order = 0)]
    public class CardAsset : ScriptableObject
    {
        [BoxGroup("材質")] public CardType cardType;
        [BoxGroup("材質")] public CardQuality cardQuality;
        [BoxGroup("材質")] [ShowAssetPreview()] public Sprite cardSprite;

        [BoxGroup("數據")] [MinValue(0), MaxValue(5), Tooltip("消耗")]
        public int expend;

        [BoxGroup("數據")] public string title;

        [BoxGroup("數據")] [ResizableTextArea] public string express;
        [BoxGroup("數據")] [ResizableTextArea] public string desc;

        [BoxGroup("數據"),Label("基礎數據")] [ReorderableList] public DictData[] dictData;
        [BoxGroup("數據"),Label("玩家加成數據")] [ReorderableList] public List<DictData> dictAddData;
        /// <summary>
        /// 寫入配置
        /// </summary>
        [Button("寫入配置")]
        public void InitCardAsset()
        {
            desc = string.Empty;
            //字典方式
            foreach (var i in express)
            {
                var currChar = i + "";
                foreach (var t in dictData)
                {
                    if (!t.key.Equals(i)) continue;

                    var addValue = 0;    //加成值
                    //判斷該數據是否需要被加成
                    if (t.key>='A'&&t.key<='Z')
                    {
                        addValue = dictAddData.FirstOrDefault(m => m.key == t.key).data;
                    }
                    currChar = t.data+addValue + "";
                    break;
                }

                desc += currChar;
            }
        }
        /// <summary>
        /// 更新卡牌
        /// </summary>
        [Button("寫入玩家加成數據")]
        public void UpdateCard()
        {
            dictAddData.Clear();
            dictAddData.Add(new DictData('X',PlayerAsset.Instance.strength));
            dictAddData.Add(new DictData('Y',PlayerAsset.Instance.agility));
            //X-玩家力量 Y-玩家敏捷
 Debug.Log(PlayerAsset.Instance.maxHp+"\t"+PlayerAsset.Instance.currentHp+"\t"+PlayerAsset.Instance.strength);
            //重寫
            InitCardAsset();
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章