一款游戏在研发初期就需要考虑多语言的问题,否则后期在进行多国语言版本时就面临着巨大的成本。鉴于之前页游的经验,其它同事设计出读取Excel的方式来管理所有的文字。但是我在使用中发现很致使的一个问题,当多人编辑一个Excel时,冲突了就很麻烦,解决起来的成本还蛮高的。

之后我想了一些办法,例如搭建一个web站点,将所有的字符串 Key、Value保存到数据库中,避免冲突,方便去查询。但感觉还是太过麻烦,成本略高。然后就想到一个办法,既然读取一个Excel容易冲突,那我就弄多个文件,一个人编辑一个Excel,这样总不会冲突了吧。然后添加 Key 的时候,先查找 Key是否存在,如果存在就提醒添加者。

这样问题就变成从读取单个文件变成遍历一个文件夹下的文件。因为Excel在打开时,会生成一个临时文件并被占用,所以不可以对它进行操作(如复制)。

using System;
using UnityEditor;
using UnityEditor.UI;
using UnityEngine;
using UnityEngine.UI;
using System.IO;
using OfficeOpenXml;
using System.Collections.Generic;
using System.Text.RegularExpressions; namespace xxxx
{
[InitializeOnLoad]
public class StringsWatcher
{
static string stringsPath;
static DateTime lastModifyTime;
static string stringsFolderPath; static StringsWatcher()
{
stringsFolderPath = Path.GetDirectoryName(Application.dataPath);
stringsFolderPath = Path.Combine(stringsFolderPath, "strings"); // 创建Strings文件夹
if (!Directory.Exists(stringsFolderPath))
{
Directory.CreateDirectory(stringsFolderPath);
} // stringsPath = Path.GetFullPath(Path.Combine(rootPath, "Strings.xlsx")); EditorApplication.update += Update;
} static void Update()
{
if (EditorApplication.isPlaying || EditorApplication.isCompiling) return; //if (!File.Exists(stringsPath)) return;
if (!Directory.Exists(stringsFolderPath)) return; DateTime time = Directory.GetLastWriteTime(stringsFolderPath); if (lastModifyTime == time) return; lastModifyTime = time; Debug.Log("Reloading " + stringsFolderPath + ", Time : " + time.ToString()); DateTime startTime = DateTime.Now; // ExcelPackage package = new ExcelPackage(new FileInfo(tempFile)); List<string> keys = new List<string>();
List<string> values = new List<string>(); // 遍历 strings 目录下的excel文件
DirectoryInfo folder = new DirectoryInfo(stringsFolderPath);
foreach (FileInfo fileItem in folder.GetFiles())
{
string strFileType = fileItem.Extension; // 如果是 excel 文件且不是临时文件, 临时文件以~$开关,读取临时文件会报错误:Invaliddataexception the file is not an valid package file
if (new Regex(@"^[^~]+\.xlsx$").IsMatch(fileItem.Name.ToLower()))
{
string tempFile = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
File.Copy(fileItem.FullName, tempFile); //Debug.Log(fileItem.Name + ", " + tempFile); ExcelPackage package = new ExcelPackage(new FileInfo(tempFile));
ExcelWorksheet sheet = package.Workbook.Worksheets[1]; int rows = sheet.Dimension.Rows;
for (int row = 2; row <= rows; row++)
{
object keyObj = sheet.Cells[row, 1].Value;
object valueObj = sheet.Cells[row, 2].Value; // Valid key and value is null or not.
if (keyObj == null)
{
Debug.LogError("Find Key is null. fileName : " + fileItem.Name + ", rowIndex : " + row);
return;
} if (valueObj == null)
{
Debug.LogError("Find Key is null. fileName : " + fileItem.Name + ", rowIndex : " + row);
return;
} // Find key is Exist or not
if (keys.Find(x => x == keyObj.ToString()) != null)
{
Debug.LogError("Find Report Key. fileName : " + fileItem.Name + ", rowIndex : " + row);
return;
} string key = keyObj.ToString();
string value = valueObj.ToString(); keys.Add(key);
values.Add(value);
} // 每删除一个文件大约多0.1秒
File.Delete(tempFile);
} // 更新内存的数据,重新保存assets
AssetDatabase.SaveAssets();
} DateTime endTime = DateTime.Now;
Debug.Log("Rebuild string.assets time : " + (endTime - startTime).TotalSeconds + "s");
}
}
}

如果你读取Excel时遇到了 Invaliddataexception the file is not an valid package file ,上面的代码或许对你有所帮助。

除了文字外,游戏项目中还需要管理的就是带有文字的UI图片,这个也需要提前进行约定,制定相关的规范。

