Sponsored By
Adrián Moreno Navarro, Blogger

June 20, 2016

4 Min Read

It would be strange to find a game today that doesn’t somehow use texts to give directions, to help the player, or to show dialogues between characters etc… And while I certainly support using least amount of text possible, sometimes it is unavoidable, (at least in the main menu, options, and credits).

In The Guest we decided to let the player discover the plot through a mixture of documents and inscriptions while also communicating with the player through the character’s thoughts, in the form of subtitles. This makes the texts play an essential role within the narrative.

 

In order for any one of our programmers on the team to have access to any text they may need for puzzles, documents, or dialogues we needed a manager to be responsible for providing the texts to the other classes in a user-friendly way. I handled the design and programming of this manager, and I must admit that if I had to program it now it would be different because we’re talking about code I wrote almost 3 years ago. But my intention is that you can see the first attempts (successful, but not perfect) I used to implement this system.

Here is the basic structure.

On the one hand we have an .xml for each set of similar texts (e.g. documents, thoughts, UI, menus). These .xml are loaded from the TextManager in an XmlDocument to query from any class (since TextManager is included in the Singleton) returning the specified string. If you need the text to be displayed as a subtitle, you send the string to SubtitlesHandler and, from there you activate the subtitle so that the text is displayed with its animations.

The SubtitlesHandler class receives a string, which it will show up on the screen with a fade in, stay for a while depending on the number of characters the text has, and then remove it again with a fade out.

In addition, all the phrases that pass through SubtitlesHandler are registered in a class Diary which keeps track of when the player has forgotten his short-term goal. To remember you can open the menu, go to the Diary tab and see all the messages that have come up on screen until that point in the game.

Below is a very simplified version of the TextManager class I wrote for The Guest.


using UnityEngine;
using System.Collections;
using System.Xml;

public class TextManager : MonoBehaviour 
{	
	XmlDocument xml_dialogues;
	XmlDocument xml_documents;
	public TextAsset text_dialogues;
	public TextAsset text_documents;

	string selected_language = "English";
	
	void Awake()
	{
		Singleton.Instance.SetGestorTextos(this);
	}
	
	void Start ()
	{
		xml_dialogues = new XmlDocument();
		xml_dialogues.LoadXml(text_dialogues.text);
		xml_documents = new XmlDocument();
		xml_documents.LoadXml(text_documents.text);			
	}		
	
	public string GetTextDialogues (string _node)
	{
		string text = xml_dialogues.SelectSingleNode("languages").SelectSingleNode(selected_language).SelectSingleNode(_node);
			        		
		if(text == null)
		{
            Debug.LogError("Text not found");
            text = "";
        }        

        return text;			
	}

	public string GetTextDocuments(string _node)
	{
        string text = xml_documents.SelectSingleNode("languages").SelectSingleNode(selected_language).SelectSingleNode(_object);

        if (text == null)
        {
            Debug.LogError("Text not found");
            text = "";
        }

        return text;
    }	
	
	public void SwitchLanguague(string _language)
	{
		selected_language = _language;		
	}
}

And here is an example of the structure that each of the .xml would have.


<?xml version="1.0" encoding="UTF-8" ?>
<languages>
	<English>	 
	
	   	<!--CINEMATICS-->
		
		<cinem_bath_text_01>Huh... I can't stand this... I need my pills... </cinem_bath_text_01>
	   	
	   	<!--FURNITURE-->
	   	
	  <door_dm_01.puerta_cerrada>Huh? Where is the doorknob?</door_dm_01.puerta_cerrada>
		<door_dm_01.puerta_default>The doorknob is still loose, I need something to screw this to the door.</door_dm_01.puerta_default>
		<door_dm_01.usar_puerta_abierta>Here it is. Now I should be able to open it.</door_dm_01.usar_puerta_abierta>
		<door_dm_01.puerta_bloqueada>I can't open it. I'm stuck in here.</door_dm_01.puerta_bloqueada>		
				
	</English>			
	<Spanish>
	
		<!--CINEMATICS-->
		
		<cinem_bath_text_01>Huh... No aguanto más... Necesito mis pastillas... </cinem_bath_text_01>
	   	
	   	<!--FURNITURE-->
	   	
	  <door_dm_01.puerta_cerrada>Huh? Donde está el pomo?</door_dm_01.puerta_cerrada>
		<door_dm_01.puerta_default>El pomon aún está suelto, necesito algo para atornillarlo a la puerta.</door_dm_01.puerta_default>
		<door_dm_01.usar_puerta_abierta>Eso es. Ahora debería poder abrirla.</door_dm_01.usar_puerta_abierta>
		<door_dm_01.puerta_bloqueada>No puedo abrirla, estoy encerrado.</door_dm_01.puerta_bloqueada>
    
	</Spanish>	
</languages>

The Guest is translated into 7 languages. Each one of the .xml contains a node for each language and, within it, all the texts in that language. We guessed that writing the .xml directly in Spanish (our mother tongue) would be an unnecessary work. But it wasn’t until we had to send the texts to 505Games to localize the texts to the other languages that we realized how inefficient the process really was. We had to draw out the lines of text of the .xml, enter them into a spreadsheet and name them so that the translators could easily identify them. Once translated, we had to go through and insert each phrase into the corresponding node of the corresponding .xml, definitely a very tedious process.

In the current project that we are working on, I am once again in charge of system texts but this time around I’m trying to avoid repeating the problems we encountered during The Guest. In the second part of this article I will discuss the improvements that I have applied and how we use Google Drive to simplify the process of writing and translation.

Read more about:

2016Featured Blogs
Daily news, dev blogs, and stories from Game Developer straight to your inbox

You May Also Like