我的问题是:当我输入“@”时,它会调用一个下拉列表,所以我可以从下拉列表中选择一个变量,我可以在InputFiled上输入如下:我的分数是@mscore,他得分是@hscore 。最后我按了一个按钮(也许叫“结账”),它会显示mscore和hscore的值,就像这样:我的分数是10,他得分是8。我怎么能完成这个功能?
答案 0 :(得分:1)
这是一个完整的脚本。
tagsParent
字段中。 (我已经附加到InputField并且附加了VerticalLayoutGroup
,这是非常的)Text
组件和Button
组件创建预制件(我使用了您可以在GameObject
> UI
菜单中创建的标准Unity按钮)< / LI>
tagPrefab
字段ReplaceTags
功能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() );
}
}
这是我第一次独立使用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();
}