Unity3D---UGUI---简单的实现一个游戏内物品通用Icon功能

前言:游戏内会有很多种物品。比如药品,道具,装备等等,每种道具也都具有不同的品质,一般游戏是从弱到强白,绿,蓝等等。每种不同的道具,点击出来的弹窗以也不是一样的。在这篇本人通过最近学习到的知识使用UGUI简单实现一下该功能
在该篇文章中你能学到的有:C#的Xml文件读取,Prefabs(预制件)的生成与使用,对配置的应用,以及各个不同模块之间的调用

一、首先我们先准备一份配置

(开发中配置都是由策划配置,因为只是自学,所以自己随便捣鼓了一份)
如下:文件名为Icon.xml(命名没有讲究的,自己喜欢就好)

<?xml version="1.0" encoding="utf-8"?>
<IconXml>
<!--                             类型: 1:装备    品质:  1:白 
                                        2:道具           2:绿
                                        3:药品           3:蓝
                                                          4:紫
                                                          5:金
 -->
    <data ItemID="0" ImageID="0" Type="1"       Quality="1"/>
    <data ItemID="1" ImageID="1" Type="1"       Quality="2"/>
    <data ItemID="2" ImageID="2" Type="3"       Quality="3"/>
    <data ItemID="3" ImageID="3" Type="3"       Quality="4"/>
    <data ItemID="4" ImageID="4" Type="2"       Quality="5"/>
    <data ItemID="5" ImageID="5" Type="2"       Quality="4"/>
    <data ItemID="6" ImageID="6" Type="2"       Quality="3"/>
</IconXml>

可能有人觉得物品作为游戏的核心之一,配置选项有点少,为什么配置的格式是xml,再次强调 简单实现!!!

二、读取配置

xml读取不用多说,一找一大堆一大片的那种。下面直接贴代码了(其实不太想贴,有些东西自己一点一点写出来,远远比Copy别人的强的多,也更有成就感)。有人要是想使用Excel也可以在网上找教程

using System.Collections.Generic;
using UnityEngine;
using System.Xml;
using System;
namespace ICON
{
    public struct IconData
    {
        public int Quality;
        public int Type;
        public int ItemID;
        public int ImageID;
        public Sprite sprite;
    };
    public class Icon : MonoBehaviour
    {
        public List<Sprite> SpriteList;
        private List<IconData> IconXmlList = new List<IconData>();
        private bool LoadOver = false;
        void Start()
        {
            LoadIconXml();
        }
        public void LoadIconXml()
        {
            XmlDocument xml = new XmlDocument();
            XmlReaderSettings settings = new XmlReaderSettings
            {
                IgnoreComments = true         //忽略文档里面的注释
            };
            XmlReader reader = XmlReader.Create("./Assets/XmlData/Icon.xml", settings);
            xml.Load(reader);
            if (xml != null)
            {
                IconXmlList.Clear();
                XmlNode node = xml.SelectSingleNode("IconXml");
                XmlNodeList list = node.ChildNodes;
                foreach (XmlNode NodeData in list)
                {
                    IconData iconData = new IconData();
                    XmlElement info = (XmlElement)NodeData;
                    iconData.ItemID = Convert.ToInt32(info.GetAttribute("ItemID"));
                    iconData.ImageID = Convert.ToInt32(info.GetAttribute("ImageID"));
                    iconData.Type = Convert.ToInt32(info.GetAttribute("Type"));
                    iconData.Quality = Convert.ToInt32(info.GetAttribute("Quality"));
                    if (iconData.ImageID < SpriteList.Count)
                    {
                        iconData.sprite = SpriteList[iconData.ImageID];
                    }
                    else
                    {
                        iconData.sprite = SpriteList[0];
                    }
                    IconXmlList.Add(iconData);
                }
            }
            LoadOver = true;
        }
        public Sprite GetItemSprite(int ItemID)
        {
            if (LoadOver)
            {
                foreach (IconData data in IconXmlList)
                {
                    if (data.ItemID == ItemID)
                    {
                        return data.sprite;
                    }
                }
                Debug.Log("ItemID  未找到相应资源配置");
                return null;
            }
            else
            {
                Debug.Log("Icon.xml  资源未读取完毕");
                return null;
            }
        }
        public Sprite GetItemSprite()
        {
            System.Random Ra = new System.Random();
            int ItemID = Ra.Next(0, IconXmlListCount());
            return GetItemSprite(ItemID);
        }
        public int IconXmlListCount()
        {
            return IconXmlList.Count;
        }
        public IconData? GetIconDataByItemID(int itemid)
        {
            if (LoadOver)
            {
                foreach (IconData data in IconXmlList)
                {
                    if (data.ItemID == itemid)
                    {
                        return data;
                    }
                }
                Debug.Log("ItemID  未找到相应资源配置");
                return null;
            }
            else
            {
                Debug.Log("Icon.xml  资源未读取完毕");
                return null;
            }
        }
    }
}

创建一个空对象,把Icon.cs放进去,添加几个Sprite 如下图 size自己定吧。
这样是因为找不到直接在配置直接配置图片的方法,所以暂时这样,之后如果找到方法的话还是直接都写在配置比较好


image.png

三、制作ItemIcon的预制件(Prefabs)

