RPG游戏《黑暗之光》流程介绍与代码分析之(九):技能系统的实现

第九章 技能系统

与物品系统类似,技能系统也是一个较为复杂的系统,其中UI设计部分涉及到一些新知识,进行重点学习。

9.1 物品信息管理系统

技能管理系统的大致操作与背包系统类似。

9.1.1 技能信息的设计

技能信息的保存格式如下

我们在Atlas中新创建一个记事本存储技能信息,与物品信息类似,命名为SkillInfoInList,内容如下(部分信息进行了修改)
5001,魔法弹,skill-09,伤害 350%,SingleTarget,Attack,350,0,20,10,Magician,1,Enemy,5
5002,治疗,skill-13,治愈30HP,Passive,HP,30,0,10,20,Magician,2,Self,0
5003,冥想,skill-10,魔法恢复20,Passive,MP,20,0,0,30,Magician,5,Self,0
5004,法力涌动,skill-05,攻击力为200%持续15秒,Buff,Attack,200,15,30,30,Magician,7,Self,0
5005,战斗热诚,skill-12,攻击力速度为200%持续30,Buff,AttackSpeed,200,30,30,30,Magician,8,Self,0
5006,究极风暴,skill-11,攻击力400% 所有敌人,MultiTarget,Attack,400,0,50,40,Magician,9,Position,10
为了便于管理物品信息和技能信息,我们新建一个TextInfo来存储这两个txt文档

9.1.2 实现技能信息的读取

与ObjectsInfo类似,我们在GameSetting中添加一个SkillsInfo以访问读取技能信息,在脚本中设定各种属性
    public enum ApplyRole{    //适用角色
        Swordman,
        Magician
    }

    public enum ApplyType{    //适用类型
        Passive,
        SingleTarget,
        MultiTarget
    }

    public enum ApplyProperty{    //适用属性
        Attack,
        Aefense,
        AttackSpeed,
        HP,
        MP
    }

    public enum ReleaseType{    //释放类型,对自身,敌人(需要鼠标指定)和某个位置(鼠标指定)
        Self,
        Enemy,
        Position
    }
    public class SkillInfo{    //技能信息表中对应的各条属性
        public int id;
        public string name;
        public string icon_name;
        public string des;
        public ApplyType applyType;
        public ApplyProperty applyProperty;
        public int applyValue;
        public int applyTime;
        public int mpCost;
        public int coldTime;
        public ApplyRole applyRole;
        public int level;
        public ReleaseType releaseType;
        public float releaseDistance;

    }
在SkillsInfo中,将技能信息存入字典的操作如下
    public static SkillsInfo _instance;
    public TextAsset skillInfoListText;
    private Dictionary<int,SkillInfo> skillInfoDict = new Dictionary<int,SkillInfo>();

    void Awake()
    {
        _instance = this;
        ReadInfo ();
    }
其中ReadInfo ()的实现可参考物品信息(见背包系统),再提供一个外部的访问接口,通过这个接口即可访问id对应的技能信息
    public void GetSkillInfoListText(int id)
    {
        SkillInfo skillInfo = null;
        skillInfoDict.TryGetValue (id, out skillInfo);
        return skillInfo;
    }

9.2 UI界面的设计

9.2.1 基础技能界面的创建

在界面中新建一个Scroll View存储所有的技能,以及一组Invisible Widget用来显示单个技能,如下图所示。在Invisible Widget下再创建两个Sprite,一个用来显示技能图标,另一个作为技能描述的背景。
在技能描述中,再新建4个Label,显示其余信息,完成后如下图所示。完成之后,将其保存为Prefab,之后根据不同职业动态添加技能栏信息。

为了实现技能拖拽到快捷栏的效果,在SkillItem中加上Box Collider与Drag Scroll View。

在运行时即可实现上下拖动的效果,这么拖动显然不方便,我们在技能栏的右边加入一个滚动条(可以搜索control),设置一下Depth即可

之后指定一下SkillGrid中ScrollView中的Scroll Bar即可

我们将预先设置好的Grid大小设置为单个技能的大小

可以通过Grid可以直接对技能进行排序,将SkillItem拖放到Prefabs之下
为了管理SkillItem的内容,我们为其添加一个SkillItem的脚本,代码如下
   void InitProperty()
    {
        iconName = transform.Find ("IconName").GetComponent<UISprite> ();    //找到每个Sprite/Label的对应控件
        name_label = transform.Find ("Property/Name").GetComponent<UILabel> ();
        skillType_label = transform.Find ("Property/SkillType").GetComponent<UILabel> ();
        skillDes_label = transform.Find ("Property/SkillDes").GetComponent<UILabel> ();
        cost_label = transform.Find ("Property/Cost").GetComponent<UILabel> ();
    }

    void SetId(int id)    //初始化并在外部调用,进行创建,更新显示
    {
        InitProperty ();
        this.id = id;
        info = SkillsInfo._instance.GetSkillInfoFromDict (id);
        iconName.spriteName = info.icon_name;
        name_label.text = info.name;

        switch (info.applyType)
        {
            case SkillsInfo.ApplyType.Passive:
                skillType_label.text = "增益";
            break;
            case SkillsInfo.ApplyType.Buff:
                skillType_label.text = "增强";
            break;
            case SkillsInfo.ApplyType.SingleTarget:
                skillType_label.text = "单体";
            break;
            case SkillsInfo.ApplyType.MultiTarget:
                skillType_label.text = "群体";
            break;
        }
        skillDes_label.text = info.des;
        cost_label.text = info.mpCost.ToString();
    }
