一、效果展示:

编辑完后,关闭窗口会自动保存数据

二、具体实现

1.创建存储数据的文件

这里我是用ScriptableObject类文件进行配置数据的存储

CustomsPassDataConfig.cs脚本

这是在右键菜单中添加创建数据文件的功能脚本,注意该脚本要继承ScriptableObject类

using System.Collections.Generic;
using UnityEngine;
using System;//每一关的具体数据
[Serializable]
public class CustomsPassData
{public bool isPass = false; //是否通过//第一张 第二张图片public Sprite Sprite1;public Sprite Sprite2;public List<Vector2> posList = new List<Vector2>(); //找不同的区域位置public List<Vector2> sizeList = new List<Vector2>(); //找不同的区域大小
}//基础数据配置
[CreateAssetMenu(menuName = "Config/CustomsPassDataConfig", fileName = "DataConfig")] //右键文件在显示的菜单中选择Config/CustomsPassDataConfig创建一个名为DataConfig的数据文件
public class CustomsPassDataConfig : ScriptableObject
{public List<CustomsPassData> CustomsPassDataList = new List<CustomsPassData>() { new CustomsPassData() };
}

效果:

2.界面布局

(1)CustomsPassPanel 关卡面板(用于放置关卡脚本)

(2)Root 空节点 (存放关卡面板的所有内容,方便显示隐藏)

PS:不使用CustomsPassPanel 面板的原因是因为他要挂载脚本,隐藏后脚本方法就无法调用了。同时它也可以当作背景板使用

(3)ImagePanel面板 (用于存放关卡的图片,需要两个)

pool代表着存放区域(两张图片不同点要点击的区域)的按钮,起到对象池的作用

(4)AreaItem 区域按钮预设

该预设放在Resources文件夹下,方便Editor窗口调用。

创建完后 删除pool下的AreaItem区域按钮,让pool没有子物体即可。

3.创建扩展编辑器

CustomsPassDataConfigEditer.cs脚本

注意:

1.扩展编辑器要使用Unity的UnityEditor程序集,所有使用该程序集类的方法都需要使用

#if UNITY_EDITOR
using UnityEditor;
#endif

包裹住,否则打包会报错

2.该脚本要放在Editor文件夹下(有第一条,不放在该文件下也可以,保险起见还是放在里面吧)

(1)创建一个菜单开启一个新的窗口功能

using System.Collections;
using System.Collections.Generic;
using UnityEngine;//注意
#if UNITY_EDITOR
using UnityEditor;
#endifpublic class CustomsPassDataConfigEditer : EditorWindow
{//注意 窗口绘制的组件都需要包裹住
#if UNITY_EDITOR//1.开启窗口方式 (注意:要使用static才能调用该方法)//注册方法到标题栏[MenuItem("Window/CustomsPassDataEditor")]private static void Open(){CustomsPassDataConfigEditer test = GetWindow<CustomsPassDataConfigEditer>("CustomsPassDataConfigEditer");//("CustomsPassDataConfigEditer")窗口标题的名字test.minSize = new Vector2(600, 300); //窗体最小值test.Show();//开启}#endif
}

效果:

(2) 窗口有了,现在创建头部标题按钮

