上一节中我们了解了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();
}
}
}