啟動屏界面、主菜單界面、選關界面、游戲界面
卡牌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 () { } }