通过判断当前角色是魔法师或者剑士,我们选择不同的技能列表,在Skill脚本中
    public int[] MagicianSkillList;
    public int[] SwordmanSkillList;
    private PlayerStatus ps;
    void Start()
    {
        ps = GameObject.FindGameObjectWithTag (Tags.player).GetComponent<PlayerStatus> ();
        int[] idList = null;
        switch (ps.role)
        {
        case playerRole.Magician:
            idList = MagicianSkillList;
            break;
        case playerRole.Swordman:
            idList = SwordmanSkillList;
            break;
        }
    }
其中MagicianSkillList和SwordmanSkillList的设置根据 SkillInfoInList得到

在确定当前角色后,我们调用SetId方法创建技能面板,在Skill脚本中,添加
    public UIGrid grid;    //控制所有技能创建的网格,控制所有skillItemPrefab
    public GameObject skillItemPrefab;    //单个技能面板
    void Start()
    {
        foreach (int id in idList)    //遍历idList之中的id信息
        {
            GameObject itemGO = NGUITools.AddChild(grid.gameObject,skillItemPrefab);    //对于每一个id,在grid之中添加技能信息的Prefab
            grid.AddChild(itemGO.transform);
            itemGO.GetComponent<SkillItem>().SetId(id);    //调用SetId方法,更改技能的显示
        }
    }
即可创建出技能栏的内容,如下所示。

9.2.2 技能的拖拽功能

为SkillItem下的IconName添加脚本SkillItemIcon,控制拖动效果,勾选Clone On Drag。将SkillItemIcon脚本继承自UIDragDropItem,以实现拖拽功能。(需删除Start()方法和Update()方法,否则会出错),如下所示,但此时无法拖拽出技能栏。

因此我们需要让克隆的图标按钮能够移出ScrollView,在SkillItemIcon中添加
public class SkillItemIcon : UIDragDropItem{
    protected override void OnDragDropStart ()
    {
        base.OnDragDropStart ();
        transform.parent = transform.root;    //把父类放到UI root下
        this.GetComponent<UISprite> ().depth = 40;
    }
}
对6个快捷栏添加box collider,并将它们的标签设置为ShortCut,在SkillItemIcon中,通过如下代码得到id
    public int skillId;
    skillId = transform.parent.GetComponent<SkillItem> ().id;
之后通过OnDragDropRelease函数实现随意拖拽效果
    protected override void OnDragDropRelease (GameObject surface)
    {
        base.OnDragDropRelease (surface);
        if (surface != null && surface.tag == Tags.shortcutItem)
        {
            surface.GetComponent<Shortcut>().SetSkill(skillId);    //实现设置技能的效果,下节实现
        }
    }

9.3 技能的快捷方式

我们创建一个Invisible Widget用以存储技能栏的快捷方式,通过快捷方式我们可以方便地使用技能。在Invisible Widget中新建6个Sprite,命名为Shortcut1~6,用以存储这6个技能,为1~6的快捷方式建立Shortcut脚本,在每个Sprite下创建Child Label作为数字提示(做成Prefab可能更好),如下所示

在拖拽的时候,我们需要创建技能图标,因此在Shortcut1~6中创建Child Sprite作为技能显示图标,并且由于技能快捷栏开始是不显示的, 设置它的active为false。并且我们增加id和info用以读取字典中技能的信息,在SkillItemIcon中通过调用Shortcut中的SetSkill完成,其中SetSkill函数如下
    public enum ShortType{    
        Skill,
        Null
    }
    private ShortType type = ShortType.Null;    //默认为Null,即默认情况下按下快捷键不显示
    private int id;
    private SkillsInfo.SkillInfo info;
    public void SetSkill(int id)    //外界进行调用
    {
        type = ShortType.Skill;
        this.id = id;
        this.info = SkillsInfo._instance.GetSkillInfoFromDict (id);
        icon.spriteName = info.icon_name;
    }
即可将技能拖入快捷方式之中。

9.4 人物等级对技能的限制


接下来考虑任务等级对技能的影响,当人物等级小于技能要求等级时,无法使用拖动技能按钮,因此对SkillItem的Prefab添加Child Sprite,里面储存禁用技能的图标。在SkillItem脚本中添加并在初始化中设置为隐藏。
    private GameObject iconMask;
    iconMask.SetActive (false);
    void InitProperty()
    {
        iconMask = transform.Find ("IconMask").gameObject;
    }
之后设置一个实时根据等级信息改变技能显示与否的功能函数,当每次点击功能面板的技能图标时调用
    public void UpdateItem(int level)    //level从别的函数调用,判断当前等级
    {
        if (level < info.level)    //info.level对应技能等级,当前等级小于技能等级时,显示iconMask并禁用拖拽功能
        {
            iconMask.SetActive (true);    
            iconName.GetComponent<SkillItemIcon> ().enabled = false;    
        } else
        {
            iconMask.SetActive (false);    
            iconName.GetComponent<SkillItemIcon> ().enabled = true;    
        }
    }
调用位置在Skill脚本中,添加调用UpdateItem(int level)的函数,如下
    public void UpdateShow()
    {
        SkillItem[] items = this.GetComponentsInChildren<SkillItem> ();
        foreach (SkillItem item in items)
        {
            item.UpdateItem(ps.level);
        }
    }
之后在void Show()中调用,即
    void Show()
    {
        isShow = true;
        this.gameObject.SetActive (true);
        UpdateShow ();    //调用 UpdateShow ();
        tween.PlayForward ();
    }
即可实现该功能


猜你喜欢

转载自blog.csdn.net/s1314_jhc/article/details/80000268
今日推荐