启动屏界面、主菜单界面、选关界面、游戏界面

卡牌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;
}
}

DataMgr.class (数据管理类)

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();
} }

Scene_MainMenu.cs (关卡场景脚本)

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 = ;
//初始化关卡数字显示
if (id < )
{
//完全用代码动态创建一个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(,,);
rtf.localPosition = Vector3.zero; }
else if (id<)
{
//十位数
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(, , );
rtf.localPosition = new Vector3(-scale * rtf.rect.width/-,,); //个位数
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 % ];
img2.SetNativeSize(); //图片原始尺寸
rtf2.localScale = new Vector3(, , );
rtf2.localPosition = new Vector3(scale * rtf2.rect.width / + , , );
}
levelInfo = DataMgr.Instance().levelData.levels[id - ];
} // Update is called once per frame
void Update () { }
}

LevelItemCell.cs (每一个关卡按钮单元脚本)

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 = ; //临时测试,一共18关
readonly int ITEM_COUNT_PAGE = ; //每一页显示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 = ; for (int i = ; i < pageCount; i++)
{
CreateLevelPanclCell(i);
}
} // Update is called once per frame
void Update()
{
//按下时记录鼠标当前位置
if (Input.GetMouseButtonDown())
{
pointerDownTimeBak = Time.time;
pointerDownX = Input.mousePosition.x;
} if (Input.GetMouseButtonUp())
{
//模拟滑动事件,假定很短时间的滑动
if (Time.time - pointerDownTimeBak < 0.5f)
{
float offsetX = Input.mousePosition.x - pointerDownX;
//向左滑动鼠标,并超过一定距离
if (offsetX < - && pageIdx < pageCount - )
{
//向左滑动鼠标,并超过一段距离
pageIdx++;
//执行所有表格面板向左平滑滑动
//0.5秒对自身左边叠加量,向左移动一段距离
contenTrans.DOBlendableLocalMoveBy(new Vector3(-panelCellOffset, , ), MOVE_TIME); }
else if (offsetX > && pageIdx > )
{
//向右滑动鼠标,并超过一段距离
pageIdx--;
//执行所有表格面板向右平滑滑动
//0.5秒对自身左边叠加量,向右移动一段距离
contenTrans.DOBlendableLocalMoveBy(new Vector3(panelCellOffset, , ), MOVE_TIME);
}
}
}
} //创建表格panel,从0开始编号
void CreateLevelPanclCell(int pageInx)
{
GameObject panelObj = Instantiate(levelPanelCellPreb, contenTrans);
RectTransform panelTrans = panelObj.GetComponent<RectTransform>();
panelTrans.anchoredPosition = new Vector2(panelCellOffset * pageInx, ); //确定本业 中具有的关卡元素个数
int startId = ITEM_COUNT_PAGE * pageInx;
//本业需要显示按钮的个数
int count = totalCount - startId; if (count > ITEM_COUNT_PAGE)
{
count = ITEM_COUNT_PAGE;
} //创建本页中所有关卡按钮
for (int i = ; i < count; i++)
{
//创建每一个关卡的按钮单元
GameObject itemObj = Instantiate(levelItemCellPreb, panelTrans); //这一段cell相关调用,实在Start()之前执行的
LevelItemCell cell = itemObj.GetComponent<LevelItemCell>();
cell.id = startId + i + ; //设置每个单元的关卡编号
cell.lvlMgr = this;
itemObj.name = cell.id.ToString(); } } //设置关卡描述
public void SetLevelDesc(string content)
{
levelDescTxt.text = content;
} void OnBackMainMenuBtn()
{
SceneManager.LoadScene("MainMenu");
}
}

LevelManager.cs (游戏管理脚本)

实现过程

