Executando verificação de segurança...
7

Como montei o sistema de seleção de idiomas do meu jogo Arkadon

Olá a todos! Hoje vou comentar da ideia que eu tive de como fazer a questão da seleção de idiomas no meu jogo. Inicialmente eu coloquei apenas a linguagem inglês nos botões e na HUD no geral, pelo costume do desenvolvimento mas sempre queria colocar português também.

Arquivo JSON

Eu comecei pensando numa estrutura básica de arquivo que não ficasse muito difícil de editar e também fosse organizado. Outra ideia que pensei, mas que não executei, seria criar uma chave "BTN_START_GAME" e dentro ter duas chaves: "pt" e "en", por exemplo. Mas seria apenas outra maneira de fazer. Abaixo encontra-se apenas uma parte do arquivo "language.json" responsável por conter todo conteúdo em texto para cada idioma.

{
	"pt": {
            "BTN_START_GAME":  "Novo Jogo",
            "BTN_HOW_TO_PLAY":  "Como Jogar",
            "TEXT_HOW_TO_PLAY":  "Q ou E -> gira a câmera\nW, A, S, D ou botão esquerdo do mouse e arrastar -> movimenta a câmera\nBotão direito do mouse ou teclado numérico (1, 2, 3, 4) -> coloca uma torre",
            "BTN_CLOSE":  "Fechar",
	},
	"en": {
            "BTN_START_GAME":  "New Game",
            "BTN_HOW_TO_PLAY":  "How To Play",
            "TEXT_HOW_TO_PLAY":  "Q or E -> rotate camera\nW, A, S, D or left mouse click and drag -> move camera\nRight mouse button or numeric keyboard (1, 2, 3, 4) -> place tower",
            "BTN_CLOSE":  "Close",
	}
}

Language Manager

Após, foi criado um script responsável por gerenciar essa questão de abrir o arquivo de linguagens, obter tal texto por uma determinada chave e também atualizar todos objetos de texto que necessitam obter do JSON. Já que estou fazendo o jogo na Unity, há uma função chamada "DontDestroyOnLoad" que coloquei no método Start do meu script para que ao trocar de cena (exemplo: do menu para a a gameplay em si) não seja destruído para ser carregado em outra cena, já que ele é responsável por manipular o arquivo.
Vou citar duas funções interessantes e que são o "core" desse sistema:

//Acessa determinada chave do texto que você deseja baseado no idioma selecionado
public  string  GetTextByKey(string  textKey){
	JObject translationFile =  JsonConvert.DeserializeObject<JObject>(languageFile.text);

	return translationFile[GetLanguageKey()][textKey].ToString();
}

//Vai pegar todos os textos que estejam referenciados nesse script e baseado na linguagem selecionada vai atualizá-los
public  void  SetLanguage(string  key){
	currentLanguageKey =  key;

	PlayerPrefs.SetString("LanguageKey", currentLanguageKey);

	UpdateAllListeners();

}

O interessante foi que ao usar o "PlayerPrefs.SetString" ele salva essa configuração para que quando voltar ao jogo continue com a última opção selecionada. No navegador ele salva usando IndexedDB API, já no Windows por exemplo, ele salva no registro do sistema.

Script que manipula os textos em si

Além de ter o gerenciador de idiomas eu criei um script que vai pegar a chave definida para tal e vai chamar as funções do LanguageManager e também cadastrar como um Listener para que possa ser possível atualizar todos os textos ao clicar num botão na tela por exemplo.

[SerializeField] private  string textKey =  "";
private  TMP_Text text;
private  UnityEngine.UI.Text nativeText;  

void  Start(){
	LanguageManager.Instance.TextListeners.Add(this);
	UpdateText();
}

public  void  UpdateText(){
	text =  GetComponent<TMP_Text>();
	nativeText =  GetComponent<UnityEngine.UI.Text>();

	if(text !=  null)
		text.text  =  LanguageManager.Instance.GetTextByKey(textKey);
	if(nativeText !=  null)
		nativeText.text  =  LanguageManager.Instance.GetTextByKey(textKey);
}