Unity项目中文字的统一管理的更多相关文章

  1. 关于Unity项目中创建项目遇到的一些问题

    1.Unity调用Android的方法默认不是在UI线程执行,所以在Android上写一些页面的重绘的方法,让Unity去调用时,注意要在Android中添加对应的runOnUiThread才可以: ...

  2. 关于 Unity 项目中的 Mono 堆内存泄露

    关于 Unity 项目中的 Mono 堆内存泄露 题记:这是补一篇应该在将近一年前就应该写的记录,今天终于补上. 内存泄露是一个老话题了,之前我专门写过一篇 排查 Lua 虚拟机内存泄露 的文章,并且 ...

  3. Javascript中怎样获取统一管理的Java提示语

    项目开发中,各个页面.各个业务操作都会使用提示语.面对这么多message,更好的方式是统一管理这些消息. 这样在做国际化的时候进行统一处理也变的方便. 推荐方案使用数据库来管理全部提示语,在项目启动 ...

  4. Android中关于项目中对Thread的管理(不是线程池)

    背景 项目中对于一些并不复杂的耗时操作,比如计算,不频繁操作数据库等,因为没必要使用线程池,所以之前项目会直接使用new Thread的方式,时间一长,回头再看,原来new Thread之处已经很多了 ...

  5. 在Unity项目中使用Git

    (搬运自我在SegmentFault的博客) 本文参考了Unity官网的Mastering Unity Project Folder Structure - Version Control Syste ...

  6. 怎么在项目中使用前端包管理器bower和构建工具gulp

    下面以WeUI(微信官方网页开发样式库)介绍一下,怎么把WeUi引入到自己的项目中,我的开发环境Visual Studio 2012,当然了Visual Studio 2015对此已有了更好的支持(h ...

  7. React项目中使用Mobx状态管理(二)

    并上一节使用的是普通的数据状态管理,不过官方推荐使用装饰器模式,而在默认的react项目中是不支持装饰器的,需要手动启用. 官方参考 一.添加配置 官方提供了四种方法, 方法一.使用TypeScrip ...

  8. Unity项目中的资源管理

    这是我在2017金山技术开放日分享的部分内容.从贴图资源格式配置的介绍开始,引申出资源配置工具,最后再谈谈一整套项目资源管理方案.在GitHub上可以获取到资源配置工具的代码,是基于下面理念的一份简单 ...

  9. android 项目中使用对话框统一封装

    近期在做拼车项目中使用到了一些对话框,而且在非常多地方都使用到了,既然非常多地方使用到,那么肯定要封装一下,

随机推荐

  1. python全栈开发day59-Django基础

    一.今日内容总结 1.HTTP协议: 请求:浏览器发给服务端的消息 格式: 请求方法 URL 协议版本\r\n k1: v1\r\n k2: v2\r\n \r\n 请求体(请求数据) 响应:服务端返 ...

  2. net core体系-web应用程序-4net core2.0大白话带你入门-1目录

    asp.net core2.0大白话带你入门 本系列包括: 1.新建asp.net core项目2.web项目目录解读3.配置访问地址4.环境变量详解5.配置文件6.日志7.DI容器8.服务的生命周期 ...

  3. 浏览器iscroll

    ::-webkit-scrollbar{width:4px;height:4px;background:transparent}::-webkit-scrollbar-track{background ...

  4. YII框架增删改查常用语句

    //实例化db $db = new \yii\db\Query(); //插入 $db->createCommand()->insert('user', [ 'name' => 't ...

  5. 在Xamarin.iOS项目中使用预设数据库

    在Xamarin.iOS项目中使用预设数据库 当开发者准备好一个预设数据库文件后,就可以将这个数据库文件添加到创建的项目中了.本节将分别在Xamarin.iOS和Xamarin.Android项目中使 ...

  6. Redis自学笔记:3.5入门-集合类型

    3.5集合类型 3.5.1介绍 在集合中的每个元素都是不同的,且没有顺序 表3-4集合类型和列表类型的对比 - 集合类型 列表类型 存储内容 至多232-1个字符串 至多232-1个字符串 有序性 否 ...

  7. [算法]Collebarative Filtering

    挖坑 https://en.wikipedia.org/wiki/Collaborative_filtering

  8. 第二章 《C++ Primer Plus》

    第二章: 让窗口暂停: cin.get(); 作为接口的函数头: 函数头句法: 函数头描述了函数与调用它的函数之间的接口. int main(); int main(void); return 0; ...

  9. [P1020]导弹拦截 (贪心/DP/二分/单调队列)

    一道很经典的题 这道题就是要求一个最长单调不升子序列和一个最长单调上升子序列. 先打了一个n2复杂度的 用DP #include<bits/stdc++.h> using namespac ...

  10. 2017.07.14【NOIP提高组】模拟赛B组

    Summary 这次比赛因为迟到了,少了很多时间,也受到了相应的惩罚,这是好的,是个标记牌,警醒着我.这次比赛的题目很难,也就是说,大家的得分都很低,总的来说,收获还是很大的,因为有非常多的技巧被掌握 ...