我的demo保卫萝卜中的技术要点

 管理类:

GameManager(单例),GameController(单例);

一些其他的管理类(PlayerManager,AudioSourceManager,FactoryManager)作为GameManager的成员变量存在(这样也可以保证只有一个存在,并且初始化在GameManager之后)

使用到的多种设计模式

:复盘一下我用过的设计模式-CSDN博客

:: Scoll View 结合 GridLayoutGroup 组件可以实现组件的整齐排列

RectTransform

RectTransform 和 Transfrom 的区别

Inspector,Awake,OnEnable与Start之间微妙的关系

Inspector 早于 Awake 早于 OnEnable 早于 Start

地图编辑器  编辑类

MapTool类

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;

#if Tool
[CustomEditor(typeof(MapMaker))]
public class MapTool : Editor
{
    private MapMaker mapMaker;

    //关卡文件列表
    private List<FileInfo> fileList = new List<FileInfo>();
    private string[] fileNameList;

    //当前编辑的关卡索引
    private int selectIndex = -1;

    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();

        if(Application.isPlaying)
        {
            mapMaker = MapMaker.Instance; 
            EditorGUILayout.BeginHorizontal();
            //获取操作的文件名
            fileNameList = GetNames(fileList);

            int currentIndex = EditorGUILayout.Popup(selectIndex, fileNameList);
            if (currentIndex != selectIndex)  //当前选择对象是否改变
            {
                selectIndex = currentIndex;

                //实例化地图的方法
                mapMaker.InitMap();
                //加载当前选择的Level文件
                mapMaker.LoadLevelFile(mapMaker.LoadLevelInfoFile(fileNameList[selectIndex]));
            }

            if (GUILayout.Button("读取关卡列表"))
            {
                LoadLevelFiles();

            }
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginHorizontal();
            if(GUILayout.Button("回复地图编辑器默认状态"))
            {
                mapMaker.RecoverTowerPoint();
            }

            if(GUILayout.Button("清除怪物路点"))
            {
                mapMaker.CLearMonsterPath();
            }

            EditorGUILayout.EndHorizontal();

            if(GUILayout.Button("保存当前关卡数据文件"))
            {
                mapMaker.SaveLevelFileByJson();
            }
        }
    }

    //加载关卡数据文件
    private void LoadLevelFiles()
    {
        CLearList();
        fileList = GetLevelFile();

    }

    //清楚文件列表
    private void CLearList()
    {
        fileList.Clear();
        selectIndex = -1;
    }

    //具体读取关卡列表的方法
    private  List<FileInfo> GetLevelFile()
    {
                                                                         //自动帮我们读后缀是.json的文件
        string[] files = Directory.GetFiles(Application.streamingAssetsPath + "/Json/Level/", "*.json");

        List<FileInfo> list = new List<FileInfo>();
        for (int i = 0; i < files.Length; i++)
        {
            FileInfo file = new FileInfo(files[i]);
            list.Add(file);
        }
        return list;
    }

    //获取关卡文件的名字
    private string[] GetNames(List<FileInfo> files)
    {
        List<string> names = new List<string>();
        foreach (FileInfo file in files)
        {
            names.Add(file.Name);
        }
        //将列表转成数组
        return names.ToArray();
    }


    
}
#endif

Mapmaker 类

using LitJson;
using System.Collections.Generic;
using System.IO;
using UnityEngine;

/// <summary>
/// 地图编辑工具,游戏中作为地图加载产生工具
/// </summary>

public class MapMaker : MonoBehaviour
{
#if Tool
    public bool drawLine;  //是否画线
    public GameObject gridGo;  //格子的预制体

    private static MapMaker _instance;

    public static MapMaker Instance { get => _instance; }
#endif

    //地图的有关属性
    private float mapWidth;  //地图宽
    private float mapHeight;  //地图高

    //格子
    [HideInInspector]
    public float gridWidth;
    [HideInInspector]
    public float gridHeight;

    //当前关卡索引
    //[HideInInspector]
    public int bigLevelID;
    //[HideInInspector]
    public int levelID;

    //全部的格子对象
    public GridPoint[,] gridPoints;

    //行列数
    public const int yRow = 8;
    public const int xCloumn = 12;

