如何使用Unity InputField调用Reference变量

时间:2017-11-06 06:42:00

标签: c# unity3d

我的问题是:当我输入“@”时,它会调用一个下拉列表,所以我可以从下拉列表中选择一个变量,我可以在InputFiled上输入如下:我的分数是@mscore,他得分是@hscore 。最后我按了一个按钮(也许叫“结账”),它会显示mscore和hscore的值,就像这样:我的分数是10,他得分是8。我怎么能完成这个功能?

1 个答案:

答案 0 :(得分:1)

这是一个完整的脚本。

  1. 将脚本附加到您想要的游戏对象
  2. 拖动&删除您要输入的输入字段
  3. 指定父RectTransform,它将标记建议列表放入以下脚本的tagsParent字段中。 (我已经附加到InputField并且附加了VerticalLayoutGroup,这是非常的)
  4. 使用Text组件和Button组件创建预制件(我使用了您可以在GameObject&gt; UI菜单中创建的标准Unity按钮)< / LI>
  5. 将预制件添加到以下脚本的tagPrefab字段
  6. 创建一个按钮并为其添加一个监听器,使用以下脚本选择对象并选择ReplaceTags功能
  7. using UnityEngine;
    using UnityEngine.UI;
    using System.Linq;
    using System.Text.RegularExpressions;
    using System.Collections.Generic;
    using System.Reflection;
    
    public class AutoFill : MonoBehaviour
    {
        public float mscore = 5 ;
        public float hscore = 10 ;
    
        public InputField inputField;
        public RectTransform tagsParent;
        public RectTransform tagPrefab;
    
        private List<FieldInfo> fields ;
        private Regex endRegex = new Regex( "@[a-zA-Z0-9]+$" );
        private Regex regex = new Regex( "@[a-zA-Z0-9]+" );
    
        /// <summary>
        /// Awake is called when the script instance is being loaded
        /// </summary>
        private void Awake()
        {
            fields = GetType().GetFields( BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public )
                            .Where( fieldInfo => fieldInfo.FieldType == typeof( float ) ) // Use this if you want to retrieve only the floating variables
                            .ToList();
    
            inputField.onValueChanged.AddListener( OnInputValueChanged );
        }
    
        /// <summary>
        /// Called when the value of the input has changed
        /// </summary>
        /// <param name="input"></param>
        private void OnInputValueChanged( string input )
        {
            Match match = endRegex.Match( inputField.text );
            if ( match.Success )
            {
                string value = match.Value.Substring(1);
                List<string> tags = GetTagsStartingWith( value );
    
                FillTagsSuggestions( match.Value, tags );
            }
            else
            {
                FillTagsSuggestions( string.Empty, new List<string>() );
            }
        }
    
        /// <summary>
        /// Fill the tags suggestion
        /// </summary>
        /// <param name="tagInput"></param>
        /// <param name="tags"></param>
        private void FillTagsSuggestions( string tagInput, List<string> tags )
        {
            int length = Mathf.Max( tags.Count, tagsParent.childCount );
    
            for ( int index = 0 ; index < length ; index++ )
            {
                int i = index; // Used to prevent closure problem
                if ( index < tags.Count )
                {
                    AddTagSuggestion( tags[index], index, tagInput );
                }
                else if( index < tagsParent.childCount )
                {
                    tagsParent.GetChild( index ).gameObject.SetActive( false );
                }
            }
        }
    
        /// <summary>
        /// Adds a tag suggestion
        /// </summary>
        /// <param name="tag"></param>
        /// <param name="index"></param>
        /// <param name="tagInput"></param>
        private void AddTagSuggestion( string tag, int index, string tagInput )
        {
            Text text;
            RectTransform suggestionTransform;
    
            // Get existing button if exists
            if ( index < tagsParent.childCount )
            {
                suggestionTransform = tagsParent.GetChild( index ) as RectTransform;
                suggestionTransform.gameObject.SetActive( true );
                text = suggestionTransform.GetComponentInChildren<Text>();
            }
            // Create new button if does not exist yet
            else
            {
                suggestionTransform = Instantiate( tagPrefab );
                text = suggestionTransform.GetComponentInChildren<Text>();
                suggestionTransform.SetParent( tagsParent, true );
            }
    
            text.text = tag;
    
            // Add listener to replace the input by the value of the tag
            Button btn = suggestionTransform.GetComponentInChildren<Button>();
            btn.onClick.RemoveAllListeners();
            btn.onClick.AddListener( () =>
            {
                inputField.text = ReplaceTag( inputField.text, tagInput, tag );
                StartCoroutine( MoveTextEndDelayed() );
            } );
        }
    
        private System.Collections.IEnumerator MoveTextEndDelayed()
        {
            inputField.Select();
            yield return null;
            inputField.MoveTextEnd( false );
        }
    
        /// <summary>
        /// Gets the tag starting with the given input
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        private FieldInfo GetTagStartingWith( string input )
        {
            return fields.Find( field => field.Name.StartsWith( input ) );
        }
    
        /// <summary>
        /// Gets all the tags starting with the given input
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public List<string> GetTagsStartingWith( string input )
        {
            return fields.FindAll( field => field.Name.StartsWith( input ) && field.Name.CompareTo( input ) != 0 ).Select( field => field.Name ).ToList();
        }
    
        /// <summary>
        /// Replaces the value in the input by the tagName
        /// </summary>
        /// <param name="input"></param>
        /// <param name="value"></param>
        /// <param name="tagName"></param>
        /// <returns></returns>
        public string ReplaceTag( string input, string value, string tagName )
        {
            var fieldInfo = fields.Find( field => field.Name.CompareTo( tagName ) == 0 );
            if ( fieldInfo != null )
                return input.Replace( value, "@" + fieldInfo.Name );
    
            return input;
        }
    
        /// <summary>
        /// Replace all the tags
        /// </summary>
        public void ReplaceTags()
        {
            string input = inputField.text;
            string output = input;
    
            MatchCollection matches = regex.Matches( input );
            for ( int i = 0 ; i < matches.Count ; i++ )
            {
                Match match = matches[i];
                string tagName = match.Value.Substring(1);
                var fieldInfo = fields.Find( field => field.Name.CompareTo( tagName ) == 0 );
                if ( fieldInfo != null )
                    output = output.Replace( matches[i].Value, fieldInfo.GetValue( this ).ToString() );
            }
    
            inputField.text = output;
            StartCoroutine( MoveTextEndDelayed() );
        }
    }
    

    OLD ANSWER

    这是我第一次独立使用Reflection,但以下解决方案似乎有效。

    // Don't forget to add `using System.Linq;` at the beginning of your file
    
    public float mscore = 5 ;
    public float hscore = 10 ;
    
    private System.Collections.Generic.List<System.Reflection.FieldInfo> fields ;
    private System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex( "@[a-zA-Z0-9]+" );
    
    
    private void Awake()
    {
        var bindingFlags = System.Reflection.BindingFlags.Instance |
            System.Reflection.BindingFlags.NonPublic |
            System.Reflection.BindingFlags.Public;
    
        fields = GetType().GetFields( bindingFlags )
                        .Where( fieldInfo => fieldInfo.FieldType == typeof( float ) ) // Use this if you want to retrieve only the floating variables
                        .ToList();
    
        Debug.Log( ReplaceInput( "my score is @mscore , his score is @hscore" ) );
        // Output "my score is 5 , his score is 10" 
    }
    
    public string ReplaceInput( string input )
    {
        string output = input;
        System.Text.RegularExpressions.MatchCollection matches = regex.Matches( input );
    
        for ( int i = 0 ; i < matches.Count ; i++ )
        {
            string fieldName = matches[i].Value.Substring(1);
            var fieldInfo = fields.Find( field => field.Name.CompareTo( fieldName ) == 0 );
            if ( fieldInfo != null )
                output = output.Replace( matches[i].Value, fieldInfo.GetValue( this ).ToString() );
        }
    
        return output;
    }
    
    // Use this function to retrieve the list of variables you can use when you start typing
    public System.Collections.Generic.List<string> GetVariables( string input )
    {
        return fields.FindAll( field => field.Name.StartsWith( input ) ).Select( field => field.Name ).ToList();
    }