Unity配置文件封装

Unity配置文件封装

应用场景

最近做的几个项目,都需要从配置文件中读取一些配置,然后做一些处理。于是就有了读写XML配置文件的想法,最终实现了如下封装:

如何使用

  1. 初始化
void Config.Init( string path, string rootNodeName );

初始化配置文件系统
path:XML配置文件的路径。
rootNodename XML根节点的名称

例如:

Config.Init(Path.Combine(Application.streamingAssetsPath, "config.xml"), "Demo");
  1. 获取属性
T Config.GetAttribute<T>( string node, string attr, T def );

获取节点属性
node:节点名(可以带路径)
attr:属性名
def:当获取失败时,返回一个默认的值。

例如:

[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSplashScreen)]
private static void SetScreenResolution()
{
    
    
	Config.Init(Path.Combine(Application.streamingAssetsPath, "config.xml"), "Demo");
	int w = Config.GetAttribute<int>("Screen", "width", 1920 );
	int h = Config.GetAttribute<int>("Screen", "height", 1080 );
	bool f = Config.GetAttribute<bool>("Screen", "fullScreen", true);
	Screen.SetResolution(w, h, f);
}
  1. 获取节点,获取属性(2)
    有时候,需要连续读取同一个节点下的多个属性,比如上述设置分辨率的例子中,连续读取了同一个Screen节点的width、height、fullScreen等多个不同属性。这时候,就可以使用下面的API。
XmlElement Config.GetNode( string nodePath, bool bIsCreate=false ); 

nodePath指定要获取的节点路径,比如:“Screen”,或更深的路径:“Setup/Comm/Screen”。
bIsCreate表示如果不存在指定的路径,则尝试自动创建它。

T GetAttribute<T>( this XmlElement node, string attr, T def );

节点获取属性的扩展

例如:

[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSplashScreen)]
private static void SetScreenResolution()
{
    
    
	Config.Init(Path.Combine(Application.streamingAssetsPath, "config.xml"), "Demo");

	XmlElement node = Config.GetNode("Screen");
	if( node != null )
	{
    
    
		int w = node.GetAttribute<int>("width", 1080);
		int h = node.GetAttribute<int>("height", 1920);
		bool f = node.GetAttribute<bool>("fullScreen", true);
		Screen.SetResolution(w, h, f);
	}
}
  1. 设置节点属性
void Config.SetAttribute( string node, string attr, string val );
void SetAttribute( this XmlElement node, string attr, string val );

有时候不仅仅需要读取配置文件,有时候还需要自动的修改配置文件,那就需要有设置属性的方法。
5. 访问InnerText

XmlElement node = Config.GetNode("Content/Pages");
if( node != null )
	UIText.text = node.InnerText;
  1. 保存
Config.Save( bool bForce = false );

bForce表示是否强制保存。默认为false,即只有配置文件内容被改变时,才会保存,否则什么也不做。当bForce被设置为true时,即便内容没有改变,仍然强制保存。

  1. 枚举子节点:
    下面是枚举子节点并加载节点配置的简单例子(加载动态滚动图):
private void Start()
{
    
    
	XmlElement node = Config.GetNode("Content");
	if( node != null )
	{
    
    
		Period = node.GetAttribute<float>("period", 10f);
        ScrollRect.ItemSpacing = node.GetAttribute<float>("spacing", 0);
        ScrollRect.SpacingColor = node.GetAttribute<Color>("color", Color.black);
        ScrollRect.Rate = Mathf.Clamp(node.GetAttribute<float>("rate", 0.15f), 0f, 1f);
        ScrollRect.Slide = node.GetAttribute<float>("slide", 2f);
        
		foreach( XmlNode child in node.ChildNodes )
		{
    
    
			if( child.NodeType == XmlNodeType.Element && child is XmlElement ele )
			{
    
    
				if (string.Compare(ele.Name, "Page", true) != 0)
					continue;

				string url = ele.GetAttributeString("url" );
				if( string.IsNullOrWhiteSpace(url) || (!File.Exists(url)))
					continue;

				CarouselItem item = Instantiate<CarouselItem>(itemPrefab, ScrollRect.Content);
				item.url = url;
			}
		}
	}
}
<?xml version="1.0" encoding="utf-8"?>
<Demo>
	<!--屏幕配置-->
	<Screen width="1080" height="1920" fullScreen="true" />
	
	<!--内容配置
		rate		滚动速度系数,0-1之间,越大速度越快
		slide		滑动速度系数(不等于0)
		spacing		分割条宽度
		color		分割条颜色
		period		每张图片停留展示时间(对视频无效,视频需播放完成)
	-->
	<Content rate="0.15" slide="3.0" spacing="20" color="#08353F" period="6">
		<Page url="e:/photos/100_0221.jpg" />
		<Page url="e:/temp/back.mp4" />
		<Page url="e:/temp/one.mp4" />
		<Page url="e:/temp/photos/100_0373.jpg" />
	</Content>
</Demo>

完整代码

using UnityEngine;
using System;
using System.IO;
using System.Xml;

