1

I am sure its possible, but I haven't figured out how. How would I go about using string interpolation for scriptableObjects? Some basic code I have for it:

    public class ScriptableCardBase : ScriptableObject
    {
      public string cardDes;
    }
        
     public class CardUI : MonoBehaviour
    {
        public List<ScriptableCardBase> card = new List<ScriptableCardBase>();
        
        public Text desText;
        
        public void DisplayCard(int i)
        {
         desText.text = card[i].cardDes;
        }
    }

For my cards, I just want to be able to display the damage of the card, or number of effects, etc. Here is a screenshot of what the SO Card looks like and where I try to input the string. Any help would be greatly appreciated!

CardSO

I guess a long questions short is, can I use string interpolation with scriptable objects?

  • Nothing out of the box, no. The difficult bit of that system, which is turning expressions into values, is handled at compile time, so you'd have to reimplement what the C# compiler does. Although, if you limit the valid expressions to a specific subset, for example fields on the object, you can probably get away with a regex. – Etienne de Martel May 24 '22 at 00:08
  • I am not sure what you're asking for here. You can do string interpolation in the `CardUI` class, so what do you mean when you're asking if you can do string interpolation "for scriptable objects?" You could do something like `desText.text = $"This card does {card[i].damage} damage with a {card[i].effect} effect."` – Chuck May 24 '22 at 13:49

1 Answers1

0

What you want is to convert your string to its Formattable version.

You can do it via reflection or some sort of IL you want. Some start could be:

public static string ParseFromFormattable(this string str, object context) {
    // Define a random char that is unlikely to appear on normal text.
    const char weirdChar = '°'; // This will prepend the interpolation parameters

    var outputStr = "";

    // Split all the parts and iterate through them, using reflection to get the value from values inside '{}'
    foreach (var part in GetStringParts()) {
        if (part[0] == weirdChar) { outputStr += context.GetType().GetField(part.Substring(1)).GetValue(context).ToString(); }
        else { outputStr += part; }
    }
    return "";


    List<string> GetStringParts() {
        var strParts = new List<string>();
        var currentPart = "";
        var writingParam = false;

        foreach (var c in str) {
            if (c == '{') {
                if (currentPart != "") { strParts.Add(currentPart); }
                currentPart = "";
                writingParam = true;
            }
            else if (writingParam && c == '}') {
                strParts.Add(weirdChar + currentPart);
                currentPart = "";
                writingParam = false;
            }
            else { currentPart += c; }
        }
        strParts.Add(currentPart); // Don't forget to add the last string
        return strParts;
    }
}

Note this is a very basic version that doesn't support complex interpolation parameters.. Only parameters that are field members of the class that is passed as 'context' will be supported.

You can expand the reflection parts to support propeties, methods, and references if you want.. or even direct code (math operations, etc). I would highly recommend just using some IL instead, though.

Lyrca
  • 528
  • 2
  • 15