选关游戏界面

  新建画布,添加背景,设置标题,增加选关区域范围

  选关区域使用纯白色作为背景(修改其透明度值),调整选关区域位置

  选关区域下方添加关卡信息(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关
readonly int ITEM_COUNT_PAGE = ; //每一页显示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, ); //确定本业 中具有的关卡元素个数
int startId = ITEM_COUNT_PAGE * pageInx;
//本业需要显示按钮的个数
int count = totalCount - startId; if (count > ITEM_COUNT_PAGE)
{
count = ITEM_COUNT_PAGE;
} //创建本页中所有关卡按钮
for(int i =;i<count;i++)
{
//创建每一个关卡的按钮单元
GameObject itemObj = Instantiate(levelItemCellPreb,panelTrans); LevelItemCell cell = itemObj.GetComponent<LevelItemCell>();
cell.id = startId+i+;
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 () { }
}

LevelItemCell.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI; //用来管理所有关卡按钮
//根据我们关卡数据定义,判断一共多少个关卡按钮。LevelManager来创建LevelPanelCell表格单元,LevelPanelCell表格单元是LevelItemCell
public class LevelManager : MonoBehaviour { int totalCount = ; //临时测试,一共18关
readonly int ITEM_COUNT_PAGE = ; //每一页显示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 = ; 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, ); //确定本业 中具有的关卡元素个数
int startId = ITEM_COUNT_PAGE * pageInx;
//本业需要显示按钮的个数
int count = totalCount - startId; if (count > ITEM_COUNT_PAGE)
{
count = ITEM_COUNT_PAGE;
} //创建本页中所有关卡按钮
for(int i =;i<count;i++)
{
//创建每一个关卡的按钮单元
GameObject itemObj = Instantiate(levelItemCellPreb,panelTrans); LevelItemCell cell = itemObj.GetComponent<LevelItemCell>();
cell.id = startId+i+;
cell.lvlMgr = this;
itemObj.name = cell.id.ToString(); } } //设置关卡描述
void SetLevelDesc(string content)
{
levelDescTxt.text = content;
}
}

LevelManager.cs

  因为我们默认初始化游戏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关
readonly int ITEM_COUNT_PAGE = ; //每一页显示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 = ; for (int i = ; i < pageCount; i++)
{
CreateLevelPanclCell(i);
}
} // Update is called once per frame
void Update () {
//按下时记录鼠标当前位置
if (Input.GetMouseButtonDown())
{
pointerDownTimeBak = Time.time;
pointerDownX = Input.mousePosition.x;
} if(Input.GetMouseButtonUp())
{
//模拟滑动事件,假定很短时间的滑动
if(Time.time - pointerDownTimeBak<0.5f)
{
float offsetX = Input.mousePosition.x - pointerDownX;
//向左滑动鼠标,并超过一定距离
if (offsetX < - && pageIdx<pageCount-)
{
//向左滑动鼠标,并超过一段距离
pageIdx++;
//执行所有表格面板向左平滑滑动
//0.5秒对自身左边叠加量,向左移动一段距离
contenTrans.DOBlendableLocalMoveBy(new Vector3(-panelCellOffset, , ), MOVE_TIME); }else if (offsetX>&&pageIdx>)
{
//向右滑动鼠标,并超过一段距离
pageIdx--;
//执行所有表格面板向右平滑滑动
//0.5秒对自身左边叠加量,向右移动一段距离
contenTrans.DOBlendableLocalMoveBy(new Vector3(panelCellOffset, , ), MOVE_TIME);
}
}
}
} //创建表格panel,从0开始编号
void CreateLevelPanclCell(int pageInx)
{
GameObject panelObj = Instantiate(levelPanelCellPreb,contenTrans);
RectTransform panelTrans = panelObj.GetComponent<RectTransform>();
panelTrans.anchoredPosition = new Vector2(panelCellOffset * pageInx, ); //确定本业 中具有的关卡元素个数
int startId = ITEM_COUNT_PAGE * pageInx;
//本业需要显示按钮的个数
int count = totalCount - startId; if (count > ITEM_COUNT_PAGE)
{
count = ITEM_COUNT_PAGE;
} //创建本页中所有关卡按钮
for(int i =;i<count;i++)
{
//创建每一个关卡的按钮单元
GameObject itemObj = Instantiate(levelItemCellPreb,panelTrans); LevelItemCell cell = itemObj.GetComponent<LevelItemCell>();
cell.id = startId+i+;
cell.lvlMgr = this;
itemObj.name = cell.id.ToString(); } } //设置关卡描述
void SetLevelDesc(string content)
{
levelDescTxt.text = content;
}
}

LevelManager.cs

  MOVE_TIME时间内选择关卡向左边的叠加量,向左移动一段距离

 contenTrans.DOBlendableLocalMoveBy(new Vector3(-panelCellOffset, , ), MOVE_TIME);

  按下时记录鼠标当前位置

