游戏邦在:
杂志专栏:
gamerboom.com订阅到鲜果订阅到抓虾google reader订阅到有道订阅到QQ邮箱订阅到帮看

Unity开发者如何有效地进行本土化操作

发布时间:2014-05-28 10:55:12 Tags:,,,,

作者:Alex Sink

对于一名游戏开发者来说,本土化总是不能出现在适当的时候。不管我们是否在一开始进行设置,因为我们认为这是正确的方法,但是紧随其后游戏便遭遇了失败。或者即使游戏表现得不错,我们也必须尝试着明确如何将其放置在之后的过程。我已经将这个问题放在之后的问题集分类中:如果这是你所面对的问题,那么这便是你需要为此花钱去解决的问题。

Localization(from agencypost)

Localization(from agencypost)

最近我参与了一个为本土化提供资金的项目,我们的任务比想象中复杂得多。虽然存在一种简单的方法,但却没有什么好的建议,所以这个任务暂时被搁置了。是使用unity获得了整个资产渠道,但是获得游戏翻译仍然不是件简单的工作。我仍然需要完成我的资源,资产以及关于文本的所有场景搜索,然后对它们进行重组并参考一些实用内容从而给予当前语言的相关翻译。我知道自己可以做得更好,对吧?

在Transfluent我认识了Jani,对于使用一种工具而更轻松地利用unity的资产渠道获得游戏翻译这一点我们具有类似的想法。他已经通过获得一个基本的编辑翻译工具而完成了第一传。因为它遭遇了许多第二层和第三层问题,所以第一传是非常好的出发点。然而,与许多unity图形用户界面编辑窗口一样,即时模式的使用将会以某种方式倒向代码结构并倾向于创造好几千行内容的文件。所以这是推动我们吸取某些教训的一个很好的起点。

本土化的障碍:

1.提取文本并将其放在数据储存区进行翻译

2.删除任何关于文本的简单引用(在场景和预制件中)并用纯粹的脚本控制文本进行替代

3.基于某种形式用字符串替代任何串并置(“hello”+“world”)以及动态文本(如来自用户“hello there”+用户名的文本)

4.重新将储存于数据储存区的文本整合到你所选择的UI解决方法中

5.找到一种方法去使用翻译器翻译你的数据—-这通常包含进入“蓝屋”(如:不创造一款游戏)

6.检查你的游戏是否已经翻译了所有内容—-使用一种你懂的“外语”并且仍然能够用于导航至各种理想选择。例如:Facebook的“英语(盗版)”https://www.facebook.com/settings?section=language

7.在发现短语未翻译时获得新的翻译内容

什么是正确的:

1.隐藏unity的所有OnGUI和GUILayout功能。这有时候看似疯狂,但这将以创造一个非常简单的方法去获得一个带有许多静态文本且能够更快速地进行翻译的UnGUI游戏告终。也许还有些功能较为模糊,就像输入内容是否应该是自动翻译的,但只要那些内容属于异常情况,这便能够帮助你轻松地翻译游戏。

2.对textmeshes,场景和预制件进行资产扫描。它将找到你的文本并对其进行翻译。我认为GameSpecificMigration中的黑名单机制可以得到完善。

3.简单的储存格式。最初,我将数据格式与专用格式绑定在一起,认为这么做会方便许多。ScriptableObjects是并未存在于场景中的基本游戏对象。它们将在运行时间中获得同意的优化,并在与别人合作时呈现出YAML合并友好型特质。确保界面就像一本简单的词典,并且在处理之后出现的各种简单任务上允许更多灵活性的出现。

4.“逆向”语言—-这是检查你的游戏的一种简单的方法,以此确保你能够翻译自己所作出的大多数决定。

5.“捕获模式”—-能够贯穿你的游戏而运行,作为一种寻找资源翻译的方法,而不是从代码中将文本复制到翻译数据库,这似乎比较不容易出错且更容易更新。你也可以选择其它方法,但这种模式能够带给你帮助。

