Unity项目中文字的统一管理

一款游戏在研发初期就需要考虑多语言的问题,否则后期在进行多国语言版本时就面临着巨大的成本。鉴于之前页游的经验,其它同事设计出读取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图片,这个也需要提前进行约定,制定相关的规范。

时间: 2024-07-28 15:58:29

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

BOS项目 第10天(activiti工作流第二天,流程变量、组任务、排他网关、spring整合activiti、项目中实现流程定义管理)

BOS项目笔记 第10天 今天内容安排: 1.流程变量(设置.获取) 2.组任务(候选人.候选组) 3.排他网关使用 4.spring整合activiti 5.将activiti应用到bos项目中 6.在bos项目中实现流程定义管理(部署.查询.查看png.删除) 1. 流程变量 1.1 设置流程变量的方式 l 方式一:启动流程实例时设置 l 方式二:办理任务时设置 l 方式三:使用RuntimeService的set方法设置 l 方式四:使用TaskService的set方法设置 注意:如果设

在unity项目中使用live2D,以及Render Texture的简单使用。

好久没有写博客了,前段时间找到了一个二次元手游开发的工作,职位是客户端主程(虽然工资不高就是了),作为个unity新人现在想想还是有点后怕,不过车到山前必有路嘛. 言归正传,这次的项目中用到了live2d,总的来说导入的很顺利,也没碰上什么坑~ 首先这里有对应的教程和sdk下载(需FQ): http://www.live2d.com/usermanual/cubism2_cn/lets-do-it/my-first-lapp.html SDK里包括了几个demo,不要一口气把里面的东西全部拖到u

java框架-----spring框架------在自己的项目中如何用maven管理spring相关jar包

1.文章内容概述: spring框架是支持maven的,因为spring框架的所有模块打包而成的jar包以及spring所依赖的其他jar包都被存放了一份在maven的中央仓库中,如果你的项目使用maven进行管理,那么你就可以在你的项目中通过maven来引入你的项目所依赖的spring相关的jar包或其他依赖库. 2.spring框架中maven相关的东西: 概述:使用maven管理spring相关的jar包,需要在pom.xml中配置groupId.artifactId之类的东西,只有在po

(21)项目中Hibernate Session的管理方式

1.openSession和getCurrentSession的区别 package com.rk.hibernate.cache; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; import org.junit.Test; public class App_SessionInProject { private static Se

18年7月实训unity项目中遇到的问题记录

1.在一个项目中做好的UI做成预置体后在另一个项目中使用时发现无法响应鼠标的输入事件 解决:在使用预置体的项目中添加EventSystem. 2.使用DontDestroyOnLoad()来避免场景切换后GameObject被销毁存在的问题 假如A场景中有一个GameObject名为player,为了不让player在场景切换到B时消失而使用DontDestroyOnLoad(player),这样会导致场景再次切换回A时,A场景中同时出现两个player,并且两个player在场景切换后都不会消

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

并上一节使用的是普通的数据状态管理,不过官方推荐使用装饰器模式,而在默认的react项目中是不支持装饰器的,需要手动启用. 官方参考 一.添加配置 官方提供了四种方法, 方法一.使用TypeScript,顾名思义该方法是项目使用typescript时的配置 方法二.使用babel-preset-mobx, 安装并添加到.babelrc配置中,该方法需要升级一些依赖, babel-core -> @/babel-core 7.x babel-loader -> @/babel-loader 8.

android 导入项目 项目中文字乱码问题

转:http://blog.csdn.net/yangdeli888/article/details/7313215 乱码问题出现了几次,一直没有在意,今天又出现了,现总结如下: eclipse之所以会出现乱码问题是因为eclipse编辑器选择的编码规则是可变的.一般默认都是UTF-8或者GBK,当从外部导入的一个工程时,如果该工程的编码方式与eclipse中设置的编码方式不同,就会产生中文的乱码问题,这其中还有几种情况. 如果导入的整个工程的编码方式与eclipse的编码方式有冲突,那么这个工

web项目中处理捕获异常统一处理

1.jfinal 中设置拦截器 2.在拦截器 捕获异常信息统一处理 1 public class ExceptionInterceptor implements Interceptor { 2 3 //@Override 4 public void intercept(Invocation ai) { 5 BaseController controller = (BaseController) ai.getController(); 6 HttpServletRequest request =

Unity项目架构设计与开发管理 学习

视频地址:https://v.qq.com/x/page/d016340mkcu.html assetstore save manager