上一節中我們瞭解了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();
}
}
}