下图是一个游戏的关卡界面,在设计关卡时,当前面一关通关后使后一关的关卡解锁该如何设计呢,本章内容将一解锁六个关卡为例
一、理论知识
1、在unity中,如何实现某些按钮可以互动,而其他按钮无法互动呢,这个关键在于button组件上面有一个叫Interactable的布尔值,只要我们把它取消勾选,那么这些按钮就无法互动了,所以在解锁按钮了之后,我们要把这些按钮上的Interactable设成true,没有解锁的关卡设置为false,那么这些按钮就不能产生互动了。
一般来说,我们使用for循环,先把所有的按钮都设置成不可互动的按钮,代码如下
for(int i=0;i<buttons.length;i++){
buttons[i].interactable=false; //buttons是用来存储关卡按钮的数组
}
然后再把已经解锁了的关卡设置成可交互的按钮
for(int i=0;i<unlockLevel;i++){
buttons[i].interactable=true; //unlockLevel是已经解锁的关卡数
}
关卡解锁后更新
if(currentLevelIndex>unlockLevel){
unlockLevel=currentLevelIndex;
PlayerPrefs.SetInt("unlockLevel",unlockLevel);
}
2、本地数据存储,在unity中,本地数据存储可以用PlayerPrefs,存储数据类型有以下几类
public static void SetInt (string key, int value);
// 设置由 key 键确定的整数值
public static void SetFloat (string key, float value);
// 设置由 key 键确定的浮点数值
public static void SetString (string key, string value);
// 设置由 key 键确定的字符串值
public static int GetInt (string key);
public static int GetInt (string key, int defaultValue);
// 获取存储文件中 key 键对应的整数值(不存在则返回 defaultValue)
public static float GetFloat (string key);
public static float GetFloat (string key, float defaultValue);
// 获取存储文件中 key 键对应的浮点数值(不存在则返回 defaultValue)
public static string GetString (string key);
public static string GetString (string key, string defaultValue);
// 获取存储文件中 key 键对应的字符串值(不存在则返回 defaultValue)
public static void Save ();
// 将所有修改的内容写入硬盘(默认情况下,Unity 会在 OnApplicationQuit() 执行过程中自动写入)
public static bool HasKey (string key);
// 判断 key 键是否存在(存在则返回 true)
public static void DeleteKey (string key);
// 删除 key 键以及其对应的值
public static void DeleteAll ();
// 删除所有存储内容(需谨慎使用)
二、实例
1、创建一个空物体,命名为buttonPanel,在此项目下创建六个按钮,分别命名为1-6,创建一个空物体buttonscript,用来存放按钮响应代码,创建六个场景,命名为1-6,用来实现场景跳转, 在六个场景中分别创建一个按钮返回关卡选择界面,为了美观可以自己添加一些内容,本篇文章是在资源商店中下载了UI button,使用了美观一点的panel,并把按钮设置为透明,然后拖拽到与panel相同的位置,这样可以在点击panel的时候响应按钮,然后给按钮贴上了关卡数(这个可以不贴,在代码中会有贴关卡数的操作,但是比较丑,自己贴的会美观一点,为了美观的内容可自行设定)
整体的布局如下( 没有实现美观的小伙伴可以把1-6当做是六个按钮)
2、点击File->build,把需要的场景拖进去,并记住后面的序号,场景跳转的时候需要用到,我这里有一些场景是不需要的,大家按照自己的场景适当变通就好,我这里的总关卡场景是quick,对应序号3,下面的1-6是六个关卡场景,对应序号4-9
3、创建六个脚本用来实现六个场景的跳转,新建六个C#脚本,分别命名为Select1-Select6
六个脚本的代码如下:(这里的4是我的第一关的场景序号,下面几关的一次往后就好)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Select1 : MonoBehaviour
{
public void OnLoginButtonClick()
{
SceneManager.LoadScene(4);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Select2 : MonoBehaviour
{
public void OnLoginButtonClick()
{
SceneManager.LoadScene(5);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Select3 : MonoBehaviour
{
public void OnLoginButtonClick()
{
SceneManager.LoadScene(6);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Select4 : MonoBehaviour
{
public void OnLoginButtonClick()
{
SceneManager.LoadScene(7);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Select5 : MonoBehaviour
{
public void OnLoginButtonClick()
{
SceneManager.LoadScene(8);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Select6 : MonoBehaviour
{
public void OnLoginButtonClick()
{
SceneManager.LoadScene(9);
}
}
4、把六个代码赋给buttonscript
5、场景跳转,这里以第一关跳转为例,其余几关的方法相同,选中第一个button,即命名为1的按钮,在右侧Inspector界面中往下滑,看到一个 on click的地方,选择+号,把buttonscript拖到右侧,在左边选择Select1,如下图,其余几个按钮跳转关卡也相同
6、关卡解锁代码,新建C# 命名为LevelSelectManager,相关代码注释如下,把这个代码赋给buttonpanel,然后把buttonpanel赋给levelSelectPanel,这里要注意的是,由于解锁的关卡数使用的是客户端数据存储,所以当运行程序后,即使关闭程序,或者关闭unity,数据都已经发生了改变(如果所有关卡都已经通关,重新运行游戏时关卡仍然是通关状态,要想回到初始状态,则要使用PlayerPrefs.SetInt("unlockedLevelIndex", 0);把数据归零,运行程序后关闭,然后把这行代码注释掉,重新运行程序即可)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class LevelSelectManager : MonoBehaviour
{
public GameObject levelSelectPanel;
Button[] levelSelectButtons;
int unlockedLevelIndex ;
// Start is called before the first frame update
void Start()
{
// PlayerPrefs.SetInt("unlockedLevelIndex", 0);
unlockedLevelIndex = PlayerPrefs.GetInt("unlockedLevelIndex"); //获取解锁过得关卡
levelSelectButtons = new Button[levelSelectPanel.transform.childCount];//关卡数组初始化
for(int i = 0; i < levelSelectPanel.transform.childCount; i++)//获取所有的button组件
{
//给每个关卡贴上关卡数
levelSelectPanel.transform.GetChild(i).GetChild(0).GetComponent<Text>().text = (i + 1).ToString();
levelSelectButtons[i]= levelSelectPanel.transform.GetChild(i).GetComponent<Button>();
}
//将所有button组件的iteractable值设置成false
foreach(var levelSelectButton in levelSelectButtons)
{
levelSelectButton.interactable = false;
//添加事件
levelSelectButton.onClick.AddListener(delegate ()
{
//获取点击按钮上的数字,这个数字就是第几关
Text text = levelSelectButton.gameObject.GetComponentInChildren<Text>();
//保存第几关
PlayerPrefs.SetInt("levelNum", int.Parse(text.text));
});
}
//解锁后关卡的interactable设置成true
for(int i = 0; i < unlockedLevelIndex +1; i++)
{
levelSelectButtons[i].interactable = true;
}
CheckLevelNum();
}
// Update is called once per frame
void CheckLevelNum()
{
int unlock = PlayerPrefs.GetInt("unlockedLevelIndex");
int levelNum = PlayerPrefs.GetInt("levelNum");
//通关条件
if (levelNum > unlock && levelNum<6)
{
PlayerPrefs.SetInt("unlockedLevelIndex", unlock + 1);
}
}
}