事件功能未按预期工作

Fla*_*ius 7 c# function event-handling unity-game-engine unity5

首先,我将解释发生的事情,然后是我期待发生的事情,最后是它背后的代码

所以当我按下输入时,文本的颜色是绿色

我期望发生的是颜色变红

这是基于if我在字段中输入"Bad"

//Please note I have edited uni9mportant code out

//Event Listener
inputField.onEndEdit.AddListener (delegate {
            VerifyWords();
});

//Clss that handles the dictionary
public abstract class WordDictionary: MonoBehaviour{
    public static Dictionary<string,bool> _wordDictionary = new Dictionary<string,bool> ();

    private void Start(){
        _wordDictionary.Add ("Bad",true);
    }
}

//Function that handles the word verification
private void VerifyWords(){
        if (openChat == false) { //If we done have open chat
            bool hasBadWords = false; //Reset boolean
            string[] stringSplit = inputField.text.Split (' '); //Split text string

            for (int i = 0; i < stringSplit.Length; i++) { // Go through each word in the string array
                if (WordDictionary._wordDictionary.ContainsKey (stringSplit[i])) { //If the word is in the dictionary
                    hasBadWords = true; //Then there is a bad word
                }
            }

            if (hasBadWords == true) { //If a bad word was found
                inputField.textComponent.color = Color.red; //Then the text should be red
            } else {
                inputField.textComponent.color = Color.green; //The text should be green
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

编辑我编写了带有注释的代码,以便将我的思考融入其中

Ron*_*yer 4

问题是该类被标记为abstract. 抽象类无法实例化,因此 Unity 无法调用Start它无法实例化的类。abstract最简单的修复方法是简单地从类定义中删除:

public class WordDictionary: MonoBehaviour{
    public static Dictionary<string,bool> _wordDictionary = new Dictionary<string,bool> ();

    private void Start(){
        _wordDictionary.Add ("Bad",true);
    }
}
Run Code Online (Sandbox Code Playgroud)

然而你现在有一个新问题。WordDictionary有一个由非静态方法初始化的静态成员。这意味着每次您创建一个新的WordDictionary,都会被调用,并且它将再次Start()将所有单词添加到字典中(或者至少它会尝试这样做,在这种情况下您将得到重复的键异常,以避免您也可以write替换现有密钥(如果存在)。_wordDictionary["Bad"] = true

这里更好的选择是使用静态构造函数。这将确保字典仅初始化一次:

public class WordDictionary: MonoBehaviour{
    public static Dictionary<string,bool> _wordDictionary = new Dictionary<string,bool> ();

    static WordDictionary() {
        _wordDictionary.Add ("Bad",true);
    }

    private void Start(){
    }
}
Run Code Online (Sandbox Code Playgroud)

现在您可以使用WordDictionary而不必担心每次实例化类时字典都会增长。WordDictionary但在这一点上,制作a确实没有用,MonoBehavior因为它实际上只是一堆单词的持有者。所以你的类现在就变成了:

public class WordDictionary: {
    private static Dictionary<string,bool> _wordDictionary = new Dictionary<string,bool> ();

    public static Dictionary<string, bool> Words {
        get { return _wordDictionary; }
    }

    static WordDictionary() {
        _wordDictionary.Add ("Bad",true);
    }
}
Run Code Online (Sandbox Code Playgroud)

我在这里添加了一个属性,因为实际上您应该使用属性,并且具有下划线名称(在我的代码世界中)意味着它是一个私有字段。您可以扩展字典来执行其他操作:

public class WordDictionary: {
    private static List<string> _wordList = new List<string> ();

    static WordDictionary() {
        _wordList.Add ("Bad");
    }

    public static Contains(string word) {
        return _wordList.Contains(word);
    }

    public static ContainsAny(IEnumerable<string> words) {
        return words.Any(w => Contains(w));
    }
}
Run Code Online (Sandbox Code Playgroud)

我看不出有任何理由Dictionary在这里使用 a,如果它包含这个词那么它就是“坏”,如果它不包含这个词那么它就是“好”。因此,更改为列表会使事情变得更简单。如果你隐藏“字典”在后台的工作方式,只暴露“包含”和“包含任何”方法,你会得到两个好处,使用变得更简单,并且你可以在不改变接口和下游的情况下改变底层“引擎”代码。

现在你的着色函数变得更加简单:

private void VerifyWords() {
    if (openChat)
        return;

    var stringSplit = inputField.text.Split(' ');

    if (WordDictionary.ContainsAny(stringSplit))                
        inputField.textComponent.color = Color.red;
    else
        inputField.textComponent.color = Color.green;
}
Run Code Online (Sandbox Code Playgroud)