    //怪物路径点
    [HideInInspector]
    public List<GridPoint.GridIndex> monsterPath;

    //怪物路径点的具体位置
    [HideInInspector]
    public List<Vector3> monsterPathPos;

    //关卡的背景道路渲染
    private SpriteRenderer bgSR;
    private SpriteRenderer roadSR;

    //每一波次产生的怪物ID列表
    public List<Round.RoundInfo> roundInfoList;

    [HideInInspector]
    public Carrot carrot;

    private void Awake()
    {
#if Tool
        _instance = this;
        InitMapMaker();
#endif

    }

    //初始化地图
    public void InitMapMaker()
    {
        Calculatesize();
        gridPoints = new GridPoint[xCloumn, yRow];
        monsterPath = new List<GridPoint.GridIndex>();
        for (int x = 0; x < xCloumn; x++)
        {
            for (int y = 0; y < yRow; y++)
            {
#if Tool
                GameObject itemGo = Instantiate(gridGo,transform.position,transform.rotation);
#endif

#if Game
                //问工厂要资源的方法
                GameObject itemGo = GameController.Instance.GetGameObjectResource("Grid");
#endif
                itemGo.transform.position = new Vector3(x * gridWidth - mapWidth / 2 + gridWidth / 2,
                    y * gridHeight - mapHeight / 2 + gridHeight / 2);
                itemGo.transform.SetParent(transform);
                gridPoints[x, y] = itemGo.GetComponent<GridPoint>();
                gridPoints[x, y].gridIndex.xIndex = x;
                gridPoints[x, y].gridIndex.yIndex = y;
            }
        }
        bgSR = transform.Find("BG").GetComponent<SpriteRenderer>();
        roadSR = transform.Find("Road").GetComponent<SpriteRenderer>();

    }

#if Game
    //加载地图
    public void LoadMap(int bigLevel, int level)
    {
        bigLevelID = bigLevel;
        levelID = level;
        LoadLevelFile(LoadLevelInfoFile("Level" + bigLevelID.ToString() + "_" + levelID.ToString() + ".json"));
        monsterPathPos = new List<Vector3>();
        for (int i = 0; i < monsterPath.Count; i++)
        {
            monsterPathPos.Add(gridPoints[monsterPath[i].xIndex, monsterPath[i].yIndex].transform.position);
        }

        //起始点与终止点
        GameObject startPointGo = GameController.Instance.GetGameObjectResource("startPoint");
        startPointGo.transform.position = monsterPathPos[0];
        startPointGo.transform.SetParent(transform);

        GameObject endPointGo = GameController.Instance.GetGameObjectResource("Carrot");
        endPointGo.transform.position = monsterPathPos[monsterPathPos.Count - 1] - new Vector3(0, 0, 1);
        endPointGo.transform.SetParent(transform);
        carrot = endPointGo.GetComponent<Carrot>();

    }


#endif

    //纠正位置
    public Vector3 CorrectPosition(float x, float y)
    {
        return new Vector3(x - mapWidth / 2 + gridWidth / 2, y - mapHeight / 2 + gridHeight / 2);
    }

    //计算地图格子宽高
    private void Calculatesize()
    {
        //视口坐标,左下角(0,0),右上角(1,1)
        Vector3 leftDown = new Vector3(0, 0);
        Vector3 rightUp = new Vector3(1, 1);

        //将视口转换为世界坐标
        Vector3 posOne = Camera.main.ViewportToWorldPoint(leftDown);
        Vector3 posTwo = Camera.main.ViewportToWorldPoint(rightUp);

        mapWidth = posTwo.x - posOne.x;
        mapHeight = posTwo.y - posOne.y;

        gridWidth = mapWidth / xCloumn;
        gridHeight = mapHeight / yRow;

    }

#if Tool
    //画格子用于辅助设计
    private void OnDrawGizmos()
    {
        if(drawLine)
        {
            Calculatesize();
            Gizmos.color = Color.green;

            //画行
            for(int y = 0; y <= yRow; y++)
            {
                Vector3 startPos = new Vector3(-mapWidth / 2, -mapHeight / 2 + y * gridHeight);
                Vector3 endPos = new Vector3(mapWidth / 2, -mapHeight / 2 + y * gridHeight);
                Gizmos.DrawLine(startPos, endPos);
            }

            //画列
            for(int x = 0;x <= xCloumn;x++)
            {
                Vector3 startPos = new Vector3(-mapWidth / 2 + x * gridWidth ,mapHeight / 2);
                Vector3 endPos = new Vector3(-mapWidth / 2 + x * gridWidth, -mapHeight / 2);
                Gizmos.DrawLine(startPos, endPos);
            }
        }
    }
#endif