namespace HXConfig
{
    
    
    public static class Config
    {
    
    
        private static XmlElement m_root = null;
        public static bool IsHasChanged {
    
     get; private set; } = false;
        public static string Path {
    
     get; private set; } = null;

        public static XmlElement CreateNode( string name )
        {
    
    
            if (m_root != null && m_root.ParentNode != null)
            {
    
    
                XmlDocument doc = m_root.ParentNode as XmlDocument;
                return doc.CreateElement(name);
            }
            else
                return null;
        }

        public static void Init( string path, string root = null )
        {
    
    
            if( m_root == null )
            {
    
    
                Path = path;
                XmlDocument doc = new XmlDocument();

                if ((!string.IsNullOrWhiteSpace(Path)) && File.Exists(Path))
                {
    
    
                    doc.Load(Path);
                    m_root = doc.DocumentElement;
                    IsHasChanged = false;
                }
                else
                {
    
    
                    XmlDeclaration xd = doc.CreateXmlDeclaration("1.0", "utf-8", null );
                    doc.AppendChild(xd);
                    if (string.IsNullOrWhiteSpace(root))
                        root = "root";
                    m_root = doc.CreateElement(root);
                    doc.AppendChild(m_root);
                    IsHasChanged = true;
                }
            }
        }

        public static void Save(bool bForce = false)
        {
    
    
            if (m_root != null && (!string.IsNullOrWhiteSpace(Path)) && m_root.ParentNode is XmlDocument doc && (bForce || IsHasChanged))
                doc.Save(Path);
        }


        public static void SetAttribute( string path, string attr, string val )
        {
    
    
            if (GetNode(path, true) is XmlElement xe)
            {
    
    
                xe.SetAttribute(attr, val);
                IsHasChanged = true;
            }
        }

        public static XmlElement GetNode(string path, bool bCreate = false )
        {
    
    
            if( bCreate)
            {
    
    
                XmlDocument doc = m_root.ParentNode as XmlDocument;
                XmlElement xe = m_root;
                foreach( var p in path.Split('/'))
                {
    
    
                    if (string.IsNullOrWhiteSpace(p))
                        continue;

                    if (xe.SelectSingleNode(p) is XmlElement c)
                        xe = c;
                    else
                    {
    
    
                        XmlElement n = doc.CreateElement(p);
                        xe.AppendChild(n);
                        xe = n;
                    }
                }
                return xe;
            }
            else
                return m_root.SelectSingleNode(path) as XmlElement;
        }

        public static string GetAttribute( string node, string attr, string def = null )
        {
    
    
            XmlElement n = GetNode(node);
            return (n == null) ? def : n.GetAttribute(attr);
        }

        public static T GetAttribute<T>(string node, string attr) where T : struct
        {
    
    
            XmlElement n = GetNode(node);
            return ( n == null ) ? default(T) : n.GetAttribute<T>(attr);
        }

        public static T GetAttribute<T>(string node, string attr, T def ) where T : struct
        {
    
    
            XmlElement n = GetNode(node);
            return (n == null) ? def : n.GetAttribute<T>(attr, def);
        }

        public static string GetAttributeString(this XmlElement node, string attr, string def = null)
        {
    
    
            return node.HasAttribute(attr) ? node.GetAttribute(attr) : def;
        }

        public static T GetAttribute<T>(this XmlElement node, string attr ) where T : struct
        {
    
    
            return GetAttribute<T>(node, attr, default);
        }

        public static T GetAttribute<T>(this XmlElement node, string attr, T def ) where T : struct
        {
    
    
            try
            {
    
    
                string s = node.GetAttribute(attr);
                if (typeof(T) == typeof(Vector3))
                    return (T)ConventVector3(s, def);
                else if (typeof(T) == typeof(Vector2))
                    return (T)ConventVector2(s, def);
                else if (typeof(T) == typeof(Color))
                    return (T)ConventColor(s, def);
                else
                    return (T)Convert.ChangeType(s, typeof(T));
            }
            catch
            {
    
    
                return def;
            }
        }

        private static object ConventVector3( string s, object def )
        {
    
    
            string[] vs = s.Split(',');
            if (vs.Length < 3)
                return (Vector3)def;
            float[] vf = new float[3];
            for (int i = 0; i < 3; ++i)
            {
    
    
                if (float.TryParse(vs[i], out float t))
                    vf[i] = t;
                else
                    return (Vector3)def;
            }
            return new Vector3(vf[0], vf[1], vf[2]);
        }

        private static object ConventVector2( string s, object def )
        {
    
    
            string[] vs = s.Split(',');
            if (vs.Length < 2)
                return (Vector3)def;
            float[] vf = new float[2];
            for (int i = 0; i < 2; ++i)
            {
    
    
                if (float.TryParse(vs[i], out float t))
                    vf[i] = t;
                else
                    return (Vector2)def;
            }
            return new Vector2(vf[0], vf[1] );
        }

        private static object ConventColor( string s, object def )
        {
    
    
            if (ColorUtility.TryParseHtmlString(s, out Color c))
                return c;
            else
                return (Color)(def);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/sdhexu/article/details/122931431
今日推荐