前言:游戏内会有很多种物品。比如药品,道具,装备等等,每种道具也都具有不同的品质,一般游戏是从弱到强白,绿,蓝等等。每种不同的道具,点击出来的弹窗以也不是一样的。在这篇本人通过最近学习到的知识使用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自己定吧。
这样是因为找不到直接在配置直接配置图片的方法,所以暂时这样,之后如果找到方法的话还是直接都写在配置比较好
三、制作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;
}
}
}
3、最简单的一步,把控件直接拖到文件夹里就行了,如图
脱出的话任何文件夹都可以,具体看要求吧,一般都会统一放一个文件夹
四、应用ItemIcon的预制件
应用的话就结合上次所学的Scroll Rect做个类似于包裹的东西吧,自动生成一些指定物品,通过ItemID生成对应的Icon。
1、Scroll Rect组件设置如下
这里没什么标准,可以根据自己兴趣设置
2、BagList组件设置如下
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组件设置如下
4、Creat0Button组件设置如下
这几个Button设置都差不多,就传进去的ItemID不一样
五、运行,点击Icon
效果图就不献丑了,没有美术支持,自己随便弄的图片,不敢发。建议代码不要全部Copy,最好是自己可以开拓一下思路扩展更多的功能
点击Icon会弹出以下Log,不同的Icon会有不同的属性
当然真正的游戏点击物品不可能打印一下Log就行了,只是到这的话差不多基础的一些东西都具备了,包括读取策划写的配置,把这些配置都应用起来。至于点击不同类型的物品弹出不同的窗口这些想必到这都会做了,无非就是加一个类型判断然后在对弹窗做一些设置。以及根据不同的品质显示不同的字色,以及各色各样的品质框以及其他品质特征这些都可以像弹窗一样通过判断在之后做出来