    /// <summary>
    /// 有关地图编辑的方法
    /// </summary>

    //清除怪物路点
    public void CLearMonsterPath()
    {
        monsterPath.Clear();
    }

    //恢复地图编辑默认状态
    public void RecoverTowerPoint()
    {
        CLearMonsterPath();
        for (int x = 0; x < xCloumn; x++)
        {
            for (int y = 0; y < yRow; y++)
            {
                gridPoints[x, y].InitGrid();
            }
        }
    }

    //初始化地图
    public void InitMap()
    {
        bigLevelID = 0;
        levelID = 0;
        RecoverTowerPoint();
        roundInfoList.Clear();
        bgSR.sprite = null;
        roadSR.sprite = null;
    }

#if Tool
    //生成LevelInfo对象用来保存文件
    private LevelInfo CreateLevelInfoGo()
    {
        LevelInfo levelInfo = new LevelInfo
        {
            bigLevelID = this.bigLevelID,
            levelID = this.levelID,
        };
        levelInfo.gridPoints = new List<GridPoint.GridState>(); ;
        for (int x = 0; x < xCloumn; x++)
        {
            for (int y = 0; y < yRow; y++)
            {
                levelInfo.gridPoints.Add(gridPoints[x, y].gridState);
            }
        }
        levelInfo.monsterPath = new List<GridPoint.GridIndex>();
        for (int i = 0; i < monsterPath.Count; i++)
        {
            levelInfo.monsterPath.Add(monsterPath[i]);
        }
        levelInfo.roundInfo = new List<Round.RoundInfo>();
        for (int i = 0; i < roundInfoList.Count; i++)
        {
            levelInfo.roundInfo.Add(roundInfoList[i]);
        }
        Debug.Log("保存成功");
        return levelInfo;
    }

    //保存当前关卡的数据文件
    public void SaveLevelFileByJson()
    {
        LevelInfo levelInfoGo = CreateLevelInfoGo();
        string filePath = Application.streamingAssetsPath + "/Json/Level/" + "Level"
            + bigLevelID.ToString() + "_" + levelID.ToString() + ".json";
        string saveJsonStr = JsonMapper.ToJson(levelInfoGo);
        StreamWriter sw = new StreamWriter(filePath);
        sw.Write(saveJsonStr);
        sw.Close();
    }
    
#endif

    //读取关卡文件解析json转化为LevelInfo对象
    public LevelInfo LoadLevelInfoFile(string fileName)
    {
        LevelInfo levelInfo = new LevelInfo();
        string filePath = Application.streamingAssetsPath + "/Json/Level/" + fileName;
        if (File.Exists(filePath))
        {
            StreamReader sr = new StreamReader(filePath);
            string jsonStr = sr.ReadToEnd();
            sr.Close();
            levelInfo = JsonMapper.ToObject<LevelInfo>(jsonStr);
            return levelInfo;

        }
        Debug.Log("文件加载失败,加载路径是:" + filePath);
        return null;
    }