if (Input.GetMouseButtonDown())
{
pointerDownTimeBak = Time.time;
pointerDownX = Input.mousePosition.x;
}

  松开鼠标时触发事件

 if(Input.GetMouseButtonUp())
{
//模拟滑动事件,假定很短时间的滑动
if(Time.time - pointerDownTimeBak<0.5f)
{
float offsetX = Input.mousePosition.x - pointerDownX;
//向左滑动鼠标,并超过一定距离
if (offsetX < - && pageIdx<pageCount-)
{
//向左滑动鼠标,并超过一段距离
pageIdx++;
//执行所有表格面板向左平滑滑动
//0.5秒对自身左边叠加量,向左移动一段距离
contenTrans.DOBlendableLocalMoveBy(new Vector3(-panelCellOffset, , ), MOVE_TIME); }else if (offsetX>&&pageIdx>)
{
//向右滑动鼠标,并超过一段距离
pageIdx--;
//执行所有表格面板向右平滑滑动
//0.5秒对自身左边叠加量,向右移动一段距离
contenTrans.DOBlendableLocalMoveBy(new Vector3(panelCellOffset, , ), 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 = ;
//初始化关卡数字显示
if (id < )
{
//完全用代码动态创建一个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(,,);
rtf.localPosition = Vector3.zero; }
else if (id<)
{
//十位数
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(, , );
rtf.localPosition = new Vector3(-scale * rtf.rect.width/-,,); //个位数
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 % ];
img2.SetNativeSize(); //图片原始尺寸
rtf2.localScale = new Vector3(, , );
rtf2.localPosition = new Vector3(scale * rtf2.rect.width / + , , );
}
} // Update is called once per frame
void Update () { }
}

LevelItemCell.cs

  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(,,);

  当id<10时,定义图片放置的位置

 rtf.localPosition = Vector3.zero;
if (id < )
{
//完全用代码动态创建一个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(,,);
rtf.localPosition = Vector3.zero; }

  个位数位置

            img.SetNativeSize();    //图片原始尺寸
rtf.localScale = new Vector3(, , );
rtf.localPosition = new Vector3(-scale * rtf.rect.width/-,,);

  十位数位置

            img2.SetNativeSize();    //图片原始尺寸
rtf2.localScale = new Vector3(, , );
rtf2.localPosition = new Vector3(scale * rtf2.rect.width / + , , );

  同理个位数,不同在于图片摆放的位置

        else if (id<)
{
//十位数
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(, , );
rtf.localPosition = new Vector3(-scale * rtf.rect.width/-,,); //个位数
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 % ];
img2.SetNativeSize(); //图片原始尺寸
rtf2.localScale = new Vector3(, , );
rtf2.localPosition = new Vector3(scale * rtf2.rect.width / + , , );
}

数据管理类

    unity除非特别指定,当切换到新场景时原场景中所有游戏对象都会销毁。那么伴随着挂在对象上的脚本也会销毁。
我们需要有一个类,能够使各处都能够便利访问。并且这个类对象实例,只需要一个

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 = ;
//初始化关卡数字显示
if (id < )
{
//完全用代码动态创建一个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(,,);
rtf.localPosition = Vector3.zero; }
else if (id<)
{
//十位数
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(, , );
rtf.localPosition = new Vector3(-scale * rtf.rect.width/-,,); //个位数
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 % ];
img2.SetNativeSize(); //图片原始尺寸
rtf2.localScale = new Vector3(, , );
rtf2.localPosition = new Vector3(scale * rtf2.rect.width / + , , );
}
levelInfo = DataMgr.Instance().levelData.levels[id - ];
} // Update is called once per frame
void Update () { }
}

LevelItemCell.cs

  初始化时点击单元关卡(粉红色效果)和锁(效果)不可见

   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 = ;
//初始化关卡数字显示
if (id < )
{
//完全用代码动态创建一个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(,,);
rtf.localPosition = Vector3.zero; }
else if (id<)
{
//十位数
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(, , );
rtf.localPosition = new Vector3(-scale * rtf.rect.width/-,,); //个位数
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 % ];
img2.SetNativeSize(); //图片原始尺寸
rtf2.localScale = new Vector3(, , );
rtf2.localPosition = new Vector3(scale * rtf2.rect.width / + , , );
}
levelInfo = DataMgr.Instance().levelData.levels[id - ];
} // Update is called once per frame
void Update () { }
}

