学习Unity脚本推荐:Unity3D官网索引
上一章已经可以实现最高分的本地存储,接下来的任务就是插入最高分并且实现排行榜其余分数的依次下调。
在代码中的修改十分简单,使用for循环依次调整即可:
function AddNewHighscore() { var curRounds = PlayerPrefs.GetInt("highscoreCurrentRounds"); var curKills = PlayerPrefs.GetInt("highscoreCurrentKills"); var newHighscorePosition: int; // check if the current score are good / above the highscores in the playersPrefs // are we assuming the local and playerprefs data is the same? - Yes for( var i:int = 0 ; i < numberHighscores ; i++ ) { // for the number of highscores if (curRounds > score[i].rounds) { // new score is higher! newHighscorePosition = i; break; } else if (curRounds == score[i].rounds && curKills > score[i].kills) { // new score is equal in rounds and kills are greater newHighscorePosition = i; break; } // if the rounds are equal and kills are less } // if the rounds are less Debug.Log (newHighscorePosition); //if it is calculate what the # of the new houigschore would be // 1-8 // new highscore 4 // 1,2,3,4,5,6,7,8 // 1,2,3,4,4,5,6,7,8 // 1,2,3,4,5,6,7,8 // 4 -> 5 // ? 5 -> 6 // 8 -> 9 // 7 -> 8 // 6 -> 7 if (newHighscorePosition < numberHighscores) { for(i = numberHighscores - 1 ; i >= newHighscorePosition ; i-- ) { // for the number of highscores //8 if (i == newHighscorePosition) { // highscore enter code PlayerPrefs.SetString("highscore" + i + "name" , score[i].name); // ask the player for name score[i].name = score[i].name; PlayerPrefs.SetInt("highscore" + i + "rounds" , curRounds); score[i].rounds = curRounds; PlayerPrefs.SetInt("highscore" + i + "kills" , curKills); score[i].kills = curKills; } else { PlayerPrefs.SetString("highscore" + i + "name" , score[i-1].name); score[i].name = score[i-1].name; PlayerPrefs.SetInt("highscore" + i + "rounds" , score[i-1].rounds); score[i].rounds = score[i-1].rounds; PlayerPrefs.SetInt("highscore" + i + "kills" , score[i-1].kills); score[i].kills = score[i-1].kills; } } } // add it into our data and save it. }
这里要用到GUI中的TextField,和xcode中的TextField十分类似。
我们可以在官网查找TextField的相关数据:Unity3D官网索引
官方给出的重载函数如下:
static function TextField (position : Rect, text : String) : String static function TextField (position : Rect, text : String, maxLength : int) : String static function TextField (position : Rect, text : String, style : GUIStyle) : String static function TextField (position : Rect, text : String, maxLength : int, style : GUIStyle) : String脚本案例
var stringToEdit : String = "Hello World"; function OnGUI () { // Make a text field that modifies stringToEdit. stringToEdit = GUI.TextField (Rect (10, 10, 200, 20), stringToEdit, 25); }我们可以在脚本中添加一下代码:
可以发现游戏运行后多了一个可以输入的文本框:
接下来要做的就是在TextField和排行榜的数据之间建立连接,使得输入框中的数据可以显示在排行榜上面。
在代码中添加两行:
这个时候再运行游戏就会发现显示发生了变化:
下面便是如何隐藏掉这个难看的输入框。
这里要介绍一个新的概念FocusControl:官网解释
简单来说的就是移动键盘焦点的一个方法。
官网给的简单案例如下:
// When pressed the button, selects the "username" Textfield. var username : String = "username"; var pwd : String = "a pwd"; function OnGUI () { // Set the internal name of the textfield GUI.SetNextControlName ("MyTextField"); // Make the actual text field. username = GUI.TextField (Rect (10,10,100,20), username); pwd = GUI.TextField (Rect (10,40,100,20), pwd); // If the user presses this button, keyboard focus will move. if (GUI.Button (Rect (10,70,80,20), "Move Focus")) GUI.FocusControl ("MyTextField"); }
再次运行项目便会发现文本输入框已经有了高亮显示,表示获取到了焦点。
也就是,现在不需要任何点击就可以直接输入了:
接下来的任务便是实现文本输入框的动态显示。
对代码做如下修改实现文本框的隐藏:
此时再次运行就会发现,输入框已经没有了,但是依旧可以输入你的姓名:
完整的脚本如下:
// this is called after a player dies OR from the main menu // Display the highscore // track the follow: Player Name, highscore number of the rounds survived and kills //Upon entering the High Score menu, test if we have a high score and if we do, ask the // player to enter a name and add it to the High Score save data. /* class Highscore { // highscore class to hold information specific to one highscore var name:String; // player name entered at time of highscore var rounds:int; // number of rounds won in this highscore var kills:int; // number of kills in this highscore }*/ var boxStartLocation:Vector2; // offset of main GUI element var center = Location(); // handy class for calculating the center of the screen function Start() { Debug.Log("The value of key 'highscoreCurrentRounds' is: " + PlayerPrefs.GetInt("highscoreCurrentRounds")); Debug.Log("The value of key 'highscoreCurrentKills' is: " + PlayerPrefs.GetInt("highscoreCurrentKills")); AddNewHighscore(); } function Update() { center.updateLocation(); // every frame, check if the screen has changed and re-calculate the screen center value. //SyncPlayerPrefs(); //Start(); } // draw a text string to the screen var textGUIStyle : GUIStyle; // to control the display of text var roundsGUIStyle : GUIStyle; // to control the display of text for kills var score = new Highscore[10]; // array of names for the highscore score[0].name = "www.DigitalTutors.com"; // Highscore #1 score[1].name = "Papa"; score[2].name = "Kyle"; score[3].name = "Tanya"; score[4].name = "Delano"; score[5].name = "Justin"; score[6].name = "Eddie"; score[7].name = "Josh"; score[8].name = "Chris"; score[9].name = "Steve"; score[0].rounds = 99; score[0].kills = 999; score[1].rounds = 1; score[1].kills = 9; var heightOffset: float = 10; // how much space to place between each highscore level var roundsOffset:float; // horizontal offset for rounds column var killsOffset:float; // horizontal offset for kills column var numberHighscores:int = 8; // controls how many loops to run to display var newName:String = "-type your name-"; function OnGUI() { GUI.SetNextControlName ("NameTextField"); newName = GUI.TextField(Rect(-100,-100,1,1),newName,30); GUI.FocusControl ("NameTextField"); PlayerPrefs.SetString("highscore" + newHighscorePosition + "name" , newName); // ask the player for name score[newHighscorePosition].name = newName; for( var i:int = 0 ; i < numberHighscores ; i++ ) { // for the number of highscores to display GUI.Box(Rect(center.offset.x + boxStartLocation.x, // draw a box with the name center.offset.y + boxStartLocation.y + i * heightOffset, 222,34),score[i].name,textGUIStyle); // using textGUIStyle GUI.Box(Rect(center.offset.x + boxStartLocation.x + roundsOffset, // draw a box with the rounds center.offset.y + boxStartLocation.y + i * heightOffset, 222,34),score[i].rounds.ToString(),roundsGUIStyle); // using roundsGUIStyle GUI.Box(Rect(center.offset.x + boxStartLocation.x + killsOffset, // draw a box with the kills center.offset.y + boxStartLocation.y + i * heightOffset, 222,34),score[i].kills.ToString(),roundsGUIStyle); // using roundsGUIStyle } } // Highscore naming scheme // key starts : "highscore" // past that, whatever the setting needs to be // a specific high score would look like this: // highscore4name var newHighscorePosition: int; function AddNewHighscore() { var curRounds = PlayerPrefs.GetInt("highscoreCurrentRounds"); var curKills = PlayerPrefs.GetInt("highscoreCurrentKills"); // check if the current score are good / above the highscores in the playersPrefs // are we assuming the local and playerprefs data is the same? - Yes for( var i:int = 0 ; i < numberHighscores ; i++ ) { // for the number of highscores if (curRounds > score[i].rounds) { // new score is higher! newHighscorePosition = i; break; } else if (curRounds == score[i].rounds && curKills > score[i].kills) { // new score is equal in rounds and kills are greater newHighscorePosition = i; break; } // if the rounds are equal and kills are less } // if the rounds are less Debug.Log (newHighscorePosition); //if it is calculate what the # of the new houigschore would be // 1-8 // new highscore 4 // 1,2,3,4,5,6,7,8 // 1,2,3,4,4,5,6,7,8 // 1,2,3,4,5,6,7,8 // 4 -> 5 // ? 5 -> 6 // 8 -> 9 // 7 -> 8 // 6 -> 7 if (newHighscorePosition < numberHighscores) { for(i = numberHighscores - 1 ; i >= newHighscorePosition ; i-- ) { // for the number of highscores //8 if (i == newHighscorePosition) { // highscore enter code PlayerPrefs.SetString("highscore" + i + "name" , score[i].name); // ask the player for name score[i].name = score[i].name; PlayerPrefs.SetInt("highscore" + i + "rounds" , curRounds); score[i].rounds = curRounds; PlayerPrefs.SetInt("highscore" + i + "kills" , curKills); score[i].kills = curKills; } else { PlayerPrefs.SetString("highscore" + i + "name" , score[i-1].name); score[i].name = score[i-1].name; PlayerPrefs.SetInt("highscore" + i + "rounds" , score[i-1].rounds); score[i].rounds = score[i-1].rounds; PlayerPrefs.SetInt("highscore" + i + "kills" , score[i-1].kills); score[i].kills = score[i-1].kills; } } } // add it into our data and save it. } function SyncPlayerPrefs() { // our assumption is that the data in player prefs should over-ride the local data // need this to see if we have player prefs keys and if we do, copy into our local // if the key does not exist, we need to populate it with the local data for( var i:int = 0 ; i < numberHighscores ; i++ ) { // for the number of highscores if (PlayerPrefs.HasKey("highscore" + i + "name" )) { //copy Player preferences value to local highscore class array score[i].name = PlayerPrefs.GetString("highscore" + i + "name"); } else { //set that player prefs to local data PlayerPrefs.SetString("highscore" + i + "name" , score[i].name); } if (PlayerPrefs.HasKey("highscore" + i + "rounds" )) { //copy Player preferences value to local highscore class array score[i].rounds = PlayerPrefs.GetInt("highscore" + i + "rounds"); } else { //set that player prefs to local data PlayerPrefs.SetInt("highscore" + i + "rounds" , score[i].rounds); } if (PlayerPrefs.HasKey("highscore" + i + "kills" )) { //copy Player preferences value to local highscore class array score[i].kills = PlayerPrefs.GetInt("highscore" + i + "kills"); } else { //set that player prefs to local data PlayerPrefs.SetInt("highscore" + i + "kills" , score[i].kills); } } }