Unity String Reference Workaround

I just wanted to share in case anyone else finds this useful. It’s very basic, but I’ve been doing something similar for years in most of my projects, Unity or otherwise.

String references can be a pain in the butt, and copy-pasting them from Unity into the scripts is just obnoxious and annoying. Instead of being constantly annoyed by them cluttering up my code, I always end up making a class of constants to reference. Also, this way if I ever do want to change the string, it is much less nerve-wracking to do so.

For Example, instead of using this:

animator.SetTrigger( "attack" );    // after having made sure to copy/paste it correctly, often in many locations.

I can simply use this:

animator.SetTrigger( StringReferences.STOP_ATTACK_TRIGGER );

to access constant variables in my unity project

namespace RPG.Core   // A simple class to keep the string parameters Unity
{
	static class StringReferences
	{
		// From Character Animator Controllers (types: Float, Int, Bool, Trigger)
		public const string FORWARD_SPEED_FLOAT = "forwardSpeed";
		public const string ATTACK_TRIGGER = "attack";
		public const string DIE_TRIGGER = "die";
		public const string STOP_ATTACK_TRIGGER = "stopAttack";
	}
}

Sometimes the names are longer/more descriptive (ANIMATOR_CHAR_TRIGGER_ATTACK) or I put a few classes in the file (one for character parameters, one for effects, etc) depending on how many string references my project has and if I feel it needs to be split up more for quicker access. I’ve done it via Dictionaries, enums, and other grouping methods, but have found this to be the simplest and fastest option to just get going.

Does anyone else have things they do to cut down on typo errors? If so, please share, I’d love to hear them! :grinning:

7 Likes

This is an excellent suggestion, and is a widely used solution for the magic string problem.

Well done!

1 Like

thanks for the share. +1 internet points for you!

You can actually do better.

If you use Rider as your editor (not free though), it automatically suggests this:

        private static readonly int HitTrigger = Animator.StringToHash("Hit");

.
.
.
       GetComponent<Animator>().SetTrigger(HitTrigger);

You can further improve this with the use of “using static”:

namespace RPG.Core   // A simple class to keep the string parameters Unity
{
	public static class StringReferences
	{
		// From Character Animator Controllers (types: Float, Int, Bool, Trigger)
		public const string FORWARD_SPEED_FLOAT = "forwardSpeed";
		public const string ATTACK_TRIGGER = "attack";
		public const string DIE_TRIGGER = "die";
		public const string STOP_ATTACK_TRIGGER = "stopAttack";
	}
}

in your other class, put this at the top

using static RPG.Core.StringReferences;

Then you don’t need the word “StringReferences” anymore:

// before
animator.SetTrigger(StringReferences.STOP_ATTACK_TRIGGER);

// after
animator.SetTrigger(STOP_ATTACK_TRIGGER);
2 Likes

An even better approach is to to use a combination of both string reference above with the Animator.StringToHash

namespace RPG.Core
{
    public static class StringReferences
    {
        public static string forwardSpeedFloat = "ForwardSpeed";
        public static string attackTrigger = "Attack";
        public static string stopAttackTrigger = "StopAttack";
        public static string deathTrigger = "Die";
    }
}

and then in your code

using Unity.Mathematics;
using UnityEngine;
using static RPG.Core.StringReferences;

namespace RPG.Attributes
{
    public class Health : MonoBehaviour
    {
        #region Inspector Fields
        // All [SerializeField] 
        #endregion

        #region Private Fields
       // all private fields
        #endregion

        #region Component References

        #region Optional

        /// <value>Cache the <a href="https://docs.unity3d.com/ScriptReference/Animator.html">UnityEngine.Animator</a></value>
        private Animator m_animator;

        private bool m_hasAnimator;
        private static int _dieHash;

        #endregion

        #endregion

        #region Properties
        // All Properties
        #endregion

        #region Unity Messages

        /// <summary>
        /// <seealso href="https://docs.unity3d.com/ScriptReference/MonoBehaviour.Awake.html"/>
        /// </summary>
        private void Awake()
        {
            m_animator = GetComponentInChildren<Animator>();
            m_hasAnimator = m_animator != null;

            if (m_hasAnimator)
            {
                _dieHash = Animator.StringToHash(deathTrigger);
            }
        }

        #endregion
    }

I use static instead of const because I also like to have an Editor Script so that I can Edit these values in an Editor Window or add it to the project settings, or create an Automatic syncing script, the possibilities are endless if you make them static strings.

Unity_tyIAX1BqJf

using UnityEditor;
using UnityEngine;
using static RPG.Core.StringReferences;

namespace RPG.Core.Editor
{
    public class StringReferencesEditor : EditorWindow
    {
        [MenuItem("Window/RPG Tool Kit/String References Editor")]
        public static void ShowExample()
        {
            StringReferencesEditor wnd = GetWindow<StringReferencesEditor>();
            wnd.titleContent = new GUIContent("String References");
        }

        private void OnGUI()
        {
            using (new EditorGUILayout.VerticalScope())
            {
                GUILayout.Label("Animator Parameters", EditorStyles.boldLabel);

                forwardSpeedFloat = EditorGUILayout.TextField("Forward Speed Float", forwardSpeedFloat);
                attackTrigger = EditorGUILayout.TextField("Attack Trigger", attackTrigger);
                stopAttackTrigger = EditorGUILayout.TextField("Stop Attack Trigger", stopAttackTrigger);
                deathTrigger = EditorGUILayout.TextField("Death Trigger", deathTrigger);
            }
        }
    }
}
1 Like

Privacy & Terms