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 ();
    }
即可實現該功能


發佈了96 篇原創文章 · 獲贊 140 · 訪問量 23萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章