Unity3D_(游戏)卡牌03_选关界面的更多相关文章

  1. Unity3D_(游戏)卡牌02_主菜单界面

      启动屏界面.主菜单界面.选关界面.游戏界面 卡牌01_启动屏界面 传送门 卡牌02_主菜单界面 传送门 卡牌03_选关界面 传送门 卡牌04_游戏界面    传送门 主菜单界面 (选择左边图标或选 ...

  2. Unity3D_(游戏)卡牌01_启动屏界面

      卡牌2D游戏展示 (游戏代码放到  卡牌04_游戏界面  文章最后面~) 游戏项目已托管到github上(里面有个32bit可执行文件) 传送门 规则 开始游戏每张卡牌初始翻开展示 展示几秒后卡牌 ...

  3. Unity3D_(游戏)卡牌04_游戏界面

        启动屏界面.主菜单界面.选关界面.游戏界面 卡牌01_启动屏界面 传送门 卡牌02_主菜单界面 传送门 卡牌03_选关界面 传送门 卡牌04_游戏界面    传送门 选关界面效果 (源代码在文 ...

  4. iOS开发 Swift开发数独游戏(三) 选关界面

    一.选关界面涉及到的功能点 1)需要UITableView以及相应数据代理.协议的实现 2)读取plist文件并转化成模型 3)在单元格点击后进入数独游戏,涉及到把数据经segue在UIViewCon ...

  5. Html5 Egret游戏开发 成语大挑战(四)选关界面

    通过前面的开始界面基本上了解了eui的使用方法,可以简单快速的制作一个UI界面,本篇使用第二界面选关界面展示更为难一点的代码控制,来展现关卡地图的内容,请确保素材和资源完整,可以在前面的教程中找到下载 ...

  6. 在WebGL场景中管理多个卡牌对象的实验

    这篇文章讨论如何在基于Babylon.js的WebGL场景中,实现多个简单卡牌类对象的显示.选择.分组.排序,同时建立一套实用的3D场景代码框架.由于作者美工能力有限,所以示例场景视觉效果可能欠佳,本 ...

  7. iOS开发 Swift开发数独游戏(四) 游戏界面的界面与逻辑

    一.游戏界面涉及到的功能点 1)数独格子的建模 (1)绘制数独格子要考虑到标记功能 所以要在每个格子内预先塞入9个标记数字,仅数独格子算下来就有9*9*9=729个格子且存在大量嵌套(这导致我在操作S ...

  8. cocos2d-x 3.3 之卡牌设计 NO.4 定时器的使用(清理内存)

    我的卡牌游戏卡牌有两个类.各自是OpenCard和CardSprite. 不知道分成两个是不是有些奇怪.我分开的原因是:一个卡牌用来当手牌,一个用来当场上的牌,这样说是不是更加奇怪了.. 玩家类里定义 ...

  9. [省选联考 2021 A/B 卷] 卡牌游戏

    垃圾福建垫底选手来看看这题. 大家怎么都写带 \(log\) 的. 我来说一个线性做法好了. 那么我们考虑枚举 \(k\) 作为翻转完的最小值. 那么构造出一个满足条件的操作,我们在 \(a_i\) ...

随机推荐

  1. 2019年8月23日 星期五(workerman和swoole的区别)

    两个框架我都有用过,workerman用得更多些,这2个框架都很出名,它们的出现大大的提高了php的应用范围及知名度 workerman和swoole都是php socket 服务器框架,都支持长连接 ...

  2. 仿优酷项目—orm

    仿优酷项目 一.ORM介绍 对象关系映射,把数据库中的表数据(表名.表记录.字段)全部映射到python中. ​ mysql: python: ​ 表名 ---->类名 ​ 记录 ----> ...

  3. python基础之初始函数

    首先,为什么要使用函数? 函数的本质来说,就是写一串代码具有某些功能,然后封装起来,接下来可以很方便的调用 例如...然后... # s = '金老板小护士'# len(s) #在这里需求是求字符串s ...

  4. gson 带泛型的转换

    json转对象 public static <T> T json2Obj(String json, Class<T> cls) { Gson gson = new Gson() ...

  5. [转载]汇编语言assume伪指令的作用

    原文:https://blog.csdn.net/u010234808/article/details/38366943 摘出关键部分: 编写程序,是写给编译软件的.由编译软件,编译成机器码,再去控制 ...

  6. Three.js类似于波浪的效果

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  7. orace result cache解析

      (1)   orace 11.2.0.4 在RAC数据库Dataguard切换时,出现少量数据丢失:          解决方案:关闭result cache 功能 或升级数据库版本并安装补丁: ...

  8. java代码中的坑

    1.Integer 类型数值比较: public static void main(String[] args) {         // TODO Auto-generated method stu ...

  9. jekens安装

    https://jenkins.io/zh/download/ Generic Java package (.war) 下载jenkins.war文件 将jenkins.war发布到tomcat服务器 ...

  10. Angular2 父子组件通信方式

    https://www.jb51.net/article/133868.htm 这次给大家带来Angular2 父子组件通信方式,使用Angular2 父子组件通信方式的注意事项有哪些,下面就是实战案 ...