一、效果展示:
编辑完后,关闭窗口会自动保存数据
二、具体实现
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;
#endif
public 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;
#endif
public 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;
#endif
public 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 Content
private 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;
#endif
public 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 Content
private 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();
#endregion
GUILayout.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;
#endif
public 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 Content
private 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();//生成所需要的区域节点 并修改位置 大小
}
#endregion
GUILayout.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>();
//获取区域预设体和pool
areaItemPrefab = (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/1GAABRRwMw5AO08oiMbMg9g 提取码:syq1
如果有什么不对,或者更加方便简单的思路。欢迎大家指正和教导。