@M0rrigan You’re calling text.replace more than once on the string
for example you swap “H” with <color=#3D3D3DFF>H</color>
but then you call it again for the “D”, and the Replace function is detecting the letters within the color property. giving you:
color=#3<color=#3D3D3DFF>D</color>3<color=#3D3D3DFF>D</color>3<color=#3D3D3DFF>D</color>FF>H</color>
all of that is just for the H character, very ugly. and this is whats breaking it as now it can’t be parsed correctly
String.Replace is NOT what you want to use for this!
Try and use RegEx (aka regular expressions). then you can simply run the regex on the base string for the new string of colors. I would recommend that you save the base string somewhere so that if you need to swap colors again you can just use the base (trying to regex a string that already went through a replace is just working hard, not smart) .
Edit: After seeing your class in the comment I see how you were trying to use it. so I rewrote the class to be a little more to how you want it;
First off you want to add this component class to the gameobject that is firing the OnTriggerEnter:
using UnityEngine;
using UnityEngine.Events;
public class TriggerRelay: MonoBehaviour
{
private class Delegator<T> : UnityEvent<T>{}
private Delegator<Collider> OnTriggerEnter_ = new Delegator<Collider>();
private Delegator<Collider> OnTriggerExit_ = new Delegator<Collider>();
public void AttachEnter(UnityAction<Collider> listener)
{
OnTriggerEnter_.AddListener(listener);
}
public void DetachEnter(UnityAction<Collider> listener)
{
OnTriggerEnter_.RemoveListener(listener);
}
public void AttachExit(UnityAction<Collider> listener)
{
OnTriggerExit_.AddListener(listener);
}
public void DetachExit(UnityAction<Collider> listener)
{
OnTriggerExit_.RemoveListener(listener);
}
void OnTriggerEnter(Collider other)
{
OnTriggerEnter_.Invoke(other);
}
void OnTriggerExit(Collider other)
{
OnTriggerExit_.Invoke(other);
}
}
This class is just a relay to pass on trigger collision events to other gameobjects. From my experience in design patterns such as MVC, I’ve found that its easier if your game logic doesn’t explicitly know that a UI exists (but it can have public variables and methods that some classes like a UI might use). the UI can know about the Game logic, but the Game Logic shouldn’t know about the UI. Keeping this in mind will help a lot in preventing you from coding into some traps later on (cause you’re minimizing dependency, and allows the game logic to have complete control over the game play as it should).
now as for that other class that will be going on Gameobject that has the Text Component:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using UnityEngine;
using UnityEngine.UI;
public class ColorText: MonoBehaviour
{
public TriggerRelay relay;
public IDictionary<string,string> characterMap = new Dictionary<string,string>()
{
{"H","<color=#003D3DFF>H</color>"},
{"E","<color=#3D003DFF>E</color>"},
{"L","<color=#3D3D00FF>L</color>"},
{"O","<color=#DD3D3DFF>O</color>"},
{"W","<color=#3DDD3DFF>W</color>"},
{"R","<color=#3D3DDDFF>R</color>"},
{"D","<color=#8D3D3DFF>D</color>"},
{"I","<color=#3D8D3DFF>I</color>"},
{"S","<color=#3D3D8DFF>S</color>"},
{"M","<color=#FFFFFFFF>M</color>"}
};
Text myText;
string baseString;
bool isFormatted;
void Awake()
{
myText = GetComponent<Text>();
isFormatted = false;
}
void OnEnable()
{
if(relay)
{
relay.AttachEnter(WhenTriggerEnter);
relay.AttachExit(WhenTriggerExit);
}
isFormatted = false;
baseString = myText.text;
}
void OnDisable()
{
if(relay)
{
relay.DetachEnter(WhenTriggerEnter);
relay.DetachExit(WhenTriggerExit);
}
isFormatted = false;
myText.text = baseString;
}
public void ChangeText(string newText)
{
myText.text = baseString = newText;
if(isFormatted)
{
Format();
}
}
void Format()
{
Regex regex
= new Regex (String.Join ("|", characterMap.Keys.Select(c => Regex.Escape(c)).ToArray()));
myText.text = regex.Replace (baseString, m => characterMap [m.Value]);
}
void WhenTriggerEnter(Collider o)
{
Format();
isFormatted = true;
}
void WhenTriggerExit(Collider o)
{
myText.text = baseString;
isFormatted = false;
}
}
just drag in the reference of the TriggerRelay onto the component in the inspector (or if you are instantiating it at runtime you can set it then)