unity 读取xml解析xml耗费性能大吗

为什么用unity开发项目,大多数都用XML文件做为项目数据配置?---unity新人 - 知乎3被浏览316分享邀请回答16 条评论分享收藏感谢收起Unity3D研究院之使用 C#合成解析XML与JSON(四十一) - KiStar的博客
- CSDN博客
KiStar的博客3D姿势(8)
讲道理这是本宅第一次写原创技术文章,且文中全部内容均为本人拙劣的技术方法实现,若有各种疑问和错误,欢迎及时指正。
绝大部分有点规模的游戏都需要读取XML,且XML数量并不少,如果每次需要数据时就读一次那就太浪费资源了,而且性能也不好,所以我自己动手简单写了一个管理读取XML简单架构。
大致思路:首先建立一个读取XML的父类,继承的子类即所要读XML的实体类。使用WWW类获取XML路径,使用www.text得到XML内容,经过处理后把所得的东西存入一个Dictionary&Type,Object&中,以后需要用到XML中数据的时候,直接从Dictionary中调数据即可,而不需要重复的读XML了。
思路大致如此,下面贴点代码详细说明一下吧。
&span style=&font-size:14&&&?xml version=&1.0& encoding=&UTF-8& standalone=&yes&?&
&PlayerConfig&
&Player name=&伊沢ライオン& id=&1001& HP=&100& MP=&50& ATK=&10& DFN=&10& &
&skill&Q&/skill&
&skill&W&/skill&
&skill&E&/skill&
&skill&R&/skill&
&/PlayerConfig&&/span&↑↑↑↑↑这个是示例XML,我们就以读取这个为例。
&span style=&font-size:14&&using UnityE
using System.C
using System.Collections.G
public class Player
public List&Player& players=new List&Player&();
public List&Skill& skill=new List&Skill&();
public class Skill {
public string skillN
}&/span&↑↑↑↑↑↑这个是Player类,存数据的
&span style=&font-size:14&&using UnityE
using System.C
using System.Collections.G
public class DatabaseConfig
//判断是否为空
public virtual bool Read(string text) {
if (string.IsNullOrEmpty(text)) {
public class DefaultConfig {
//单例模式
private static DefaultC
public static DefaultConfig getInstance() {
if (instance == null) {
instance = new DefaultConfig();
public Dictionary&System.Type, DatabaseConfig& configDic = new Dictionary&System.Type, DatabaseConfig&();
public T GetConfigByType&T&() where T : DatabaseConfig {
//查找字典是否已有T类型的数据源
if (configDic.ContainsKey(typeof(T))) {
return configDic[typeof(T)] as T;
&/span&&span style=&font-size:18&&
&/span&↑↑↑↑↑↑这段是读取XML的父类和声明Dictionary的部分。其中父类只有一个Read()方法判断是否为空,因为在子类中还要override。
这里特别说明一下,我使用的Dictionary是&type,Object&方式存储的,key就是当前要存入字典中value对象的Type,使用typeof(ClassName)或者Object.getType()都可以得到。而value就是DatabaseConfig的对象。
下面还有一个判断是否已有T类型的key,如果有,就把它对应的value(即T类型的对象)返回去,实体类通过操作这个对象就可以获取Player的各种字段值了。
&span style=&font-size:14&&using UnityE
using System.C
using System.X
using System.Collections.G
public class PlayerConfig : DatabaseConfig{
Player player1 = new Player();
public override bool Read(string text){
if (base.Read(text) == false){
XmlDocument xmldoc = new XmlDocument();
xmldoc.LoadXml(text);
XmlElement rootElem = xmldoc.DocumentE
//读取根节点下面子节点的元素
XmlNodeList xmllist1 = rootElem.ChildN
//遍历所有根节点下面子节点的属性
foreach (XmlElement tempel1 in xmllist1){
Player tmpplayer1 = new Player();
tmpplayer1.name = tempel1.GetAttribute(&name&);
tmpplayer1.id = int.Parse(tempel1.GetAttribute(&id&));
//将当前Player记录到players链表下
player1.players.Add(tmpplayer1);
}&/span&&span style=&font-size:14&&
public Player GetPlayerByID(int id) {
if ( id&= 0) {
foreach (var player in player1.players) {
if (player.id == id) {
#endregion
}&/span&&span style=&font-size:18&&
&/span&↑↑↑↑↑↑这个就是继承于父类的一个实际读取XML的子类。中间一大部分都是C#中读取XML的代码,我就不多介绍了,可以搜索C#读取XML了解。我这里只获取了一个id、一个name做测试,其他字段都可以通过相同方法获取。
最下面写了一个功能函数,是在实际使用时调用的,就是通过判断id来获取player对象。
由于我个人水平极低,在我写代码的时候遇到如下一些低级问题,仅献给和我一样的初学者们,希望你们少走弯路。
1、GetPlayerByID函数找不到players
这是我第一个遇到的问题,而实际出问题的地方却并非多高端。players是Player类中的一个List,我最开始并没有把Player player1写在Read()函数外,而出了方法体player1找不到了,当然也就不可能在其他位置调用了。
2、存入players的数据为null
3、存入players的数据出错
上面两个问题也是困扰我半宿,都是围绕这个List展开的。我最开始的写法是这样的:tmpplayer1.players.Add(tmpplayer1);Debug时看不出什么问题,但是实际存在players里的东西就不一样了,因为foreach循环体里每次都要new tmpplayer(),代表着每次循环所使用的tmpplayers都不是同一个,可以理解为tmpplayer1、tmpplayer2,对象不是同一个,其players的自然也不是同一个,所以List总是只保存了最后一次存入的数据(因为foreach结束了不再newtmpplayer了),之前写入的东西都被后一个覆盖掉了。
其实上面说这么多,原因就是在Read()函数体中操作的数据是没有被保存的,出了这个函数,如果没有保存或return就再也找不到了,包括players。所以我在函数外声明了一个player对象专门用于保存函数体内操作后的数据,而后还要把这个对象存入Dictionary中,这样数据就不会丢了。
&span style=&font-size:14&&using UnityE
using System.C
public class LoadManager : MonoBehaviour {
//游戏一开始就加载所有的xml
void Start () {
//需要添加新的配置表,只需添加addconfig方法,加上读取的xml名即可
addConfig&PlayerConfig&();
addConfig&XXX&();
void addConfig&T&() where T : DatabaseConfig, new() {
T config = new T();
StartCoroutine(loadXML(config));
// Debug.Log(config);
public string getPlatForm(DatabaseConfig configPath) {
string path = Application.streamingAssetsPath+ configPath.ToString() + &.
IEnumerator loadXML(DatabaseConfig tempConfig) {
string path = getPlatForm(tempConfig);
WWW www = new WWW(path);
Debug.Log(www.text);
tempConfig.Read(www.text);
DefaultConfig.getInstance().configDic.Add(tempConfig.GetType(), tempConfig);
这里使用了streamingAssets文件夹作为存放XML的路径,大家可以搜索streamingAssets有好多介绍。最下面就是用协程加载找到XML并调用Read()方法读取XML内容,上面已经讲过了,最后把这个对象存到Dictionary里。
所以需要加载其他XML的时候,只要写一个继承于DatabaseConfig的子类就可以了,然后把AddConfig&ClassName&放进Start里,在Unity一运行的时候,就把这个XML读好放进Dictionary里了。需要增加或减少XML只需要管理Start里的条目就可以了。虽然整体逻辑我自己想起来也很费脑子,但是以后再增删XML可就省事多了。
最后附一段测试代码
void testDemo() {if(&pre name=&code& class=&csharp& style=&font-size:18&&PlayerConfig playercon= DefaultConfig.getInstance().GetConfigByType&PlayerConfig&()&span style=&font-family: Arial, Helvetica, sans-&&){&/span&
&pre name=&code& class=&csharp&&
Player currentPlayer = playercon.GetPlayerByID(1001);
Debug.Log(currentPlayer.name);
如果Dictionary里有PlayerConfig的key,那么下面就是获取Player的对象,查找ID为1001角色,如果没有错误,最后Debug里输出的值就是“伊沢ライオン”啦!
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:9413次
排名:千里之外
原创:15篇
转载:17篇
(1)(1)(2)(1)(1)(1)(2)(1)(2)(2)(6)(12)
(window.slotbydup = window.slotbydup || []).push({
id: '4740881',
container: s,
size: '200,200',
display: 'inlay-fix'记一次基于Unity的Profiler性能分析
& & &A. CPU-GC Allow:& & & & 关注原则:1.检测任何一次性内存分配大于2KB的选项 2.检测每帧都具有20B以上内存分配的选项.& & &B. Time ms:&nbsp
14:24&&&[]
,LoadRunner能够对整个企业架构进行测试。企业使用LoadRunner能最大限度地缩短测试时间,优化性能和加速应用系统的发布周期。 LoadRunner可适用于各种体系架构的自动负载测试,能预测系统行为并评估系统性能。 VisualVM:JDK的一个集成的分析工具。监控应用程序的性能和内存占用
18:09&&&[]
最近忙着把一个项目从MySQL迁移到MongoDB,在导入旧数据的过程中,遇到了些许波折,犯了不少错误,但同时也学到了不少知识,遂记录下来。 & 公司为这个项目专门配备了几台高性能务器,清一色的双路四核超线程CPU,外加32G内存,运维人员安装好MongoDB后,就交我手里了,我习惯于在
13:11&&&[]
长话短说,我整理了一下mac版Unity3D pro下的Profiler连接Android的使用。注意是专业版的Unity3D。在Window下会有Profiler
这个工具的意义是,游戏在客户端跑然后UnityProfile测试一些参数 连接手机有两种方式。 1.wifi:让手机和电脑痛处
16:55&&&[]
,第一件事就是思考如何将 eslint 用起来,一定要对用户优雅简单。首先就是改造工具,tingle 的构建和开发工具是基于 gulp 做的,在开发的时候我们只需要使用 gulp d 就可以启动一个带有实时编译 stylus 和 jsx 的 browser-sync server,非常方便,我想
21:35&&&[]
这篇文章是记录一次ORACLE数据库UNDO表空间爆满的分析过程,主要整理、梳理了同事分析的思路。具体过程如下所示: 早上收到一数据库服务器的UNDO表空间的告警邮件,最早一封是7:55发出的(监控作业是15分钟一次),从告警邮件分析,好像是UNDO表空间突然一下子被耗尽了。
08:10&&&[]
Unity提供两种方式让Developer的Android设备连接Profiler进行性能分析: 1、通过wifi,Android设备和计算机处于同一个Wlan中。 2、通过USB ADB
一般情况我们的计算机都是网线,所以我们采用ADB的方式。相比与wifi,ADB也更及时的反应设备性能。
官方的英文文档如下:
http://docs.unity<//Manual/Profiler.html
For ADB profiling, follow these steps: Attach your device to your Mac/PC via cable and make sure ADB recognizes the device (i.e. it shows in adb devices list). Check the “Development Build” checkbox in Unity’s build settings dialog, and hit “Build & Run”. When the app launches on the device, open the profiler window in Unity Editor (Window-&Profiler) Select the AndroidProfiler(ADB@127.0.0.1:54999) from the Profiler Window Active Profiler drop down menu. Note: The Unity editor will automatically create an adb tunnel for your application when you press “Build & Run”. If you want to profile another application or you restart the adb server you have to setup this tunnel manually. To do this, open a Terminal window / CMD prompt and enter adb forward tcp:54999 localabstract:Unityinsert bundle identifier here Note: The entry in the drop down menu is only visible when the selected target is Android. If you are using a firewall, you need to make sure that ports 54998 to 55511 are open in the firewall’s outbound rules - these are the ports used by Unity for remote profiling.
按照文档的步骤,这里我来翻译一下:
首先我们先设置ADB: 打开CMD命令行窗口,输入以下命令:
adb forward tcp:54999 localabstract:Unity-com.thisisgame.gamedemo
然后 从Unity中Export Android 工程的时候一定要勾选 Development Build
然后在手机上打开游戏。 打开Unity Profiler窗口选择(ADB@127.0.0.1:54999)
然后就能在Profiler进行性能分析了。
22:37&&&[]
,只需要一个总的权限即可,像我这一次,就只是为了拷贝数据,所以我为所有的仓库都设置了admin这个超级管理员的读写权限,具体设置方法,请参考SVN权限设置。 && 然后就是拷贝数据了~~~下载小乌龟的svn客户端(TortoiseSVN)安装配置,这里又有一个小坑,就是在连接数
17:26&&&[]
事情源自今天公司发生了一件事情,因为工作关系所以背景内容就不细讲,不过这里有人几天前遇到了同样的问题: 偷天换日:网络劫持,网页js被伪装替换 。以此为例,来吐槽吐槽这个hijacking的“黑客”水平有多烂。
我把劫持被替换掉的脚本贴出来,上文中对方遇到的问题是 common.js ,与我们的情况类似。
从这段脚本我们大致可以看出,显示判断是否有id为 mck0 的标签(我试着google mck0 的意思,无果),如果没有则会向DOM中添加两个script标签。说实话这js写得真是烂,既然用了Array,for循环的时候还把循环次数写死了。而且,js是创建数组居然还是用 new Array() ,亲,ES2016都快要火起来了。这里安利一下Airbnb的 JavaScript Style Guide ,至于为什么推崇使用 [] ,参考 Why is arr = [] faster than arr = new Array? 。
扯远了,回到这段脚本,数组中存了两个地址,一个是 common.js 的地址,一个是指向
的一个地址。
先说第一个,脚本作者可谓良苦用心,为了隐藏自己,虽然替换了 common.js ,但还是希望网页是可以顺利访问的,所以重新添加了一个能够正常访问的 common.js 的资源,后面加了日期的后缀用来区分。这作者实在是自作聪明啊。
对于一个稍微有点规模的前端项目而言,核心的几个lib都是会被其他的lib依赖的,你倒好,篡改了 common.js ,然后在 HEAD 标签里面append新的 &script& 标签,亲,你这是插到最后去了你知道吗?你让别的库怎么依赖你这个插进去的 common.js ?你找一下 head 里面第一个 scirpt 出现的位置,用 insertBefore 这个函数就可插到最前面了。
话说回来,也不能怪这个“黑客”水平太烂,主要是国内很多前端开发的水平也不够,现在有很多支持js动态加载的工具,如鼎鼎有名的 RequireJS ,国内做前端开发的,好多外包公司能简单就简单,能糊弄就糊弄。当然了,前端工程师如果觉得这个太难上手,用个主流的打包工具打个包总归很简单的吧, Webpack 随便玩。要是觉得这个还太难,用 Gulp 把js合并混淆一下,要是负点责任加个hash的版本号,这些总归很简单了吧。
补充说明,其实这里用打包工具跟依赖工具,其实都只是增加了“黑客”修改脚本的难度,理论上他们还是可以实现文件替换的,比较保险的做法是在后端做CheckSum,不管是CDN上的资源,还是自己服务器的资源,提供一个API使得前端在加载了资源后,与后端记录的CheckSum值进行对比,验证文件的一致性。另外,还可以对dom的append操作做一些检测,比如监听并阻止外部append行为等等。
接下来再说说黑客
10:11&&&[]
最近花了差不多1天的时间在折腾一个Bug,该Bug的表象如下:&
这个Bug还特别独特,在开发电脑中无提示,在终端用户那里每次使用软件的时候都报这个。仔细思考了一下最近在源码中新添加的功能,没发现有啥特别明显的问题。于是,根据字面意思的理解是“运行时错误”,所以一开始解决这个问题的思路是将所有应用程序的运行时拷贝至应用程序目录。尝试过之后,依然报这个异常。分析可能跟运行时的动态链接库没有关系。于是,调整解决问题的思路,考虑将工程中新添加的代码进行分割。部分部分的测试新添加的代码到底那里有问题,排查到最后是这个函数内部发生了异常。异常函数的代码如下:
void CleanSerialPort() { if(g_hEvent != NULL) { CloseHandle(g_hEvent); g_hEvent = NULL; } if(g_SerialPort.IsOpen()) { COMMPROP memset(&properties, 0, sizeof(properties)); g_SerialPort.GetProperties(); g_SerialPort.ClearWriteBuffer(); g_SerialPort.ClearReadBuffer(); g_SerialPort.Flush(); g_SerialPort.CancelIo(); g_SerialPort.Close(); } }
一开始仔细读了几遍代码,没发现有啥异常的地方。在这个时候,只能通过一点一点调试编译器来最终确定问题在那里。调试编译器的方式比较传统,是通过MessageBox消息来实现。最终定位到g_SerialPort的Close函数。该函数的原型如下:&
void CSerialPort::Close() { if(IsOpen()) { CloseHandle(m_hComm); m_hComm = INVALID_HANDLE_VALUE; } }
仔细读了几遍,依然没发现问题在那里。但是,又反复琢磨了一段时间之后,把这个问题想清楚了。当把串口数据线拔出之后,串口设备已经在操作系统中不存在,这个时候却还要去强行关闭串口设备,此时当然会发生异常,不发生异常才是不正常的情况。于是,考虑在这一大段代码的外围加一个try…catch…,果不其然,成功捕获到异常,异常代码的值为0x05,代表的含义为ERROR_ACCESS_DENIED,表示拒绝访问。目前操作系统中已经不存在该串口设备,因此拒绝访问是正常的状态。最终的代码如下:&  
void CleanSerialPort() { try { if(g_hEvent != NULL) { CloseHandle(g_hEvent); g_hEvent = NULL; } if(g_SerialPort.IsOpen()) { COMMPROP memset(&properties, 0, sizeof(properties)); g_SerialPort.GetProperties(); g_SerialPort.ClearWriteBuffer(); g_SerialPort.ClearReadBuffer(); g_SerialPort.Flush(); g_SerialPort.CancelIo(); g_SerialPort.Close(); } } catch(CSerialException &e) { ATLTRACE(&Unexpected CSerialPort exception, Error:%u\n&, e.m_dwError); UNREFERENCED_PARAMETER(e); } }
捕获到这个异常之后,在不关闭应用程序的情况下,不影响再次初始化串口设备,而应用程序也不报一开始的Runtime error,因此默认目前的处理方案可行。&
00:26&&&[]
CSS 1、考察了盒子模型 2、内联元素、块元素 3、css3的贝塞尔曲线(张鑫旭大神的解说) 4、弹性盒子flexbox 综合考察
1、js跨域问题 算法考察 1、有36辆自动赛车和6条跑道,没有计时器的前提下,最少用几次比赛可以筛选出最快的三辆赛车? 2、一面墙,单独工作时,A花18
13:17&&&[]
这几天主要有几件事情要做:一是论文,而是项目,三是博客,朋友有一个未完成的项目,checkout到自己的电脑之后,将项目导入到MyEclipse,将项目中的包加入Java build path时,出现了JRE System Library(unbound),去掉,换成自己的jre,再配置tomcat。 访问项目出现了空白 等配置好之后,启动tomcat,没有报错。可以访问localhost:8080出现小猫。但是访问localhost:8080/xxx,整个项目下的页面都是空白,不光是jsp,html也访问不了,就在网上搜索答案“可以访问localhost:8080,访问部署的项目出现空白”,答案也五花八门有说端口被占用,有说tomcat的work目录下没有生成项目文件,还有说防火墙没有关,我按照网上的做了,却依然没有任何效果,只白白浪费时间。 能访问html,不能访问jsp 去检查web.xml,突然看到web.xml中配置的filter元素,属性中有一行是将html写成了tml,改了之后,发现自己建的MyHtml.html能访问,虽然jsp页面还是访问不了,但是毕竟不全是空白了,这个时候我继续在网上搜索一下“可以访问html,不能访问jsp”,网上又是一大片答案,也硬着头皮跟着那些答案碎片做,没有成功,为什么没有去改filter呢,我还是坚信代码没有错。因为在远程部署的可以正常访问。 web.xml配置的filter不生效 后来我把web.xml中配置的filter注释之后,只剩下welcome-file-list这项,能访问自己新建的jsp,但是项目里面的index.jsp由于要访问action所以出现了错误,这是正常的。看来filter这里有些蹊跷。后来我试着调试代码。这次的filter如果错误就不好在网上搜答案了,之前自己没有做过项目实践,只想着能很快地能在网上找到答案,这次只有自己调试,调试发现,这个filte里对页面判断后有三个跳转方法
对index.jsp和login.jsp等设置的是ignorePages,需要进入(FilterChain)chain.doFilter 对html、jpg、css等设置的是allowResources 对其他的页面和资源是没有进行(FilterChain)chain.doFilter的。
经过debug发现index.jsp始终不能进入chain.doFilter。我就在路径判断之前加了打印路径的语句,发现打印出来的路径都有一个xxx/index.jsp。与过滤的index.jsp路径不符,这时候才想到这个路径的问题,导致一直不能进入,就想着访问的时候能不能不输入index.jsp前面的xxx,于是conf中的server.xml里面host下面加入了 &Context docBase=&C:\Apache\apache-tomcat-7.0.72\webapps\xxx& path=&/& reloadable=&true&/& 就是把默认启动的应用设置为自己的项目。输入localhost:8080后,终于进入了自己项目的首页。 想法 经过这次教训,我明白了调试代码的重要性,出现问题也不能光想着去网上找答案,网上的答案有些不具备普遍性,就算是普遍存在的问题,也不能照着网上的步骤一步一步做,自己从网上的答案找到启发,然后再在这个方向一点一点去找原因,这样会有趣多了。
05:00&&&[]

我要回帖

更多关于 unity xml 读写 的文章

 

随机推荐