Unity configuration file encapsulation

Unity configuration file encapsulation

Application Scenario

Several recent projects need to read some configuration from the configuration file and then do some processing. So there was the idea of ​​reading and writing XML configuration files, and finally realized the following package:

how to use

  1. initialization
void Config.Init( string path, string rootNodeName );

Initial configuration file system
path: Path to the XML configuration file.
rootNodename XML root node name

For example:

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

Obtain node attribute
node: node name (can include path)
attr: attribute name
def: when the acquisition fails, return a default value.

For example:

[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. Get nodes, get attributes (2)
    Sometimes, it is necessary to continuously read multiple attributes under the same node. For example, in the above example of setting resolution, multiple attributes such as width, height, and fullScreen of the same Screen node are continuously read. different attributes. At this time, you can use the following API.
XmlElement Config.GetNode( string nodePath, bool bIsCreate=false ); 

nodePath specifies the node path to get, for example: "Screen", or a deeper path: "Setup/Comm/Screen".
bIsCreate means that if the specified path does not exist, try to create it automatically.

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

Node gets the extension of attributes

For example:

[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. Set node properties
void Config.SetAttribute( string node, string attr, string val );
void SetAttribute( this XmlElement node, string attr, string val );

Sometimes it is not only necessary to read the configuration file, but sometimes it is necessary to automatically modify the configuration file, so there needs to be a method for setting properties.
5. Access InnerText

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

bForce indicates whether to force saving. The default is false, that is, only when the content of the configuration file is changed, it will be saved, otherwise nothing will be done. When bForce is set to true, even if the content has not changed, it is still forced to save.

  1. Enumerate child nodes:
    The following is a simple example of enumerating child nodes and loading node configuration (loading a dynamic scrolling map):
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>

full code

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);
        }
    }
}

Guess you like

Origin blog.csdn.net/sdhexu/article/details/122931431