unity创建 《找不同》游戏 图片编辑器

一、效果展示:

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

二、具体实现

 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 

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

猜你喜欢

转载自blog.csdn.net/qq_42345116/article/details/122945787