启动屏界面、主菜单界面、选关界面、游戏界面
卡牌01_启动屏界面 传送门
卡牌02_主菜单界面 传送门
卡牌03_选关界面 传送门
卡牌04_游戏界面 传送门
选关界面效果
(鼠标放在不同关卡上显示不同的关卡提示信息,点击关卡按钮时候出现短暂粉红色点击效果,点击返回主菜单游戏回到主菜单界面,点击游戏关卡进入游戏界面)
不同游戏主题显示不同数量的关卡,用到了游戏数据管理类,不同游戏主题显示的卡牌不同
using System.Collections; using System.Collections.Generic; using UnityEngine; public class DataMgr { private static DataMgr ins = null; public THEME_ID themeId; //某一主题所有关卡数据 public LevelData levelData; public int levelId; //进入游戏前,保存当前选择的关卡id public LevelInfo levelInfo; //当前关卡信息 private DataMgr() { //将构造函数设置为私有,这样避免外部创建类的实例,只能通过Instance()来获取数据管理类的实例 } public static DataMgr Instance() { if(ins == null) { ins = new DataMgr(); } return ins; } public LevelData InitLevelData(THEME_ID id) { levelData = null; switch (id) { case THEME_ID.Logo: levelData = Resources.Load<LevelData>("Prefabs/data/LevelDataLogo"); break; case THEME_ID.Student: levelData = Resources.Load<LevelData>("Prefabs/data/LevelDataStudent"); break; default: levelData = Resources.Load<LevelData>("Prefabs/data/LevelDataLogo"); break; } return levelData; } }
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; public enum THEME_ID { Logo, Student } public class Scene_MainMenu : MonoBehaviour { // Use this for initialization void Start () { GameObject.Find("LogoBtn").GetComponent<Button>().onClick.AddListener(()=>{ OnClickThemeBtn(THEME_ID.Logo); }); GameObject.Find("StudentBtn").GetComponent<Button>().onClick.AddListener(() => { OnClickThemeBtn(THEME_ID.Student); }); GameObject.Find("CloseBtn").GetComponent<Button>().onClick.AddListener(() => { OnCloseApp(); }); } // Update is called once per frame void Update () { } void OnClickThemeBtn(THEME_ID theme) { SceneManager.LoadScene("SelectLevel"); DataMgr.Instance().themeId = theme; } //退出程序 void OnCloseApp() { Application.Quit(); } }
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UnityEngine.EventSystems; using UnityEngine.SceneManagement; //选关界面,每一个关卡按钮单元 public class LevelItemCell : MonoBehaviour ,IPointerEnterHandler,IPointerExitHandler, IPointerDownHandler,IPointerUpHandler,IPointerClickHandler{ public RectTransform numTrans; public GameObject LockObj; public GameObject pressObj; //[HideInInspector] public int id; //每个单元对应的关卡id(从1开始) public LevelManager lvlMgr; LevelInfo levelInfo; //点击按钮,跳转到游戏界面 public void OnPointerClick(PointerEventData eventData) { DataMgr.Instance().levelId = id; DataMgr.Instance().levelInfo = levelInfo; SceneManager.LoadScene("Gameplay"); } public void OnPointerDown(PointerEventData eventData) { pressObj.SetActive(true); } //当鼠标进入本单元矩形区域,显示当前关卡描述 public void OnPointerEnter(PointerEventData eventData) { lvlMgr.SetLevelDesc(levelInfo.desc); } public void OnPointerExit(PointerEventData eventData) { lvlMgr.SetLevelDesc("关卡信息"); } public void OnPointerUp(PointerEventData eventData) { pressObj.SetActive(false); } private void Awake() { LockObj.SetActive(false); pressObj.SetActive(false); } // Use this for initialization void Start () { float scale = 2; //初始化关卡数字显示 if (id < 10) { //完全用代码动态创建一个Image对象,并作为num的子节点 GameObject obj = new GameObject("num1",typeof(Image)); RectTransform rtf = obj.GetComponent<RectTransform>(); rtf.SetParent(numTrans); //设置数字 Image img = obj.GetComponent<Image>(); img.sprite = lvlMgr.spr_nums[id]; img.SetNativeSize(); //图片原始尺寸 rtf.localScale = new Vector3(2,2,1); rtf.localPosition = Vector3.zero; } else if (id<100) { //十位数 GameObject obj = new GameObject("num1", typeof(Image)); RectTransform rtf = obj.GetComponent<RectTransform>(); rtf.SetParent(numTrans); //设置数字 Image img = obj.GetComponent<Image>(); img.sprite = lvlMgr.spr_nums[id/10]; img.SetNativeSize(); //图片原始尺寸 rtf.localScale = new Vector3(2, 2, 1); rtf.localPosition = new Vector3(-scale * rtf.rect.width/2-1,0,0); //个位数 GameObject obj2 = new GameObject("num2", typeof(Image)); RectTransform rtf2 = obj2.GetComponent<RectTransform>(); rtf2.SetParent(numTrans); //设置数字 Image img2 = obj2.GetComponent<Image>(); img2.sprite = lvlMgr.spr_nums[id % 10]; img2.SetNativeSize(); //图片原始尺寸 rtf2.localScale = new Vector3(2, 2, 1); rtf2.localPosition = new Vector3(scale * rtf2.rect.width / 2 + 1, 0, 0); } levelInfo = DataMgr.Instance().levelData.levels[id - 1]; } // Update is called once per frame void Update () { } }
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using DG.Tweening; using UnityEngine.SceneManagement; //用来管理所有关卡按钮 //根据我们关卡数据定义,判断一共多少个关卡按钮。LevelManager来创建LevelPanelCell表格单元,LevelPanelCell表格单元是LevelItemCell public class LevelManager : MonoBehaviour { int totalCount = 0; //临时测试,一共18关 readonly int ITEM_COUNT_PAGE = 15; //每一页显示15个关卡 readonly float PANEL_SPACE = 10f; readonly float MOVE_TIME = 0.5f; public RectTransform contenTrans; public Sprite[] spr_nums; float panelCellOffset; int pageCount; GameObject levelPanelCellPreb; GameObject levelItemCellPreb; Text levelDescTxt; float pointerDownTimeBak; float pointerDownX; int pageIdx; public void Awake() { levelPanelCellPreb = Resources.Load<GameObject>("Prefabs/SelectLevel/LevelPanelCell"); levelItemCellPreb = Resources.Load("Prefabs/SelectLevel/LevelItemCell") as GameObject; levelDescTxt = GameObject.Find("LevelDesc/text").GetComponent<Text>(); GameObject.Find("BackMainMenu").GetComponent<Button>().onClick.AddListener(()=> { OnBackMainMenuBtn(); }); DataMgr.Instance().InitLevelData(DataMgr.Instance().themeId); totalCount = DataMgr.Instance().levelData.levels.Length; //根据关卡数据表的个数,动态设置单元数量 } // Use this for initialization void Start() { //计算panel的偏移 panelCellOffset = contenTrans.rect.width + PANEL_SPACE; //计算出一共需要多少页 pageCount = Mathf.CeilToInt((float)totalCount / ITEM_COUNT_PAGE); //当前显示的第几页表格panel,从0开始 pageIdx = 0; for (int i = 0; i < pageCount; i++) { CreateLevelPanclCell(i); } } // Update is called once per frame void Update() { //按下时记录鼠标当前位置 if (Input.GetMouseButtonDown(0)) { pointerDownTimeBak = Time.time; pointerDownX = Input.mousePosition.x; } if (Input.GetMouseButtonUp(0)) { //模拟滑动事件,假定很短时间的滑动 if (Time.time - pointerDownTimeBak < 0.5f) { float offsetX = Input.mousePosition.x - pointerDownX; //向左滑动鼠标,并超过一定距离 if (offsetX < -200 && pageIdx < pageCount - 1) { //向左滑动鼠标,并超过一段距离 pageIdx++; //执行所有表格面板向左平滑滑动 //0.5秒对自身左边叠加量,向左移动一段距离 contenTrans.DOBlendableLocalMoveBy(new Vector3(-panelCellOffset, 0, 0), MOVE_TIME); } else if (offsetX > 200 && pageIdx > 0) { //向右滑动鼠标,并超过一段距离 pageIdx--; //执行所有表格面板向右平滑滑动 //0.5秒对自身左边叠加量,向右移动一段距离 contenTrans.DOBlendableLocalMoveBy(new Vector3(panelCellOffset, 0, 0), MOVE_TIME); } } } } //创建表格panel,从0开始编号 void CreateLevelPanclCell(int pageInx) { GameObject panelObj = Instantiate(levelPanelCellPreb, contenTrans); RectTransform panelTrans = panelObj.GetComponent<RectTransform>(); panelTrans.anchoredPosition = new Vector2(panelCellOffset * pageInx, 0); //确定本业 中具有的关卡元素个数 int startId = ITEM_COUNT_PAGE * pageInx; //本业需要显示按钮的个数 int count = totalCount - startId; if (count > ITEM_COUNT_PAGE) { count = ITEM_COUNT_PAGE; } //创建本页中所有关卡按钮 for (int i = 0; i < count; i++) { //创建每一个关卡的按钮单元 GameObject itemObj = Instantiate(levelItemCellPreb, panelTrans); //这一段cell相关调用,实在Start()之前执行的 LevelItemCell cell = itemObj.GetComponent<LevelItemCell>(); cell.id = startId + i + 1; //设置每个单元的关卡编号 cell.lvlMgr = this; itemObj.name = cell.id.ToString(); } } //设置关卡描述 public void SetLevelDesc(string content) { levelDescTxt.text = content; } void OnBackMainMenuBtn() { SceneManager.LoadScene("MainMenu"); } }
实现过程
选关游戏界面
新建画布,添加背景,设置标题,增加选关区域范围
选关区域使用纯白色作为背景(修改其透明度值),调整选关区域位置
选关区域下方添加关卡信息(Panel默认是透明)
LevelManager下方创建游戏空物体对象(Content),添加Panel,Panel上添加Grid Layout Group表格布局插件
Fixed Column Count 固定行
Constraint Count 每行固定最大值为5个单元表格
利用组格插件好处:更方便实现动态添加选项关卡
LevelItemCell游戏单个关卡(点击关卡时的颜色)
动态生成关卡为未解锁状态
点击关卡时状态
关卡解锁状态
添加Image覆盖LevelItemCell选关单元,调整透明度(改名lock,未解锁关卡时的颜色)
同点击鼠标让关卡变色一个原理
将LevelItemCell设置为预设体,使关卡能动态创建(业务与开发分离)
添加脚本LevelItemCell并挂到预设体LevelItemCell上(脚本与预设体同名看起来方便)
挂载完Apply更新,添加到源预设体上~
同理将LevelPanelCell也设置为预设体,动态创建一页关卡后会再动态创建关卡页
添加脚本LevelManager,挂载到LevelManager控件上
LevelManager用来管理所有关卡按钮
LevelManager脚本根据我们关卡数据定义,判断一共多少个关卡按钮。LevelManager来创建LevelPanelCell表格单元,LevelPanelCell表格单元是LevelItemCell
将Content关卡页面绑定到LevelManager关卡页面范围上
public RectTransform contenTrans;
计算panel的偏移
readonly float PANEL_SPACE = 10f; panelCellffset = contenTrans.rect.width + PANEL_SPACE;
计算出一共需要多少页
int totalCount = 18; //临时测试,一共18关 readonly int ITEM_COUNT_PAGE = 15; //每一页显示15个关卡 readonly float PANEL_SPACE = 10f; pageCount = Mathf.CeilToInt((float)totalCount / ITEM_COUNT_PAGE);
Mathf.CeilToInt()上取整(Mathf.CeilToInt(1.5)、Mathf.CeilToInt(2.2)=3)
获得游戏控件UI
public void Awake() { levelPanelCellPreb = Resources.Load<GameObject>("Prefabs/SelectLevel/LevelPanelCell"); levelItemCellPreb = Resources.Load("Prefabs/SelectLevel/LevelItemCell") as GameObject; levelDescTxt = GameObject.Find("LevelDesc/text").GetComponent<Text>(); }
创建表格panel,从0开始编号
void CreateLevelPanclCell(int pageInx) { GameObject panelObj = Instantiate(levelPanelCellPreb,contenTrans); RectTransform panelTrans = panelObj.GetComponent<RectTransform>(); panelTrans.anchoredPosition = new Vector2(panelCellOffset * pageInx, 0); //确定本业 中具有的关卡元素个数 int startId = ITEM_COUNT_PAGE * pageInx; //本业需要显示按钮的个数 int count = totalCount - startId; if (count > ITEM_COUNT_PAGE) { count = ITEM_COUNT_PAGE; } //创建本页中所有关卡按钮 for(int i =0;i<count;i++) { //创建每一个关卡的按钮单元 GameObject itemObj = Instantiate(levelItemCellPreb,panelTrans); LevelItemCell cell = itemObj.GetComponent<LevelItemCell>(); cell.id = startId+i+1; cell.lvlMgr = this; itemObj.name = cell.id.ToString(); } }
using System.Collections; using System.Collections.Generic; using UnityEngine; //选关界面,每一个关卡按钮单元 public class LevelItemCell : MonoBehaviour { public int id; //每个单元对应的关卡id(从1开始) public LevelManager lvlMgr; // Use this for initialization void Start () { } // Update is called once per frame void Update () { } }
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; //用来管理所有关卡按钮 //根据我们关卡数据定义,判断一共多少个关卡按钮。LevelManager来创建LevelPanelCell表格单元,LevelPanelCell表格单元是LevelItemCell public class LevelManager : MonoBehaviour { int totalCount = 18; //临时测试,一共18关 readonly int ITEM_COUNT_PAGE = 15; //每一页显示15个关卡 readonly float PANEL_SPACE = 10f; public RectTransform contenTrans; float panelCellOffset; int pageCount; GameObject levelPanelCellPreb; GameObject levelItemCellPreb; Text levelDescTxt; //int pageIdx; public void Awake() { levelPanelCellPreb = Resources.Load<GameObject>("Prefabs/SelectLevel/LevelPanelCell"); levelItemCellPreb = Resources.Load("Prefabs/SelectLevel/LevelItemCell") as GameObject; levelDescTxt = GameObject.Find("LevelDesc/text").GetComponent<Text>(); } // Use this for initialization void Start () { //计算panel的偏移 panelCellOffset = contenTrans.rect.width + PANEL_SPACE; //计算出一共需要多少页 pageCount = Mathf.CeilToInt((float)totalCount / ITEM_COUNT_PAGE); // pageIdx = 0; for (int i = 0; i < pageCount; i++) { CreateLevelPanclCell(i); } } // Update is called once per frame void Update () { } //创建表格panel,从0开始编号 void CreateLevelPanclCell(int pageInx) { GameObject panelObj = Instantiate(levelPanelCellPreb,contenTrans); RectTransform panelTrans = panelObj.GetComponent<RectTransform>(); panelTrans.anchoredPosition = new Vector2(panelCellOffset * pageInx, 0); //确定本业 中具有的关卡元素个数 int startId = ITEM_COUNT_PAGE * pageInx; //本业需要显示按钮的个数 int count = totalCount - startId; if (count > ITEM_COUNT_PAGE) { count = ITEM_COUNT_PAGE; } //创建本页中所有关卡按钮 for(int i =0;i<count;i++) { //创建每一个关卡的按钮单元 GameObject itemObj = Instantiate(levelItemCellPreb,panelTrans); LevelItemCell cell = itemObj.GetComponent<LevelItemCell>(); cell.id = startId+i+1; cell.lvlMgr = this; itemObj.name = cell.id.ToString(); } } //设置关卡描述 void SetLevelDesc(string content) { levelDescTxt.text = content; } }
因为我们默认初始化游戏18个关卡,一个选关界面存放15个关卡
所有关卡时出现出现两个选关界面
为了只出现一个选关界面
使用Unity提供的Mask插件
Mask插件:提供给需要Mask的图片修改渲染顶点,达到遮罩效果
在LevelManager控件上添加Mask插件
整体滑动效果
DOTween插件控制选关界面移动 下载:传送门
下载完后,把解压的包,直接拖入工程 在unity 菜单栏 Tools—Demigiant—DOTween Utility Panel。点击后,在右图中点击Setup DOTween… 工具会导入必要的库。
滑动效果效果:
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using DG.Tweening; //用来管理所有关卡按钮 //根据我们关卡数据定义,判断一共多少个关卡按钮。LevelManager来创建LevelPanelCell表格单元,LevelPanelCell表格单元是LevelItemCell public class LevelManager : MonoBehaviour { int totalCount = 18; //临时测试,一共18关 readonly int ITEM_COUNT_PAGE = 15; //每一页显示15个关卡 readonly float PANEL_SPACE = 10f; readonly float MOVE_TIME = 0.5f; public RectTransform contenTrans; float panelCellOffset; int pageCount; GameObject levelPanelCellPreb; GameObject levelItemCellPreb; Text levelDescTxt; float pointerDownTimeBak; float pointerDownX; int pageIdx; public void Awake() { levelPanelCellPreb = Resources.Load<GameObject>("Prefabs/SelectLevel/LevelPanelCell"); levelItemCellPreb = Resources.Load("Prefabs/SelectLevel/LevelItemCell") as GameObject; levelDescTxt = GameObject.Find("LevelDesc/text").GetComponent<Text>(); } // Use this for initialization void Start () { //计算panel的偏移 panelCellOffset = contenTrans.rect.width + PANEL_SPACE; //计算出一共需要多少页 pageCount = Mathf.CeilToInt((float)totalCount / ITEM_COUNT_PAGE); //当前显示的第几页表格panel,从0开始 pageIdx = 0; for (int i = 0; i < pageCount; i++) { CreateLevelPanclCell(i); } } // Update is called once per frame void Update () { //按下时记录鼠标当前位置 if (Input.GetMouseButtonDown(0)) { pointerDownTimeBak = Time.time; pointerDownX = Input.mousePosition.x; } if(Input.GetMouseButtonUp(0)) { //模拟滑动事件,假定很短时间的滑动 if(Time.time - pointerDownTimeBak<0.5f) { float offsetX = Input.mousePosition.x - pointerDownX; //向左滑动鼠标,并超过一定距离 if (offsetX < -200 && pageIdx<pageCount-1) { //向左滑动鼠标,并超过一段距离 pageIdx++; //执行所有表格面板向左平滑滑动 //0.5秒对自身左边叠加量,向左移动一段距离 contenTrans.DOBlendableLocalMoveBy(new Vector3(-panelCellOffset, 0, 0), MOVE_TIME); }else if (offsetX>200&&pageIdx>0) { //向右滑动鼠标,并超过一段距离 pageIdx--; //执行所有表格面板向右平滑滑动 //0.5秒对自身左边叠加量,向右移动一段距离 contenTrans.DOBlendableLocalMoveBy(new Vector3(panelCellOffset, 0, 0), MOVE_TIME); } } } } //创建表格panel,从0开始编号 void CreateLevelPanclCell(int pageInx) { GameObject panelObj = Instantiate(levelPanelCellPreb,contenTrans); RectTransform panelTrans = panelObj.GetComponent<RectTransform>(); panelTrans.anchoredPosition = new Vector2(panelCellOffset * pageInx, 0); //确定本业 中具有的关卡元素个数 int startId = ITEM_COUNT_PAGE * pageInx; //本业需要显示按钮的个数 int count = totalCount - startId; if (count > ITEM_COUNT_PAGE) { count = ITEM_COUNT_PAGE; } //创建本页中所有关卡按钮 for(int i =0;i<count;i++) { //创建每一个关卡的按钮单元 GameObject itemObj = Instantiate(levelItemCellPreb,panelTrans); LevelItemCell cell = itemObj.GetComponent<LevelItemCell>(); cell.id = startId+i+1; cell.lvlMgr = this; itemObj.name = cell.id.ToString(); } } //设置关卡描述 void SetLevelDesc(string content) { levelDescTxt.text = content; } }
MOVE_TIME时间内选择关卡向左边的叠加量,向左移动一段距离
contenTrans.DOBlendableLocalMoveBy(new Vector3(-panelCellOffset, 0, 0), MOVE_TIME);
按下时记录鼠标当前位置
if (Input.GetMouseButtonDown(0)) { pointerDownTimeBak = Time.time; pointerDownX = Input.mousePosition.x; }
松开鼠标时触发事件
if(Input.GetMouseButtonUp(0)) { //模拟滑动事件,假定很短时间的滑动 if(Time.time - pointerDownTimeBak<0.5f) { float offsetX = Input.mousePosition.x - pointerDownX; //向左滑动鼠标,并超过一定距离 if (offsetX < -200 && pageIdx<pageCount-1) { //向左滑动鼠标,并超过一段距离 pageIdx++; //执行所有表格面板向左平滑滑动 //0.5秒对自身左边叠加量,向左移动一段距离 contenTrans.DOBlendableLocalMoveBy(new Vector3(-panelCellOffset, 0, 0), MOVE_TIME); }else if (offsetX>200&&pageIdx>0) { //向右滑动鼠标,并超过一段距离 pageIdx--; //执行所有表格面板向右平滑滑动 //0.5秒对自身左边叠加量,向右移动一段距离 contenTrans.DOBlendableLocalMoveBy(new Vector3(panelCellOffset, 0, 0), MOVE_TIME); } } }
代码创建关卡数字
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; //选关界面,每一个关卡按钮单元 public class LevelItemCell : MonoBehaviour { public RectTransform numTrans; public int id; //每个单元对应的关卡id(从1开始) public LevelManager lvlMgr; private void Awake() { } // Use this for initialization void Start () { float scale = 2; //初始化关卡数字显示 if (id < 10) { //完全用代码动态创建一个Image对象,并作为num的子节点 GameObject obj = new GameObject("num1",typeof(Image)); RectTransform rtf = obj.GetComponent<RectTransform>(); rtf.SetParent(numTrans); //设置数字 Image img = obj.GetComponent<Image>(); img.sprite = lvlMgr.spr_nums[id]; img.SetNativeSize(); //图片原始尺寸 rtf.localScale = new Vector3(2,2,1); rtf.localPosition = Vector3.zero; } else if (id<100) { //十位数 GameObject obj = new GameObject("num1", typeof(Image)); RectTransform rtf = obj.GetComponent<RectTransform>(); rtf.SetParent(numTrans); //设置数字 Image img = obj.GetComponent<Image>(); img.sprite = lvlMgr.spr_nums[id/10]; img.SetNativeSize(); //图片原始尺寸 rtf.localScale = new Vector3(2, 2, 1); rtf.localPosition = new Vector3(-scale * rtf.rect.width/2-1,0,0); //个位数 GameObject obj2 = new GameObject("num2", typeof(Image)); RectTransform rtf2 = obj2.GetComponent<RectTransform>(); rtf2.SetParent(numTrans); //设置数字 Image img2 = obj2.GetComponent<Image>(); img2.sprite = lvlMgr.spr_nums[id % 10]; img2.SetNativeSize(); //图片原始尺寸 rtf2.localScale = new Vector3(2, 2, 1); rtf2.localPosition = new Vector3(scale * rtf2.rect.width / 2 + 1, 0, 0); } } // Update is called once per frame void Update () { } }
num子节点下创建两个Image控件存放数字
定义Sprite[]数组,将图片绑定上去
public Sprite[] spr_nums;
用代码动态创建一个Image对象,并作为num的子节点
GameObject obj = new GameObject("num1",typeof(Image)); RectTransform rtf = obj.GetComponent<RectTransform>(); rtf.SetParent(numTrans);
图片原始尺寸
img.SetNativeSize();
图片的缩放比例
rtf.localScale = new Vector3(2,2,1);
当id<10时,定义图片放置的位置
rtf.localPosition = Vector3.zero;
if (id < 10) { //完全用代码动态创建一个Image对象,并作为num的子节点 GameObject obj = new GameObject("num1",typeof(Image)); RectTransform rtf = obj.GetComponent<RectTransform>(); rtf.SetParent(numTrans); //设置数字 Image img = obj.GetComponent<Image>(); img.sprite = lvlMgr.spr_nums[id]; img.SetNativeSize(); //图片原始尺寸 rtf.localScale = new Vector3(2,2,1); rtf.localPosition = Vector3.zero; }
个位数位置
img.SetNativeSize(); //图片原始尺寸 rtf.localScale = new Vector3(2, 2, 1); rtf.localPosition = new Vector3(-scale * rtf.rect.width/2-1,0,0);
十位数位置
img2.SetNativeSize(); //图片原始尺寸 rtf2.localScale = new Vector3(2, 2, 1); rtf2.localPosition = new Vector3(scale * rtf2.rect.width / 2 + 1, 0, 0);
同理个位数,不同在于图片摆放的位置
else if (id<100) { //十位数 GameObject obj = new GameObject("num1", typeof(Image)); RectTransform rtf = obj.GetComponent<RectTransform>(); rtf.SetParent(numTrans); //设置数字 Image img = obj.GetComponent<Image>(); img.sprite = lvlMgr.spr_nums[id/10]; img.SetNativeSize(); //图片原始尺寸 rtf.localScale = new Vector3(2, 2, 1); rtf.localPosition = new Vector3(-scale * rtf.rect.width/2-1,0,0); //个位数 GameObject obj2 = new GameObject("num2", typeof(Image)); RectTransform rtf2 = obj2.GetComponent<RectTransform>(); rtf2.SetParent(numTrans); //设置数字 Image img2 = obj2.GetComponent<Image>(); img2.sprite = lvlMgr.spr_nums[id % 10]; img2.SetNativeSize(); //图片原始尺寸 rtf2.localScale = new Vector3(2, 2, 1); rtf2.localPosition = new Vector3(scale * rtf2.rect.width / 2 + 1, 0, 0); }
数据管理类
unity除非特别指定,当切换到新场景时原场景中所有游戏对象都会销毁。那么伴随着挂在对象上的脚本也会销毁。
我们需要有一个类,能够使各处都能够便利访问。并且这个类对象实例,只需要一个
第一个游戏主题只有18关
第一个游戏主题有20关
( Unity引擎加载场景有点慢(´・_・`) )
某一主题所有关卡数据
public LevelData levelData;
点击不同主题按钮选择不同主题的关卡
void OnClickThemeBtn(THEME_ID theme) { SceneManager.LoadScene("SelectLevel"); DataMgr.Instance().themeId = theme; }
public LevelData InitLevelData(THEME_ID id) { levelData = null; switch (id) { case THEME_ID.Logo: levelData = Resources.Load<LevelData>("Prefabs/data/LevelDataLogo"); break; case THEME_ID.Student: levelData = Resources.Load<LevelData>("Prefabs/data/LevelDataStudent"); break; default: levelData = Resources.Load<LevelData>("Prefabs/data/LevelDataLogo"); break; } return levelData; }
关卡单元实现
添加两个游戏主键的引用
public GameObject LockObj; public GameObject pressObj;
点击按钮时关卡单元变色Image和锁的Image添加上去
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UnityEngine.EventSystems; using UnityEngine.SceneManagement; //选关界面,每一个关卡按钮单元 public class LevelItemCell : MonoBehaviour ,IPointerEnterHandler,IPointerExitHandler, IPointerDownHandler,IPointerUpHandler,IPointerClickHandler{ public RectTransform numTrans; public GameObject LockObj; public GameObject pressObj; //[HideInInspector] public int id; //每个单元对应的关卡id(从1开始) public LevelManager lvlMgr; LevelInfo levelInfo; //点击按钮,跳转到游戏界面 public void OnPointerClick(PointerEventData eventData) { DataMgr.Instance().levelId = id; DataMgr.Instance().levelInfo = levelInfo; SceneManager.LoadScene("Gameplay"); } public void OnPointerDown(PointerEventData eventData) { pressObj.SetActive(true); } //当鼠标进入本单元矩形区域,显示当前关卡描述 public void OnPointerEnter(PointerEventData eventData) { lvlMgr.SetLevelDesc(levelInfo.desc); } public void OnPointerExit(PointerEventData eventData) { lvlMgr.SetLevelDesc("关卡信息"); } public void OnPointerUp(PointerEventData eventData) { pressObj.SetActive(false); } private void Awake() { LockObj.SetActive(false); pressObj.SetActive(false); } // Use this for initialization void Start () { float scale = 2; //初始化关卡数字显示 if (id < 10) { //完全用代码动态创建一个Image对象,并作为num的子节点 GameObject obj = new GameObject("num1",typeof(Image)); RectTransform rtf = obj.GetComponent<RectTransform>(); rtf.SetParent(numTrans); //设置数字 Image img = obj.GetComponent<Image>(); img.sprite = lvlMgr.spr_nums[id]; img.SetNativeSize(); //图片原始尺寸 rtf.localScale = new Vector3(2,2,1); rtf.localPosition = Vector3.zero; } else if (id<100) { //十位数 GameObject obj = new GameObject("num1", typeof(Image)); RectTransform rtf = obj.GetComponent<RectTransform>(); rtf.SetParent(numTrans); //设置数字 Image img = obj.GetComponent<Image>(); img.sprite = lvlMgr.spr_nums[id/10]; img.SetNativeSize(); //图片原始尺寸 rtf.localScale = new Vector3(2, 2, 1); rtf.localPosition = new Vector3(-scale * rtf.rect.width/2-1,0,0); //个位数 GameObject obj2 = new GameObject("num2", typeof(Image)); RectTransform rtf2 = obj2.GetComponent<RectTransform>(); rtf2.SetParent(numTrans); //设置数字 Image img2 = obj2.GetComponent<Image>(); img2.sprite = lvlMgr.spr_nums[id % 10]; img2.SetNativeSize(); //图片原始尺寸 rtf2.localScale = new Vector3(2, 2, 1); rtf2.localPosition = new Vector3(scale * rtf2.rect.width / 2 + 1, 0, 0); } levelInfo = DataMgr.Instance().levelData.levels[id - 1]; } // Update is called once per frame void Update () { } }
初始化时点击单元关卡(粉红色效果)和锁(效果)不可见
private void Awake() { LockObj.SetActive(false); pressObj.SetActive(false); }
点击按钮事件
//点击按钮,跳转到游戏界面 public void OnPointerClick(PointerEventData eventData) { DataMgr.Instance().levelId = id; DataMgr.Instance().levelInfo = levelInfo; SceneManager.LoadScene("Gameplay"); } public void OnPointerDown(PointerEventData eventData) { pressObj.SetActive(true); } //当鼠标进入本单元矩形区域,显示当前关卡描述 public void OnPointerEnter(PointerEventData eventData) { lvlMgr.SetLevelDesc(levelInfo.desc); } public void OnPointerExit(PointerEventData eventData) { lvlMgr.SetLevelDesc("关卡信息"); } public void OnPointerUp(PointerEventData eventData) { pressObj.SetActive(false); }
public class LevelItemCell : MonoBehaviour ,IPointerEnterHandler,IPointerExitHandler, IPointerDownHandler,IPointerUpHandler,IPointerClickHandler{ public RectTransform numTrans; public GameObject LockObj; public GameObject pressObj; //[HideInInspector] public int id; //每个单元对应的关卡id(从1开始) public LevelManager lvlMgr; LevelInfo levelInfo; //点击按钮,跳转到游戏界面 public void OnPointerClick(PointerEventData eventData) { DataMgr.Instance().levelId = id; DataMgr.Instance().levelInfo = levelInfo; SceneManager.LoadScene("Gameplay"); } public void OnPointerDown(PointerEventData eventData) { pressObj.SetActive(true); } //当鼠标进入本单元矩形区域,显示当前关卡描述 public void OnPointerEnter(PointerEventData eventData) { lvlMgr.SetLevelDesc(levelInfo.desc); } public void OnPointerExit(PointerEventData eventData) { lvlMgr.SetLevelDesc("关卡信息"); } public void OnPointerUp(PointerEventData eventData) { pressObj.SetActive(false); } private void Awake() { LockObj.SetActive(false); pressObj.SetActive(false); } // Use this for initialization void Start () { float scale = 2; //初始化关卡数字显示 if (id < 10) { //完全用代码动态创建一个Image对象,并作为num的子节点 GameObject obj = new GameObject("num1",typeof(Image)); RectTransform rtf = obj.GetComponent<RectTransform>(); rtf.SetParent(numTrans); //设置数字 Image img = obj.GetComponent<Image>(); img.sprite = lvlMgr.spr_nums[id]; img.SetNativeSize(); //图片原始尺寸 rtf.localScale = new Vector3(2,2,1); rtf.localPosition = Vector3.zero; } else if (id<100) { //十位数 GameObject obj = new GameObject("num1", typeof(Image)); RectTransform rtf = obj.GetComponent<RectTransform>(); rtf.SetParent(numTrans); //设置数字 Image img = obj.GetComponent<Image>(); img.sprite = lvlMgr.spr_nums[id/10]; img.SetNativeSize(); //图片原始尺寸 rtf.localScale = new Vector3(2, 2, 1); rtf.localPosition = new Vector3(-scale * rtf.rect.width/2-1,0,0); //个位数 GameObject obj2 = new GameObject("num2", typeof(Image)); RectTransform rtf2 = obj2.GetComponent<RectTransform>(); rtf2.SetParent(numTrans); //设置数字 Image img2 = obj2.GetComponent<Image>(); img2.sprite = lvlMgr.spr_nums[id % 10]; img2.SetNativeSize(); //图片原始尺寸 rtf2.localScale = new Vector3(2, 2, 1); rtf2.localPosition = new Vector3(scale * rtf2.rect.width / 2 + 1, 0, 0); } levelInfo = DataMgr.Instance().levelData.levels[id - 1]; } // Update is called once per frame void Update () { } }