Get localized object name the player is looking at

Hey,
I’ve a script changing a TMPText to the object name the player is actively looking at. E.g. the player is looking at a gas canister object and the text will change to “Gas Canister”. Currently I’m just fetching the gameobjects name:

_raycastNameTMP.text = hit.transform.gameObject.name;

But I want to localize the name. E.g. if the language is set to german the TMPText should show “Gaskanister” instead of “Gas Canister”.

For testing I created localization settings, two locals (en<-default and de) and one string table with a string (key: item.gascanister) and added a Localize String Event to the TMPText.

So basically I need to get a localization string by a key like “item.[gameobject.name]” or maybe giving each item type an ID and use keys like item.0, item.1 etc.? What do I have to do to achieve this?

Appreciate any help.

Hey.

Here’s a few different ways to approach this:

  1. Use the GameObject name as your key. Continue to use the gameobject name as the key but also put an English value like so
    8125265--1053554--upload_2022-5-13_14-52-34.png

Then in script:
_raycastNameTMP.text = LocalizationSettings.StringDatabase.GetLocalizedString("My String Table", hit.transform.gameObject.name);

This is a little brittle as you may change the GameObject name and lose the connection to the table entry.

  1. Create a localized name component.
public class LocalizedName : MonoBehaviour
{
    public LocalizedString componentName;
}
_raycastNameTMP.text = hit.transform.GetComponent<LocalizedName>().componentName.GetLocalizedString();

This is safer as you wont lose the connection and can always change the key names providing you set the reference through the inspector(it will use the id, not key name)

It may be worth localizing the whole sentence instead of just the word as the order of the words can change.

  1. An improvement to 2. Use a LocalizedStringEvent on your TMP component8125265--1053563--upload_2022-5-13_15-1-13.png

Now to set the text change the reference like so:

var localizeString = _raycastNameTMP.GetComponent<LocalizeStringEvent>();
var target = hit.transform.GetComponent<LocalizedName>();

localizeString.StringReference = target.componentName;

This is a little better:

  • If the player changes the language it will update automatically
  • If the string table is not yet loaded then it will load in the background and wont block the main thread.

Thanks for your quick answer. I tried the first one and put this into my code for testing:

_raycastNameTMP.text = LocalizationSettings.StringDatabase.GetLocalizedString("UI Text", "gascanister");

I also created the string inside the table “UI Text” but Unity crashes when I look at an object.

This is from the Editor Log:

FirstPersonController.cs:152 is where the mentioned code is.

What version of Unity is this running on? Is this in the player or Editor?

Editor, Unity 2021.2.19f1

Can you try running the Addressables analyzer?
https://docs.unity3d.com/Packages/com.unity.localization@1.3/manual/Addressables.html#addressable-analyzers

Just did that and had some errors and warnings. I fixed all of them except the Unfixable Rules:
8125598--1053641--unity_local_analyze.PNG

Now it’s working and there are no crashes anymore. There’s only one issue left: The default language should be english but when I play it’s german.
8125598--1053650--unity_local_settings.PNG

1 Like

Is your operating system German?
I can’t see any reason it would be using German

It is, didn’t now it updates the language automatically :smile:
I tried to implement your second suggestion and get these errors when I add Localization String Event to my TMP and every time I open it in the editor:

And I have a microlag in playmode when I get a localizationstring for the first time.

I fixed that problem. The editor throw errors if the Localize String Event has no default string reference.

I’m now trying to combine the fetched value with another Smart Localization String. So the player sees the item amount and its name (plural/singular) like “You’ve 1 gas canister.” or “You’ve 20 gas canisters.”.

I’ve found two solutions for that so far (the test item is a carrot because the gas canister is a bad example, because the german plural and singular are the same :smile:):

Solution 1:
8129651--1054502--unity_local_solution_1A.PNG

8129651--1054505--unity_local_solution_1B.PNG

_localString.StringReference.Arguments = new object[]
        {
            new Dictionary<int, object>
            {
                [0] = plantamount,
                [1] = plantamount == 1 ?
                    LocalizationSettings.StringDatabase.GetLocalizedString("UI Text", "plant.carrot") :
                    LocalizationSettings.StringDatabase.GetLocalizedString("UI Text", "plant.carrots")
            }
        };

        _localString.RefreshString();

Solution 2:
8129651--1054508--unity_local_solution_2A.PNG
8129651--1054511--unity_local_solution_2B.PNG

(_localString.StringReference["plant-amount"] as IntVariable).Value = plantamount;
        (_localString.StringReference["plant-type"] as StringVariable).Value = plantamount == 1 ?
            LocalizationSettings.StringDatabase.GetLocalizedString("UI Text", "plant.carrot") :
            LocalizationSettings.StringDatabase.GetLocalizedString("UI Text", "plant.carrots");

Both solutions do work but both also throw a NullReferenceException at their first line. How could I fix that?

You want to use a plural smart string for this
https://docs.unity3d.com/Packages/com.unity.localization@1.3/manual/Smart/Plural-Formatter.html

What does the full error say?

Just did it and replaced the plant.carrot value with {0:plural:Carrot|Carrots} and removed plant.carrots. Should be the best solution in my case.

The full error says:

Can you share the LocalTest script?

using UnityEngine;
using UnityEngine.Localization.Settings;
using UnityEngine.Localization.Components;
using UnityEngine.Localization.SmartFormat.PersistentVariables;
using System.Collections.Generic;

public class LocalTest : MonoBehaviour
{
    public LocalizeStringEvent _localString;
    public int plantamount = 0;

    private void Update()
    {
        /*_localString.StringReference.Arguments = new object[]
        {
            new Dictionary<int, object>
            {
                [0] = plantamount,
                [1] = plantamount == 1 ?
                    LocalizationSettings.StringDatabase.GetLocalizedString("UI Text", "plant.carrot") :
                    LocalizationSettings.StringDatabase.GetLocalizedString("UI Text", "plant.carrots")
            }
        };

        _localString.RefreshString();*/

        (_localString.StringReference["plant-amount"] as IntVariable).Value = plantamount;
        (_localString.StringReference["plant-type"] as StringVariable).Value = plantamount == 1 ?
            LocalizationSettings.StringDatabase.GetLocalizedString("UI Text", "plant.carrot") :
            LocalizationSettings.StringDatabase.GetLocalizedString("UI Text", "plant.carrots");
    }
}

The error is now in line 27

It looks like the variable is not being found. Maybe this script is on a different game object or there’s a typo in the name?
Try doing the plural smart string and just use a single integer value instead of also including the string.

I restartet Unity (unintentionally) and no there’s no error anymore :eyes: I hope it stays like this. Thank you very much for your help and patience :slight_smile:

1 Like