6.编辑窗口逻辑/视图分离。拆分“视图”逻辑,就像通过“应用”逻辑呈现文本,如上传,命令翻译。基于strangeioc的中介模式(http://en.wikipedia.org/wiki/Mediator_pattern),我越来越习惯这种方法。是否想要上传你自己完成的新翻译内容?当然。那么在编辑窗口呢?也要。

7.测试—-测试能够帮助我避免沉浸于某些愚蠢的内容,如脱机以及计划停运。它们将帮助我在前进的过程中核实设计和数据格式,因为如果我不能单独测试它,它便很容易崩溃。尽管我以前使用过nunitlite,不过Unity的测试工具刚刚出现,并且是一个很棒且较为完善的工具,基于Jenkins(游戏邦注:是基于Java开发的一种持续集成工具,用于监控秩序重复的工作),我能够自动操作测试,从而在代码损坏某些内容时立即获得反馈。

未知:(例如“已知的未知”)

1.基于OnLocalize支持的运行时间。显然我们需要一种方法去告知代理语言发生了改变,所以我决定使用Unity向客户发送信息。这并不是我经常做的某些事,但却是我发现其它类似的中间件成功使用过的一种模式。

2.标记化。我认为这将以积极的结果告终,而这更多地取决于KISS原则的功劳。最简单的解决方法只是隐藏字符串。格式以及在“Hello,{0}”格式中使用字符串看似是最正确的方法。事实证明,关于翻译存在许多细微差别,可能会让屏幕截图变得更有效(也有可能变得更糟糕)。

未来的工作:

1.编辑器的支持。翻译你的编辑工具EditorGUILayout和EditorGUI似乎是有效的。我认为所有需要完整的本土化编辑工具的内容在某种程度上都将连接隐藏的editorguilayout和editorgui与一个特定的TranslationUtilityInstance。我不认为这具有挑战性,但是我也不确定是否真的需要这样的内容。

2.确保文本“看起来”是合理的,并且如果翻译内容需要提前运行的话,提供给翻译器一个更棒的提示。这与在获取模式中发送屏幕截图一样简单。

3.更深入的整合—-支持在各种框架上自动换行以及规格调整。

4.支持更多UI框架—-它们带有许多相关联的不同挑战。

5.中间件整合—-整合搭配fungus和其它工具链意味着能够更轻松地创造游戏。拥有像fungus以及其它故事/游戏创造支持工具真的很酷。

6.更多资产扫描。创造更多支持自动转移的文本。思考:本土化playmaker文本。资产扫描器的设置是为了帮助解决编辑器脚本撰写的粘滞位问题,ICustomProcessors只是处理GameObjects将功能延伸向全新的脚本类型。

随着越来越多人使用工具,我们的目标便是根据新识别的用例而继续完善它。

本文为游戏邦/gamerboom.com编译,拒绝任何不保留版权的转载,如需转载请联系:游戏邦

Localization as a Unity Developer

by Alex Sink

Localization as a Unity Developer

As a game developer, often times localization is something that never seems to happen at the right time. Either we put it in from the beginning, because we think that’s the right way to do it, and then the game flops. Or the game does well, and we have to try frantically to figure out how to put it in later. I’ve been more comfortable putting this problem into the latter classification of a “rich man” problem-set: if it’s a problem you have, then it’s one that you can afford to throw money at.

I recently came off a project with funding for localization, and the task was much more daunting than it should have been. There had to be a simple way, but with no good suggestions, the task was shelved. I had access to the entire asset pipeline with unity and it’s still no easier to get the game translated. I still have to go through my source, assets, and all the scenes searching for text and then re-engineer all of them to reference some utility to get translations based on the current language. I knew that things could be done better. Right?

I was introduced to Jani at Transfluent, who had a similar vision of a tool to make it easier to get a game translated by leveraging unity’s asset pipeline. He had done a first pass at getting a basic in-editor translation tool up and running. It had encountered many second- and third-tier issues, so that first pass was a useful jumping-off point. However, like many unity gui editor windows, use of immediate mode leaked into code structure in ways that tended to create multi-thousand-line files. So it was a great starting point to start learning some lessons.

Obsticles to localization:

1.Extract text and put it into a data store to be translated

2.Remove any simple references to text –in scenes and prefabs– and replace with pure script- controlled text

3.Replace any string concatenation (“hello “+ “world”) and dynamic text (such as text from the user “hello there”+username) with strings in some format.

4.Re-integrate text stored in the data store into your UI solution of choice

5.Find a way to work with translators to get your data – this often involves going into the blue room (i.e., not making a game)

6.Check that your game has translated everything – using a “foreign” language that you understand but still can use to navigate to various desired options. See: Facebook’s “English (Pirate)” https://www.facebook.com/settings?section=language

7.Get new translations when a phrase is found un-translated

What went right:

1.Wrapping all of unity’s OnGUI and GUILayout functionality. Seemed crazy at the time, but this ended up creating a pretty simple way to get an OnGUI-heavy game with lots of static text into a translated form as quickly as possible. There may be some functions that are somewhat ambiguous, like whether the input should be auto-translated, but as long as those are exceptions, this makes it easy to translate your game.

2.Asset scanning for textmeshes, scenes and prefabs alike. It will find your text and get it translated. I think the blacklsiting mechanism in GameSpecificMigration can be improved.

3.Simple storage format. Initially, I had tied the data format to a proprietary format, thinking it would make my life easier. ScriptableObjects are wonderful things that are basically gameobjects that don’t live in the scene. They get the same optimizations at runtime and the merge-friendly of YAML when collaborating with folks. Keeping the interface to a simple dictionary allowed a lot of flexibility in how to handle a variety of simple tasks later on, too.

4.”Backwards” language – an easy way to check your game to make sure you have translated most of your decisions.

5.”Capture mode” – being able to simply run through your game as a way of finding source translations instead of copy-pasting text from code to a translation database seems far less error-prone and easier to update. You can still do that if you want, but this helps.

6.Editor window logic/view separation. Split out “view” logic like displaying text from “application” logic, such as uploading, ordering translations. I had grown used to this with strangeioc’s mediation pattern http://en.wikipedia.org/wiki/Mediator_pattern. Want to upload new translations you did yourself in the inspector? Sure. How about in the editor window? Ok too.

7.Testing – Tests prevented me from getting hung up on silly things like being offline and planned outages. And they helped me verify design and data formats as I went along, because if I couldn’t test it independently of other things, then it was likely brittle. While I had previously used nunitlite, Unity’s test tools had just come out and were a nice improvement, and with Jenkins (l acostej.blogspot.com/2012/03/unity3d-from-commit-to-deployment-onto.html) I could automate the tests so that I immediately get feedback when code breaks something.

Unknown: (i.e., the “Known unknowns”)

1.Runtime support with OnLocalize. Obviously there needs to be a way to notify clients that the language has changed, so I decided to go with the Unity way of broadcasting messages to clients. Not something I’d do normally, but it’s a pattern that I’ve seen successfully used by other similar middleware.

2.Tokenization. I think this ended up in the positive realm, but only because the KISS principle won out over an effort to be clever that would have taken me out of my depth. The simplest solution was simply wrapping string. Format, and using strings in the format “Hello, {0}” seem like they may be the right way to go. And as it turns out, there are a *ton* of nuances to translation that would make a screenshot way more useful than a suggested part of speech (or worse yet, suggestion of plurality) as a token name in there.

Future work:

1.Editor-support. Translate your editor tools – EditorGUILayout and EditorGUI seem to work. I think all that would be needed to have fully localized editor tools would be some way to connect the wrapped editorguilayout and editorgui with a specific TranslationUtilityInstance instead of the global one. I don’t think this would be challenging at all, but the demand for such a thing seems to be uncertain.

2.Making sure the text will “look” right and give the translators a better clue if their translations will work upfront. This could be as simple as sending screenshots while in capture mode as well.

3.Deeper integrations – support word wrapping and resizing (see: shrink to fit) on various frameworks

4.Supporting more UI frameworks – they have different challenges involved with them.

5.Middleware integration – integration into things like fungus and other toolchains meant to make it easier to create games. It would be cool to have tools like fungus, and other story/game building tools supported natively.

6.More asset scanning. Create more supported auto-migrated text. Think: localized playmaker text. The Asset Scanner was set up to help solve some of the sticky bits of editor scripting and ICustomProcessors that just deal with the GameObjects to extend functionality to new types of scripts.

As more folks use the tool, the goal is to continue to make it better as new use-cases are identified. I hope to hear from you so we can start to solve some of these problems better, together. (source:gamasutra)

 


上一篇:

下一篇: