替换字符串UNITY中的动态变量

时间:2018-12-16 07:22:14

标签: regex string unity3d reflection

我正在建立一个简单的对话系统,并希望“动态化”某些句子。 例如,我有一个句子

  

嘿冒险家{{PlayerName}}!   欢迎世界各地!

现在在代码中,我试图用游戏中字符串的实际值替换它。我正在做这样的事情。但这是行不通的。我的功能所在的组件中确实有一个string PlayerName

Regex regex = new Regex("(?<={{)(.*?)(?=}})");
MatchCollection matches = regex.Matches(sentence);

for(int i = 0; i < matches.Count; i++)
{
    Debug.Log(matches[i]);
    sentence.Replace("{{"+matches[i]+"}}", this.GetType().GetField(matches[i].ToString()).GetValue(this) as string);
}
return sentence;

但是即使匹配正确,这也会返回一个错误。

有什么方法可以解决,还是做得更好?

3 个答案:

答案 0 :(得分:1)

这是我要解决的方法。

创建一个字典,其中包含要替换的键和要替换的键的值。

new_dataset$SequenceNr[1:16] <- 1
new_dataset$SequenceNr[17:32] <- 2
new_dataset$SequenceNr[33:48] <- 3
new_dataset$SequenceNr[49:64] <- 4

然后检查字典中值的文本。 如果您确定所有键都以“ [[]”开头,并以“]”结尾,那么这将是快速简便的事情。

Dictionary<string, string> valuesToReplace;
valuesToReplace = new Dictionary<string, string>();
    valuesToReplace.Add("[playerName]", "Max");
    valuesToReplace.Add("[day]", "Thursday");

这也将更快地工作,因为它允许您在不降低代码速度的情况下添加任意数量的变量。

答案 1 :(得分:0)

使用Regex.Replace方法和一个MatchEvaluator委托(未经测试):

    Dictionary<string, string> Replacements = new Dictionary<string, string>();
    Regex DialogVariableRegex = new Regex("(?<={{)(.*?)(?=}})");

    string Replace(string sentence) {

        DialogVariableRegex.Replace(sentence, EvaluateMatch);

        return sentence;
    }

    string EvaluateMatch(Match match) {

        var matchedKey = match.Value;

        if (Replacements.ContainsKey(matchedKey))
            return Replacements[matchedKey];
        else
            return ">>MISSING KEY<<";
    }

答案 2 :(得分:0)

这现在有点老了,但我想我会更新上面接受的代码。它不会工作,因为每次循环迭代时都会重置起始索引,因此设置 startOfVar = i 在它遇到结束字符时会完全重置。另外,如果有一个开放的括号 '[' 而没有结束的括号,则会出现问题。您也不能再在文本中使用这些括号。

还将分隔符设置为单个字符。它测试正常,但如果我将我的播放器名称设置为“Rob}ert”,则在执行替换时会出现问题。

这是我在 Unity 中测试过的代码的更新:

    public string EvaluateVariables(string str)
    {
        Dictionary<string, string> varDict = GetVariableDictionary();
        List<string> varReplacements = new List<string>();
        string matchGuid = Guid.NewGuid().ToString();
        bool matched = false;

        int start = int.MaxValue;
        for (int i = 0; i < str.Length; i++)
        {
            if (str[i] == '{')
            {
                if (str[i + 1] == '$')
                {
                    start = i;
                    matched = true;
                }
            }
            else if (str[i] == '}' && matched)
            {
                string replacement = str.Substring(start, (i - start) + 1);
                if (varDict.ContainsKey(replacement))
                {
                    varReplacements.Add(replacement + matchGuid + varDict[replacement]);
                }
                start = int.MaxValue;
                matched = false;
            }
        }

        foreach (string replacement in varReplacements)
        {
            str = str.Replace(replacement.Split(new string[] { matchGuid }, StringSplitOptions.None)[0], replacement.Split(new string[] { matchGuid }, StringSplitOptions.None)[1]);
        }

        return str;
    }

    private Dictionary<string, string> GetVariableDictionary()
    {
        Dictionary<string, string> varDict = new Dictionary<string, string>();
        varDict.Add("{$playerName}", playerName);
        varDict.Add("{$npcName}", npcName);
        return varDict;
    }