学习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");
}
在OnGUI函数中作如下修改:
再次运行项目便会发现文本输入框已经有了高亮显示,表示获取到了焦点。
也就是,现在不需要任何点击就可以直接输入了:
接下来的任务便是实现文本输入框的动态显示。
对代码做如下修改实现文本框的隐藏:
此时再次运行就会发现,输入框已经没有了,但是依旧可以输入你的姓名:
完整的脚本如下:
// 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);
}
}
}