E foi essa minha experiência em desenvolver meu próprio sistema de troca de idiomas para meu jogo sendo feito na Unity. Espero que tenha agregado algo concreto em vocês e já estava com a vontade de falar sobre pois foi uma ideia relativamente simples mas que deu um trabalhinho meio grande devido a questão da performance, pois haviam outras maneiras de se fazer mas que não eram satisfatórias.

Gostaria de agradecer a atenção de todos e também falar que lançou finalmente a atualização 3 do meu jogo com muitas modificações:

Para jogar: https://rodrigoborges.itch.io/arkadon
Para saber mais sobre a versão 3: Changelog
Link discord: Clique aqui

As próximas atualizações serão feitas para correções de bugs e balanceamento da gameplay, necessito da ajuda de todos, se possível, para jogar e me sugerir o que pode mudar, por exemplo: tal inimigo está com muito dano inicial, nerfa, e entre outras dicas.

Valeu demais por todo o apoio da comunidade até então, pois me incentivaram demais e me deram um ânimo absurdo. Agradeço demais também a oportunidade e a liberdade de ter postado aqui no TabNews, sem palavras! ☺️

Carregando publicação patrocinada...
4
{
  "pt": {
           "BTN_START_GAME":  "Novo Jogo",
           "BTN_HOW_TO_PLAY":  "Como Jogar",
           "TEXT_HOW_TO_PLAY":  "Q ou E -> gira a câmera\nW, A, S, D ou botão esquerdo do mouse e arrastar -> movimenta a câmera\nBotão direito do mouse ou teclado numérico (1, 2, 3, 4) -> coloca uma torre",
           "BTN_CLOSE":  "Fechar",
  },
  "en": {
           "BTN_START_GAME":  "New Game",
           "BTN_HOW_TO_PLAY":  "How To Play",
           "TEXT_HOW_TO_PLAY":  "Q or E -> rotate camera\nW, A, S, D or left mouse click and drag -> move camera\nRight mouse button or numeric keyboard (1, 2, 3, 4) -> place tower",
           "BTN_CLOSE":  "Close",
  }
}

Achei interessante porque eu tive uma idéia muito parecida em um projeto pessoal meu (que pretendo tornar open-source futuramente).

Inicialmente, a idéia foi idêntica à sua, mas encontrei um problema. No futuro, com mais idiomas adicionados, ficaria muito trabalhoso reescrever o comando em cada idioma diferente.

A solução foi adicionar a chave sendo o comando, e o valor as traduções mais ou menos assim:


{
	"BTN_START_GAME": {
              "pt": "Novo Jogo",
              "en": "New game"
        },
        "BTN_HOW_TO_PLAY":  {
               "pt": "Como Jogar",
               "en": "How to play"
        }
        ...
        ...
}

Será que essa é realmente a melhor opção?

3

Boa ideia, fiz algo semelhante em um projeto pessoal e realmente reduz muito a repetição de chaves. Sem contar que pra navegar no JSON ficou bem mais intuitivo, pois como as chaves de idioma estão todas no mesmo alinhamento, é mais fácil de comparar as strings para uma eventual correção na tradução 😄

1

Com certeza, tem esse outro benefício de comparação e também para possíveis correções de traduções. Vou mudar para ficar melhor. Obrigado pelo feedback pessoal!

2

Opa, valeu pelo feedback Gabriel!

Concordo com você, se torna muito repetitivo para adicionar mais idiomas. Acho que vou fazer essa alteração tanto no JSON quanto nos scripts responsáveis por pegar a informação, assim vou ter apenas uma chave para buscar tal informação de texto e dentro dela conter os valores referentes a tal idioma.

1

Eu acho que nesse caso vocês vão criar um excesso de repetições desnecessário. No meu caso eu criaria um JSON para cada idioma e concentraria um por um ali, usando o mesmo esquema de

3

Eu acho que você não terminou de escrever o seu comentário ou aconteceu algum bug, mas na minha opinião, criar um arquivo JSON para cada idioma daria no mesmo do que foi feito no código dele. A única diferença é que iria ter mais arquivos no programa.

0

Uma coisa que me surgiu na mente aqui agora. Vocês tem interesse em desenvolvimento de jogos, mais precisamente em como desenvolver em si (mão na massa)? Pois estou pensando em começar a fazer vídeos sobre, utilizando a Unity. Gostaria de trazer mais conhecimento a respeito disso!