预制件的制作我在这简单说一下吧
预制件其实就是把你在UGUI中自定义的控件导出去。然后通过代码、Unity3D编辑器 在其他得任何地方进行重复的使用
导出的方法很简单,直接把你想做成预制件的控件拖到项目里面的Prefabs文件夹(当然任何文件夹都可以,不过还是规范一点比较好)

一个小提示,如果是预制件Inspector下的那个三色立方体会变成蓝色的

1、右键创建一个Image的控件(记得别把Raycast Target取消勾选了,不然点击事件会出问题)

2、创建一个C#脚本

我在里面主要实现了按下,抬起事件,以及把配置文件的物品信息储存到对应每个物品的Icon。简单实现就不弄这么多了,这个其实也只是大概的框架,一个思路。还有很多种写法有很多种方式。比如按下时可以通过ItemID调取Icon.cs的GetIconDataByItemID()函数取出物品的信息,就可以省去SetIconData()这一步了

脚本好了之后可以直接拖到控件里面就行了

using UnityEngine;
using UnityEngine.EventSystems;
using ICON;

public class ItemIcon : MonoBehaviour,IPointerDownHandler,IPointerUpHandler
{
    // Use this for initialization
    private int ItemID = -1;
    private int EventTag = -1;
    private bool IsActive = true;
    private Vector2 DownPos;
    private Vector2 UpPos;
    private IconData Data;
    void Start () {

    }
    public void SetItemID(int ID)
    {
        ItemID = ID;
    }
    public void SetTag(int Tag)
    {
        EventTag = Tag;
        Debug.Log("SetTag = " + EventTag);
    }
    public void OnPointerDown(PointerEventData data)
    {
        DownPos = data.position;
        Debug.Log("OnPointerDown::Tag = " + EventTag + "   类型 = " + Data.Type + "    ItemID = " + Data.ItemID + "    品质 = " + Data.Quality);
    }
    public void OnPointerUp(PointerEventData data)
    {
        UpPos = data.position;
        if(DownPos == UpPos)
        {
            Debug.Log("OnPointUp::SetTag = " + EventTag);
        }    
    }
    public void SetIconData(IconData? data)
    {
        if (data != null)
        {
            Data = (IconData)data;            
        }        
    }
}
image.png

3、最简单的一步,把控件直接拖到文件夹里就行了,如图

脱出的话任何文件夹都可以,具体看要求吧,一般都会统一放一个文件夹

image.png

四、应用ItemIcon的预制件

应用的话就结合上次所学的Scroll Rect做个类似于包裹的东西吧,自动生成一些指定物品,通过ItemID生成对应的Icon。

1、Scroll Rect组件设置如下

这里没什么标准,可以根据自己兴趣设置


image.png

2、BagList组件设置如下

image.png

Bag脚本如下:
GameObject就是之前创建的那个空对象
ItemIcon就是拖出去的预制件,通过Instantiate调取

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using ICON;

public class Bag : MonoBehaviour
{
    public GameObject gameObject;
    public GameObject Prefab;
    private List<GameObject> ImageList = new List<GameObject>();
    private int Tag = 0;
    void Start () {
        gameObject.GetComponent<Icon>().LoadIconXml();
        for (int i = 0; i < 4; i++)
        {
            AddItemIcon(i);
        }
    }
    public void AddItemIcon(int ItemID)
    {
        GameObject Tempimage = Instantiate(Prefab);
        Tempimage.transform.SetParent(this.transform,true);
        if (ItemID < 0 || ItemID >= gameObject.GetComponent<Icon>().IconXmlListCount())
        {
            System.Random Ra = new System.Random();
            ItemID = Ra.Next(0, gameObject.GetComponent<Icon>().IconXmlListCount());
        }
        Tempimage.GetComponent<ItemIcon>().SetIconData(gameObject.GetComponent<Icon>().GetIconDataByItemID(ItemID));
        Tempimage.GetComponent<ItemIcon>().SetTag(Tag);
        Tempimage.GetComponent<ItemIcon>().SetItemID(ItemID);
        Tempimage.GetComponent<Image>().sprite = gameObject.GetComponent<Icon>().GetItemSprite(ItemID);
        Tempimage.transform.localPosition = new Vector3(0, 0, 0);
        Tempimage.transform.localScale = new Vector3(1,1,1);
        Tempimage.gameObject.SetActive(true);
        Tag++;
        ImageList.Add(Tempimage);
    }
}

3、Scrollbar组件设置如下

image.png

4、Creat0Button组件设置如下

这几个Button设置都差不多,就传进去的ItemID不一样


image.png

五、运行,点击Icon

效果图就不献丑了,没有美术支持,自己随便弄的图片,不敢发。建议代码不要全部Copy,最好是自己可以开拓一下思路扩展更多的功能
点击Icon会弹出以下Log,不同的Icon会有不同的属性


image.png

当然真正的游戏点击物品不可能打印一下Log就行了,只是到这的话差不多基础的一些东西都具备了,包括读取策划写的配置,把这些配置都应用起来。至于点击不同类型的物品弹出不同的窗口这些想必到这都会做了,无非就是加一个类型判断然后在对弹窗做一些设置。以及根据不同的品质显示不同的字色,以及各色各样的品质框以及其他品质特征这些都可以像弹窗一样通过判断在之后做出来

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容