    //
    public void LoadLevelFile(LevelInfo levelInfo)
    {
        bigLevelID = levelInfo.bigLevelID;
        levelID = levelInfo.levelID;
        for (int x = 0; x < xCloumn; x++)
        {
            for (int y = 0; y < yRow; y++)
            {
                gridPoints[x, y].gridState = levelInfo.gridPoints[y + x * yRow];

                //更新格子的状态
                gridPoints[x, y].UpdateGrid();
            }
        }
        monsterPath.Clear();
        for (int x = 0; x < levelInfo.monsterPath.Count; x++)
        {
            monsterPath.Add(levelInfo.monsterPath[x]);
        }

        roundInfoList = new List<Round.RoundInfo>();
        for (int i = 0; i < levelInfo.roundInfo.Count; i++)
        {
            roundInfoList.Add(levelInfo.roundInfo[i]);
        }

        bgSR.sprite = Resources.Load<Sprite>("Pictures/NormalMordel/Game/"
            + bigLevelID.ToString() + "/" + "BG" + (levelID / 3).ToString());
        roadSR.sprite = Resources.Load<Sprite>("Pictures/NormalMordel/Game/"
            + bigLevelID.ToString() + "/" + "Road" + levelID.ToString());
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/879823.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Django ORM(多表)

文章目录 前言一、关联关系模型二、一对多写入数据二、多对多写入数据二、跨表查询1.查找test 标签的文章2.查找作者名为 test 的文章及标签 三、跨表删除 前言 表与表之间的关系可分为以下三种&#xff1a; 一对一: 一对一关系表示一个模型的每个实例与另一个模型的每个实例…

【字符函数】strcpy函数(字符串复制函数)+strcat函数(字符串追加)+strcmp函数(字符串比较)【笔记】

1.复制函数--------------strcpy函数 函数使用 char*strcpy&#xff08;char* destination, const char* source&#xff09; strcpy函数用于拷贝字符串&#xff0c;即将一个字符串中的内容拷贝到另一个字符串中&#xff08;会覆盖原字符串内容&#xff09;。它的参数是两个指…

Mysql梳理6——order by排序

目录 6 order by排序 6.1 排序数据 6.2 单列排序 6.3 多行排列 6 order by排序 6.1 排序数据 使用ORDER BY字句排序 ASC&#xff08;ascend&#xff09;:升序DESC(descend):降序 ORDER BY子句在SELECT语句的结尾 6.2 单列排序 如果没有使用排序操作&#xff0c;默认…

【HarmonyOS NEXT】DevEco快速实现真机截屏,并保存到电脑

点日志点照机图标选一个路径保存图片在ide中右键图片&#xff0c;点复制电脑随便找个位置保存图片https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/ide-screenshot-V5

1-2.Jetpack 之 Navigation 跳转编码模板

一、Navigation 1、Navigation 概述 Navigation 是 Jetpack 中的一个重要成员&#xff0c;它主要是结合导航图&#xff08;Navigation Graph&#xff09;来控制和简化 Fragment 之间的导航&#xff0c;即往哪里走&#xff0c;该怎么走 2、Navigate 引入 在模块级 build.gra…

Datawhale------Tiny-universe学习笔记——Qwen(1)

1. Qwen整体介绍 对于一个完全没接触过大模型的小白来说&#xff0c;猛一听这个名字首先会一懵&#xff1a;Qwen是啥。这里首先解答一下这个问题。下面是官网给出介绍&#xff1a;Qwen是阿里巴巴集团Qwen团队研发的大语言模型和大型多模态模型系列。其实随着大模型领域的发展&a…

全同台加密综述

文章目录 一、FHE的定义与性质1、核心算法2、性质 二、构造思想三、全同态加密研究进展1、支持部分同态的 Pre-FHE 方案2、基于理想格的 第1代 FHE方案3、基于LWE的 第2代 FHE方案3、基于近似特征向量的 第3代 FHE方案4、支持浮点数运算的 第4代 FHE方案5、其他 FHE方案5.1、基…

数字化时代,住宅代理是怎样为企业赋能的?

在数字化时代&#xff0c;企业的发展也面临着转型&#xff0c;一方面是未知的挑战&#xff0c;一方面是不可多得的机遇。如何在全球市场中保持竞争力是企业要认真思考的问题。如果说主动寻找出路太过冒险&#xff0c;那不妨试试内省式的自我管理革新。代理服务器是一种中介服务…

TI DSP下载器XDS100 V2.0无法使用问题

前言 TI DSP下载器XDS100 V2.0用着用着会突然报Error&#xff0c;特别是你想要用Code Composer Studio烧录下载程序的时候 查看设备管理器&#xff0c;发现XDS100 V2.0的设备端口莫名其妙消失了 问了淘宝的厂家&#xff0c;他说TI的开发板信号可能会导致调试器通信信号中断&a…

软件安全最佳实践:首先关注的地方

尽管组织拥有大量可用的工具&#xff0c;但应用程序安全性仍然不足。 最近的数据显示&#xff0c;在过去四到五年中&#xff0c;软件供应链攻击同比增长了 600-700%&#xff0c;超过一半的美国企业在过去 12 个月中遭受过某种形式的软件供应链攻击。 为何应用程序安全工作未…

相亲交易系统源码详解与开发指南

随着互联网技术的发展&#xff0c;越来越多的传统行业开始寻求线上转型&#xff0c;其中就包括婚恋服务。传统的相亲方式已经不能满足现代人快节奏的生活需求&#xff0c;因此&#xff0c;开发一款基于Web的相亲交易系统显得尤为重要开发者h17711347205。本文将详细介绍如何使用…

WEB攻防-JavaWweb项目JWT身份攻击组件安全访问控制

知识点&#xff1a; 1、JavaWeb常见安全及代码逻辑&#xff1b; 2、目录遍历&身份验证&逻辑&JWT&#xff1b; 3、访问控制&安全组件&越权&三方组件&#xff1b; 演示案例&#xff1a; JavaWeb-WebGoat8靶场搭建使用 安全问题-目录遍历&身份认…

Ubuntu20.04 搜索不到任何蓝牙设备

电脑信息 联想扬天YangTianT4900k 问题描述 打开蓝牙之后&#xff0c;一直转圈&#xff0c;搜索不到任何蓝牙设备 排查 dmesg | grep -i blue 有如下错误&#xff1a; Bluetooth: hci0: RTL: unknown IC info, lmp subver 8852, hci rev 000b, hci ver 000b lsusb 芯片型号如…

imo云办公室 Imo_DownLoadUI.php 任意文件下载漏洞复现

0x01 漏洞描述&#xff1a; imo云办公室由上海易睦网络科技有限公司于2007年创立&#xff0c;总部位于上海&#xff0c;imo云办公室管理运营企业即时通讯平台imo&#xff0c;包括对imo的在线支持&#xff0c;故障处理&#xff0c;客户服务等&#xff0c;对imo进行持续研发&…

Nexpose 6.6.269 发布下载,新增功能概览

Nexpose 6.6.269 for Linux & Windows - 漏洞扫描 Rapid7 Vulnerability Management, release Sep 11, 2024 请访问原文链接&#xff1a;https://sysin.org/blog/nexpose-6/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.or…

web - JavaScript

JavaScript 1&#xff0c;JavaScript简介 JavaScript 是一门跨平台、面向对象的脚本语言&#xff0c;而Java语言也是跨平台的、面向对象的语言&#xff0c;只不过Java是编译语言&#xff0c;是需要编译成字节码文件才能运行的&#xff1b;JavaScript是脚本语言&#xff0c;不…

Mac 上哪个剪切板增强工具比较好用? 好用剪切板工具推荐

在日常文字编辑中&#xff0c;我们经常需要重复使用复制的内容。然而&#xff0c;新内容一旦复制&#xff0c;旧内容就会被覆盖。因此&#xff0c;选择一款易用高效的剪贴板工具成为了许多人的需求。本文整理了一些适用于 macOS 系统的优秀剪贴板增强工具&#xff0c;欢迎大家下…

人工智能-大语言模型-微调技术-LoRA及背后原理简介

1. 《LORA: LOW-RANK ADAPTATION OF LARGE LANGUAGE MODELS》 LORA: 大型语言模型的低秩适应 摘要&#xff1a; 随着大规模预训练模型的发展&#xff0c;全参数微调变得越来越不可行。本文提出了一种名为LoRA&#xff08;低秩适应&#xff09;的方法&#xff0c;通过在Transf…

用JS给官方电子课本扩展个下载功能

为了方便学生、老师和家长&#xff0c;官方提供了几乎所有在用的正版电子课本&#xff0c;由于没有下载功能&#xff0c;只能在线看&#xff0c;有点不方便。 为了更方便使用&#xff0c;用JS外挂了一个下载按钮。 扩展后效果如图&#xff1a; &#xff08;根据2022年版课程…

fastadmin 部署后前台会员中心出现404错误

访问前台会员中心出现404错误。 解决&#xff1a;nginx访问站点增加伪静态 location / {if (!-e $request_filename){rewrite ^(.*)$ /index.php?s$1 last; break;} }在phpstydy中增加伪静态&#xff0c;如图&#xff1a;