参考效果图:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;//注意
#if UNITY_EDITOR
using UnityEditor;
#endifpublic class CustomsPassDataConfigEditer : EditorWindow
{//注意 窗口绘制的组件都需要包裹住
#if UNITY_EDITOR//1.开启窗口方式//注册方法到标题栏 (注意:要使用static才能调用该方法)[MenuItem("Window/CustomsPassDataEditor")]private static void Open(){CustomsPassDataConfigEditer test = GetWindow<CustomsPassDataConfigEditer>("CustomsPassDataConfigEditer");//("CustomsPassDataConfigEditer")窗口标题的名字test.minSize = new Vector2(600, 300); //窗体最小值test.Show();//开启}//窗口的组件都要在OnGUI创建void OnGUI() {TitleMenuBtn();//绘制标题按钮}#endif#region TitleMenuBtn//一种系统样式,使用它就可以使按钮展示为矩形黑框样式string titleTxt = "难度:简单"; //难度标题string currentCustomsTxt = "当前关卡:第一关";private GUIStyle _preButton = new GUIStyle("PreButton");private void TitleMenuBtn(){if (GUI.Button(new Rect(5, 5, 60, 15), "Easy", _preButton)){titleTxt = "难度:简单";}if (GUI.Button(new Rect(65, 5, 60, 15), "Common", _preButton)){titleTxt = "难度:普通";}if (GUI.Button(new Rect(125, 5, 60, 15), "Difficulty", _preButton)){titleTxt = "难度:困难";}//添加if (GUI.Button(new Rect((int)position.width - 105, 5, 50, 15), "Add", _preButton)){Debug.Log("添加");}//删除if (GUI.Button(new Rect((int)position.width - 55, 5, 50, 15), "delete", _preButton)){Debug.Log("删除");}//难度标题GUI.Label(new Rect(10, 25, 100, 15), titleTxt); GUI.Label(new Rect(110, 25, 100, 15), currentCustomsTxt);}#endregion}

运行效果图:

(3)制作左侧选择关卡按钮

参考图:

这里按钮左右填充了整个面板的原因是我用了自适应布局GuILayout,所以不用担心。

代码:这里添加了OnEnable、 Content和SelectCustomsPassData方法。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;//注意
#if UNITY_EDITOR
using UnityEditor;
#endifpublic class CustomsPassDataConfigEditer : EditorWindow
{int index = 0;         //当前关卡下标 (用于从EasyData的List中获取关卡数据)int customsCount = 0;  //关卡总数量CustomsPassDataConfig currentImageData;//注意 窗口绘制的组件都需要包裹住
#if UNITY_EDITOR//1.开启窗口方式//注册方法到标题栏 (注意:要使用static才能调用该方法)[MenuItem("Window/CustomsPassDataEditor")]private static void Open(){CustomsPassDataConfigEditer test = GetWindow<CustomsPassDataConfigEditer>("CustomsPassDataConfigEditer");//("CustomsPassDataConfigEditer")窗口标题的名字test.minSize = new Vector2(600, 300); //窗体最小值test.Show();//开启}//开启窗口时 初始化数据void OnEnable() {//数据初始化(使用绝对路径获取刚才创建的EasyData文件)currentImageData = AssetDatabase.LoadAssetAtPath<CustomsPassDataConfig>("Assets/02_Scripts/BaseDataConfige/EasyData.asset");SelectCustomsPassData(0);//关卡生成}//窗口的组件都要在OnGUI创建void OnGUI() {TitleMenuBtn(); //绘制标题按钮Content();      //内容}#endif#region TitleMenuBtn//一种系统样式,使用它就可以使按钮展示为矩形黑框样式string titleTxt = "难度:简单"; //难度标题string currentCustomsTxt = "当前关卡:第一关";private GUIStyle _preButton = new GUIStyle("PreButton");private void TitleMenuBtn(){if (GUI.Button(new Rect(5, 5, 60, 15), "Easy", _preButton)){titleTxt = "难度:简单";}if (GUI.Button(new Rect(65, 5, 60, 15), "Common", _preButton)){titleTxt = "难度:普通";}if (GUI.Button(new Rect(125, 5, 60, 15), "Difficulty", _preButton)){titleTxt = "难度:困难";}//添加if (GUI.Button(new Rect((int)position.width - 105, 5, 50, 15), "Add", _preButton)){Debug.Log("添加");}//删除if (GUI.Button(new Rect((int)position.width - 55, 5, 50, 15), "delete", _preButton)){Debug.Log("删除");}//难度标题GUI.Label(new Rect(10, 25, 100, 15), titleTxt); GUI.Label(new Rect(110, 25, 100, 15), currentCustomsTxt);}#endregion#region Contentprivate Vector2 _scroll;void Content(){GUILayout.Space(45); //插入空白GUILayout.BeginHorizontal("Box");GUILayout.BeginVertical();_scroll = GUILayout.BeginScrollView(_scroll);//开始一个滚动视野//关卡按钮生成for (int i = 0; i < customsCount; i++){if (GUILayout.Button("关卡" + (i + 1))){Debug.Log("关卡"  + (i + 1));}}GUILayout.EndScrollView();          //结束一个滚动视野GUILayout.EndVertical();            //结束一个垂直布局GUILayout.Space(10);                //插入空白GUILayout.EndHorizontal();}#endregion#region 修改当前选择的关卡,并获取数据进行展示 //获取当前关卡数据void SelectCustomsPassData(int i){index = i;//关卡数量customsCount = currentImageData.CustomsPassDataList.Count;}#endregion}

效果图:

(4) 我们继续补充右侧 图片

参考图:

代码: 这里添加了GetComponent方法,在Content中添加了 “图片选择区域”

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;//注意
#if UNITY_EDITOR
using UnityEditor;
#endifpublic class CustomsPassDataConfigEditer : EditorWindow
{int index = 0;         //当前关卡下标 (用于从EasyData的List中获取关卡数据)int customsCount = 0;  //关卡总数量CustomsPassDataConfig currentImageData;//图片画布Image imagePanel;Image image2Panel;//注意 窗口绘制的组件都需要包裹住
#if UNITY_EDITOR//1.开启窗口方式//注册方法到标题栏 (注意:要使用static才能调用该方法)[MenuItem("Window/CustomsPassDataEditor")]private static void Open(){CustomsPassDataConfigEditer test = GetWindow<CustomsPassDataConfigEditer>("CustomsPassDataConfigEditer");//("CustomsPassDataConfigEditer")窗口标题的名字test.minSize = new Vector2(600, 300); //窗体最小值test.Show();//开启}//开启窗口时 初始化数据void OnEnable() {//数据初始化(使用绝对路径获取刚才创建的EasyData文件)currentImageData = AssetDatabase.LoadAssetAtPath<CustomsPassDataConfig>("Assets/02_Scripts/BaseDataConfige/EasyData.asset");GetComponent(); //组件获取SelectCustomsPassData(0);//关卡生成}//窗口的组件都要在OnGUI创建void OnGUI() {TitleMenuBtn(); //绘制标题按钮Content();      //内容}#endif#region TitleMenuBtn//一种系统样式,使用它就可以使按钮展示为矩形黑框样式string titleTxt = "难度:简单"; //难度标题string currentCustomsTxt = "当前关卡:第一关";private GUIStyle _preButton = new GUIStyle("PreButton");private void TitleMenuBtn(){if (GUI.Button(new Rect(5, 5, 60, 15), "Easy", _preButton)){titleTxt = "难度:简单";}if (GUI.Button(new Rect(65, 5, 60, 15), "Common", _preButton)){titleTxt = "难度:普通";}if (GUI.Button(new Rect(125, 5, 60, 15), "Difficulty", _preButton)){titleTxt = "难度:困难";}//添加if (GUI.Button(new Rect((int)position.width - 105, 5, 50, 15), "Add", _preButton)){Debug.Log("添加");}//删除if (GUI.Button(new Rect((int)position.width - 55, 5, 50, 15), "delete", _preButton)){Debug.Log("删除");}//难度标题GUI.Label(new Rect(10, 25, 100, 15), titleTxt); GUI.Label(new Rect(110, 25, 100, 15), currentCustomsTxt);}#endregion#region Contentprivate Vector2 _scroll;void Content(){GUILayout.Space(45); //插入空白GUILayout.BeginHorizontal("Box");GUILayout.BeginVertical();_scroll = GUILayout.BeginScrollView(_scroll);//开始一个滚动视野//关卡按钮生成for (int i = 0; i < customsCount; i++){if (GUILayout.Button("关卡" + (i + 1))){Debug.Log("关卡"  + (i + 1));}}GUILayout.EndScrollView();          //结束一个滚动视野GUILayout.EndVertical();            //结束一个垂直布局GUILayout.Space(10);                //插入空白GUILayout.BeginVertical();          //开始一个垂直布局#region 图片选择区域GUILayout.BeginHorizontal("Box");imagePanel.sprite = currentImageData.CustomsPassDataList[index].Sprite1 = EditorGUILayout.ObjectField("第一张:", currentImageData.CustomsPassDataList[index].Sprite1, typeof(Sprite), true) as Sprite;image2Panel.sprite = currentImageData.CustomsPassDataList[index].Sprite2 = EditorGUILayout.ObjectField("第二张:", currentImageData.CustomsPassDataList[index].Sprite2, typeof(Sprite), true) as Sprite;GUILayout.EndHorizontal();#endregionGUILayout.EndVertical();            //结束一个垂直布局GUILayout.EndHorizontal();}#endregion#region 修改当前选择的关卡,并获取数据进行展示 //获取当前关卡数据void SelectCustomsPassData(int i){index = i;//关卡数量customsCount = currentImageData.CustomsPassDataList.Count;//关卡切换时修改图片imagePanel.sprite = currentImageData.CustomsPassDataList[index].Sprite1;image2Panel.sprite = currentImageData.CustomsPassDataList[index].Sprite2;}#endregion#region 获取组件bool isGetComponent = true; //只有开启第一次获取,后面不在获取void GetComponent(){//图片面板为空时,获取if (isGetComponent){//加载组件(根据绝对路径获取,注意不要搞错路径)imagePanel = GameObject.Find("Canvas/CustomsPassPanel/root/ImagePanel").GetComponent<Image>();image2Panel = GameObject.Find("Canvas/CustomsPassPanel/root/Image2Panel").GetComponent<Image>();isGetComponent = false;}}#endregion}

运行效果:

(5)最后补充右侧区域的位置、大小信息

参考图片:

代码:补充GetComponent,添加CreateAreaItem()方法,在Content方法中 添加了“AreaItem位置、大小区域”和 “添加区域节点 按钮”块

 #region 获取某个场景所有物体//UnityEditor.SceneManagement.EditorSceneManager.OpenScene("Assets/01_Scenes/Test.unity");//UnityEngine.SceneManagement.Scene curScene = UnityEngine.SceneManagement.SceneManager.GetSceneByPath("Assets/ArtTools/ModelShow/Scenes/ModelShowTest.unity");//GameObject[] gos = curScene.GetRootGameObjects();//foreach (var go in gos)//{//    Debug.Log(go.name);//}#endregion//图片面板为空时,获取if (imagePanel == null || image2Panel == null){//获取当前场景物体foreach (GameObject obj in Resources.FindObjectsOfTypeAll(typeof(GameObject))){if (obj.name == "ImagePanel"){imagePanel = obj.transform.GetComponent<Image>();}else if (obj.name == "ImagePanel2"){image2Panel = obj.transform.GetComponent<Image>();}//都不为空时 跳出循环if (imagePanel != null && image2Panel != null)break;}}//修改图片imagePanel.sprite = currentImageData.CustomsPassDataList[index].Sprite1;image2Panel.sprite = currentImageData.CustomsPassDataList[index].Sprite2;//找到当前场景的物体GameObject go = GameObject.Find("Canvas/CustomsPassPanel/root/ImagePanel/pool/AreaItem");//在场景中点击效果EditorGUIUtility.PingObject(go);Selection.activeGameObject = go;

效果:

核心功能已经完成,接下来就是修改补充一下了,脚本中有明确的注释,不懂得大家也可以私信问我。

最终脚本内容

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;//注意
#if UNITY_EDITOR
using UnityEditor;
#endifpublic class CustomsPassDataConfigEditer : EditorWindow
{bool isLayOut = false;//判断一开始是否布局完成 (自适应LayoutGUI绘制得组件会被执行两次,第一次是布局,第二次是绘制,在第一次执行布局的时候,执行组件赋值会出现一个错误提示)int index = 0;         //当前关卡下标 (用于从EasyData的List中获取关卡数据)int customsCount = 0;  //关卡总数量CustomsPassDataConfig currentImageData;//图片画布Image imagePanel;Image image2Panel;//区域预设、两个对象池GameObject areaItemPrefab;Transform pool;Transform pool2;//注意 窗口绘制的组件都需要包裹住
#if UNITY_EDITOR//1.开启窗口方式//注册方法到标题栏 (注意:要使用static才能调用该方法)[MenuItem("Window/CustomsPassDataEditor")]private static void Open(){CustomsPassDataConfigEditer test = GetWindow<CustomsPassDataConfigEditer>("CustomsPassDataConfigEditer");//("CustomsPassDataConfigEditer")窗口标题的名字test.minSize = new Vector2(600, 300); //窗体最小值test.Show();//开启}//开启窗口时 初始化数据void OnEnable(){//数据初始化(使用绝对路径获取刚才创建的EasyData文件)currentImageData = AssetDatabase.LoadAssetAtPath<CustomsPassDataConfig>("Assets/02_Scripts/BaseDataConfige/EasyData.asset");GetComponent(); //组件获取SelectCustomsPassData(0);//关卡生成}//3.关闭时保存ScriptableObject类型数据protected void OnDisable(){isLayOut = false;//还原图片为空imagePanel.sprite = null;image2Panel.sprite = null;//隐藏所有区域for (int i = 0; i < pool.childCount; i++)pool.GetChild(i).gameObject.SetActive(false);EditorUtility.SetDirty(currentImageData); //不加这段话,项目关闭打开后不保存ScriptableObject数据}//窗口的组件都要在OnGUI创建void OnGUI(){//获取关卡资源 初始化currentCustomsTxt = $"当前关卡:第{index + 1}关";TitleMenuBtn(); //绘制标题按钮Content();      //内容GUILayout.FlexibleSpace();      //最后创建一个自适应的空白区域,也即是填满本次布局中的这部分空间isLayOut = true; //执行完布局后为true}#endif#region TitleMenuBtn//一种系统样式,使用它就可以使按钮展示为矩形黑框样式string titleTxt = "难度:简单"; //难度标题string currentCustomsTxt = "当前关卡:第一关";private GUIStyle _preButton = new GUIStyle("PreButton");private void TitleMenuBtn(){if (GUI.Button(new Rect(5, 5, 60, 15), "Easy", _preButton)){//数据初始化currentImageData = AssetDatabase.LoadAssetAtPath<CustomsPassDataConfig>("Assets/02_Scripts/BaseDataConfige/EasyData.asset");titleTxt = "难度:简单";SelectCustomsPassData(0); //选择关卡后 修改场景组件数据}if (GUI.Button(new Rect(65, 5, 60, 15), "Common", _preButton)){//数据初始化currentImageData = AssetDatabase.LoadAssetAtPath<CustomsPassDataConfig>("Assets/02_Scripts/BaseDataConfige/CommonData.asset");titleTxt = "难度:普通";SelectCustomsPassData(0); //选择关卡后 修改场景组件数据}if (GUI.Button(new Rect(125, 5, 60, 15), "Difficulty", _preButton)){//数据初始化currentImageData = AssetDatabase.LoadAssetAtPath<CustomsPassDataConfig>("Assets/02_Scripts/BaseDataConfige/DifficultyData.asset");titleTxt = "难度:困难";SelectCustomsPassData(0); //选择关卡后 修改场景组件数据}//添加if (GUI.Button(new Rect((int)position.width - 105, 5, 50, 15), "Add", _preButton)){currentImageData.CustomsPassDataList.Add(new CustomsPassData());customsCount = currentImageData.CustomsPassDataList.Count;SelectCustomsPassData(customsCount - 1); //选择关卡后 修改场景组件数据}//删除if (GUI.Button(new Rect((int)position.width - 55, 5, 50, 15), "delete", _preButton)){//最后一个时 只清除数据if (currentImageData.CustomsPassDataList.Count - 1 <= 0){currentImageData.CustomsPassDataList[index].Sprite1 = null;currentImageData.CustomsPassDataList[index].Sprite2 = null;currentImageData.CustomsPassDataList[index].posList.Clear();currentImageData.CustomsPassDataList[index].sizeList.Clear();return;}currentImageData.CustomsPassDataList.Remove(currentImageData.CustomsPassDataList[index]);index = 0;}//难度标题GUI.Label(new Rect(10, 25, 100, 15), titleTxt);GUI.Label(new Rect(110, 25, 100, 15), currentCustomsTxt);}#endregion#region Contentprivate Vector2 _scroll;private Vector2 _scrollList;void Content(){GUILayout.Space(45); //插入空白GUILayout.BeginHorizontal("Box");GUILayout.BeginVertical();_scroll = GUILayout.BeginScrollView(_scroll);//开始一个滚动视野//关卡按钮生成for (int i = 0; i < customsCount; i++){if (GUILayout.Button("关卡" + (i + 1))){if (isLayOut){//图片修改SelectCustomsPassData(i);//选择关卡}}}GUILayout.EndScrollView();          //结束一个滚动视野GUILayout.EndVertical();            //结束一个垂直布局GUILayout.Space(10);                //插入空白GUILayout.BeginVertical();          //开始一个垂直布局#region 图片选择区域GUILayout.BeginHorizontal("Box");imagePanel.sprite = currentImageData.CustomsPassDataList[index].Sprite1 = EditorGUILayout.ObjectField("第一张:", currentImageData.CustomsPassDataList[index].Sprite1, typeof(Sprite), true) as Sprite;image2Panel.sprite = currentImageData.CustomsPassDataList[index].Sprite2 = EditorGUILayout.ObjectField("第二张:", currentImageData.CustomsPassDataList[index].Sprite2, typeof(Sprite), true) as Sprite;GUILayout.EndHorizontal();#endregion#region AreaItem位置、大小区域GUILayout.BeginHorizontal("Box");GUILayout.Label("区域信息:");_scrollList = GUILayout.BeginScrollView(_scrollList);//开始一个滚动视野for (int i = 0; i < currentImageData.CustomsPassDataList[index].posList.Count; i++){GUILayout.BeginHorizontal("Box");//位置currentImageData.CustomsPassDataList[index].posList[i] = pool.GetChild(i).GetComponent<RectTransform>().anchoredPosition = EditorGUILayout.Vector2Field($"Position{i}", pool.GetChild(i).GetComponent<RectTransform>().anchoredPosition);//大小currentImageData.CustomsPassDataList[index].sizeList[i] = pool.GetChild(i).GetComponent<RectTransform>().sizeDelta = EditorGUILayout.Vector2Field($"Size{i}", pool.GetChild(i).GetComponent<RectTransform>().sizeDelta);//删除区域节点if (GUILayout.Button("删除")){//DestroyImmediate(pool.GetChild(i));//销毁物体pool.GetChild(i).gameObject.SetActive(false);//销毁物体//pool2.GetChild(i).gameObject.SetActive(false);//销毁物体currentImageData.CustomsPassDataList[index].posList.Remove(currentImageData.CustomsPassDataList[index].posList[i]);currentImageData.CustomsPassDataList[index].sizeList.Remove(currentImageData.CustomsPassDataList[index].sizeList[i]);}GUILayout.EndHorizontal();}GUILayout.EndScrollView();          //结束一个滚动视野GUILayout.EndHorizontal();          //结束水平区域#endregion#region 添加区域节点 按钮if (GUILayout.Button("添加")){currentImageData.CustomsPassDataList[index].posList.Add(new Vector2(0, 0));currentImageData.CustomsPassDataList[index].sizeList.Add(new Vector2(200, 200));Debug.Log(currentImageData.CustomsPassDataList[index].sizeList[currentImageData.CustomsPassDataList[index].sizeList.Count - 1]);CreateAreaItem();//生成所需要的区域节点 并修改位置 大小}#endregionGUILayout.EndVertical();            //结束一个垂直布局GUILayout.EndHorizontal();}#endregion#region 修改当前选择的关卡,并获取数据进行展示 void SelectCustomsPassData(int i){index = i;//关卡数量customsCount = currentImageData.CustomsPassDataList.Count;//关卡切换时,修改图片imagePanel.sprite = currentImageData.CustomsPassDataList[index].Sprite1;image2Panel.sprite = currentImageData.CustomsPassDataList[index].Sprite2;CreateAreaItem();//生成所需要的区域节点 并修改位置 大小}#endregion#region 获取组件bool isGetComponent = true; //只有开启第一次获取,后面不在获取void GetComponent(){//图片面板为空时,获取if (isGetComponent){//加载组件(根据绝对路径获取,注意不要搞错路径)imagePanel = GameObject.Find("Canvas/CustomsPassPanel/root/ImagePanel").GetComponent<Image>();image2Panel = GameObject.Find("Canvas/CustomsPassPanel/root/Image2Panel").GetComponent<Image>();//获取区域预设体和poolareaItemPrefab = (GameObject)Resources.Load("06_Prefabs/AreaItem");pool = GameObject.Find("Canvas/CustomsPassPanel/root/ImagePanel/pool").transform;pool2 = GameObject.Find("Canvas/CustomsPassPanel/root/Image2Panel/pool").transform;isGetComponent = false;}}#endregion#region 生成所需要的区域节点 并修改位置 大小int areaItemCount;RectTransform obj;RectTransform obj2;void CreateAreaItem(){areaItemCount = currentImageData.CustomsPassDataList[index].posList.Count - pool.childCount; //计算对象池中所需的区域按钮//生成所缺少的区域按钮for (int i = 0; i < areaItemCount; i++){//创建区域预设Instantiate(areaItemPrefab, pool);Instantiate(areaItemPrefab, pool2);}//隐藏对象池中全部的区域按钮for (int i = 0; i < pool.childCount; i++){pool.GetChild(i).gameObject.SetActive(false);}//显示需要的区域按钮 修改名称、位置和大小 (注意pool2下的区域按钮不用显示,我们显示操作pool下的区域按钮)for (int i = 0; i < currentImageData.CustomsPassDataList[index].posList.Count; i++){obj = pool.GetChild(i).GetComponent<RectTransform>();obj2 = pool2.GetChild(i).GetComponent<RectTransform>();obj2.name = obj.name = i.ToString();//修改名称//修改位置 大小obj.anchoredPosition = currentImageData.CustomsPassDataList[index].posList[i];obj.sizeDelta = currentImageData.CustomsPassDataList[index].sizeList[i];//显示obj.gameObject.SetActive(true);obj2.gameObject.SetActive(false);}}#endregion}

下面附上资源包,我用的unity版本是2019.4.4f1,里面包含了找茬的简单玩法。

链接:https://pan.baidu.com/s/1HPhlH6l8NsG2gy-xffI2sw?pwd=syq1 
提取码:syq1

如果有什么不对,或者更加方便简单的思路。欢迎大家指正和教导。

unity创建 《找不同》游戏 图片编辑器相关推荐

  1. 使用Unity创建塔防游戏(Part2)

    How to Create a Tower Defense Game in Unity – Part 2 原文地址:https://www.raywenderlich.com/107529/unity ...

  2. Unity 创建2D平台游戏开发学习教程

    了解如何使用C#在Unity中创建您的第一款2D平台游戏 你会学到什么 使用Unity创建2D奥运会 使用可脚本化的对象和单一模式 使用良好的编程实践 创造武器和射弹 使用可脚本化的对象和委托模式创建 ...

  3. 「Unity2D」使用Unity创建一个2D游戏系列-1

    「Unity2D」使用Unity创建一个2D游戏系列-1 安装unity并且创建你的第一个场景 在第一章,你将会学习到一些非常基本的内容:首先是unity的下载和安装,其次是准备创建我们游戏内的第一个 ...

  4. 使用Unity创建塔防游戏(Part1)

    How to Create a Tower Defense Game in Unity - Part1 原文作者:Barbara Reichart 文章原译:http://www.cnblogs.co ...

  5. 「Unity2D」使用Unity创建一个2D游戏系列-8

    现在我们通过使用粒子改进了游戏的视觉效果,接着我们会在工程里里添加一些音乐和声音.使用Unity我们可以很简单做到,但是这部分却对游戏非常重要重要. 你会学到在哪里去找游戏的声音和音乐,选取一些声音用 ...

  6. 「Unity2D」使用Unity创建一个2D游戏系列-9

    菜单选项 - 载入和重启游戏 本文由泰然教程组成员 betterdenger 翻译,原文请参阅「Menus - loading and restarting the game」 我们已经完成了我们游戏 ...

  7. Unity 和腾讯游戏成立联合创新实验室:从技术创新探索游戏产品新模式和概念

    2019年5月12日,Unity和腾讯游戏共同宣布成立联合创新实验室.双方将充分发挥各自深耕在游戏领域多年的技术优势,协同创新.共同探索未来游戏产品新模式和概念,致力于技术上的飞跃性突破,为中国游戏行 ...

  8. 为什么要选择 Unity 3D来开发游戏?

    选择合适的游戏引擎对于移动游戏开发项目的成功至关重要.功能丰富的 Unity 3D 引擎有助于针对跨多个设备兼容的不同平台进行游戏开发.游戏引擎具有许多资源,例如即时资产.IDE.在线社区帮助.免费教 ...

  9. 用Unity和Playmaker创建一个限时游戏 Creating a Time Limit game with Unity and Playmaker

    本课程结束时,您将拥有在Unity中使用Playmaker创建游戏的工具 你会学到: playmaker状态的基础以及它们如何与动作一起工作. 安装悬停车,可以在竞技场内行驶. 不同力度的射击地雷驱动 ...

  10. Unity创建游戏VFX视觉特效-初级到中级

    MP4 |视频:h264,1280×720 |音频:AAC,44100 Hz 语言:英语+中英文字幕(根据原英文字幕机译更准确)|大小解压后:3.36 GB |时长:4h 17m 本课程是关于用Uni ...

最新文章

  1. MSCKF理论推导与代码解析
  2. “间谍芯片”疑云:谁在撒谎?警示何在?
  3. hdu 1520 没有上司的晚会
  4. dns tunnel 使用 nishang 下载TXT里的cmd(TXT里)实现CC command+ ceye实现数据外发
  5. 人工智能火了 高端人才成了香饽饽
  6. 【Spring】依赖注入 加载顺序
  7. windows和ubuntu双系统设置开机默认系统
  8. JavaScript调用WebServices
  9. ES6--那些新加入的数组方法
  10. TCP协议之三次握手与四次挥手
  11. Android Button常用属性
  12. WPF中一个控件绑定另一个控件的属性
  13. web安全day7:IIS之FTP服务器
  14. css字体库免费下载使用(带网址)
  15. 乐高mindstormsev3_lego mindstorms ev3下载-乐高EV3机器人编程软件1.3.1 家庭版-东坡下载...
  16. PCAN和TSMaster软件入门
  17. 深入理解哈希表(JAVA和Redis哈希表实现)
  18. one 主格 复数 宾格_主格、宾格、名词所有格
  19. 人类跌落梦境显示无法连接服务器,人类跌落梦境手游网络连接失败进不去解决办法一览...
  20. 利用燕尾花数据集画出P-R曲线

热门文章

  1. Mt7628调试简记
  2. 使用Jupyter Notebook远程连接服务器
  3. 离散选择模型(DCM)和深度神经网络(DNN)结合
  4. ArcGIS与插值(一): 统计与地统计
  5. android获取ro._Android 简单的设备信息获取
  6. excel网页服务器端,Excel服务VI――用Excel Web Services创建应用程
  7. 机器健康监测的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
  8. SQLIntegrityConstraintViolationException: ORA-00001: unique constraint及sequence调整初始值
  9. java similarity_Java WordNet Similarity
  10. 电商平台用户购买行为真实度的检测方法及系统