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

ops/2024/9/20 4:01:58/ 标签: Unity

 管理类:

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 Toolpublic 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 ToolGameObject itemGo = Instantiate(gridGo,transform.position,transform.rotation);
#endif#if Game//问工厂要资源的方法GameObject itemGo = GameController.Instance.GetGameObjectResource("Grid");
#endifitemGo.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.ppmy.cn/ops/113242.html

相关文章

MySQL 数据库与表的创建指南

MySQL 数据库与表的创建指南 在进行 MySQL 开发时&#xff0c;了解如何创建数据库和表是基础。本文将详细介绍如何通过 MySQL 的 SQL 语句创建数据库和表&#xff0c;并解释每个步骤中的关键点。 1. 什么是 MySQL&#xff1f; MySQL 是目前最流行的开源关系型数据库管理系统…

C++——string类

1.初识string string属于C标准库&#xff0c;而不属于STL&#xff0c;STL也属于C标准库 string是管理字符的顺序表&#xff0c;用来管理字符数组 string是模板&#xff0c;只是库直接给它typedef了&#xff0c;直接实例化了 string是动态开辟的字符数组&#xff0c;指向的空间在…

Mycat搭建分库分表

分库分表解决的问题 单表数据量过大带来的性能和存储容量的限制的问题&#xff1a; 索引效率下降读写瓶颈存储容量限制事务性能问题分库分表架构 再搭建一对主从复制节点&#xff0c;3307主节点&#xff0c;3309从节点配置数据源 dw1 , dr1,创建集群c1创建逻辑库 CREATE DATAB…

图书管理系统(面向对象的编程练习)

图书管理系统&#xff08;面向对象的编程练习&#xff09; 1.系统演示2.设计框架讲解3.代码的详细讲解3.1 多本书籍的实现3.2 不同操作人员的实现3.3 不同work操作的实现 1.系统演示 下面主要展示系统的删除图书功能和显示图书功能&#xff0c;帮助大家在开始写代码前先了解图…

85-MySQL怎么判断要不要加索引

在MySQL中&#xff0c;决定是否为表中的列添加索引通常基于查询性能的考量。以下是一些常见的情况和策略&#xff1a; 查询频繁且对性能有影响的列&#xff1a;如果某个列经常用于查询条件&#xff0c;且没有创建索引&#xff0c;查询性能可能会下降。 在WHERE、JOIN和ORDER B…

AI应用开发平台Dify本地Ubuntu环境部署结合内网穿透远程管理大模型

文章目录 前言1. Docker部署Dify2. 本地访问Dify3. Ubuntu安装Cpolar4. 配置公网地址5. 远程访问6. 固定Cpolar公网地址7. 固定地址访问 前言 本文主要介绍如何在Linux Ubuntu系统使用Docker快速部署大语言模型应用开发平台Dify,并结合cpolar内网穿透工具实现公网环境远程访问…

系统 IO

"裸奔"层次&#xff1a;不带操作系统的编程 APP(应用程序) -------------------------------- Hardware(硬件) 特点&#xff1a;简单&#xff0c;应用程序直接操作硬件(寄存器) 缺点&#xff1a; 1. 搞应用开发的必须要了解硬件的实现细节&#xff0c;能够看懂原理图…

【数据结构】十大经典排序算法总结与分析

文章目录 前言1. 十大经典排序算法分类2. 相关概念3. 十大经典算法总结4. 补充内容4.1 比较排序和非比较排序的区别4.2 稳定的算法就真的稳定了吗&#xff1f;4.3 稳定的意义4.4 时间复杂度的补充4.5 空间复杂度补充 结语 前言 排序算法是《数据结构与算法》中最基本的算法之一…

QtConcorrent学习、以及与QThread之间的联系

目录 一、QtConcorrent 概述 1、功能 2、特点 3、使用场景 4、QtConcurrent::run 5、应用示例 5、挑战和解决方案 6、QtConcurrent的重要性和价值 二、QFuture 1、主要特点和功能 2、应用示例 三、QtConcorrent与QThread 1、抽象级别和易用性 2. 线程管理和资源利…

C++速通LeetCode简单第6题-环形链表

快慢指针真的很好用&#xff01; /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode(int x) : val(x), next(NULL) {}* };*/ class Solution { public:bool hasCycle(ListNode *head) {//快慢指针ListNode* fast…

2024.9.19

[ABC266F] Well-defined Path Queries on a Namori 题面翻译 题目描述 给定一张有 N N N 个点、 N N N 条边的简单连通无向图和 Q Q Q 次询问&#xff0c;对于每次询问&#xff0c;给定 x i , y i x_i,y_i xi​,yi​&#xff0c;表示两点的编号&#xff0c;请你回答第 x i …

微信小程序开发第三课

1 wxml语法 1.1 模版语法 # 1 在页面 xx.js 的 Page() 方法的 data 对象中进行声明定义 # 2 在xx.wxml 中使用 {{}} 包裹&#xff0c;显示数据 # 3 可以显示如下&#xff0c;不能编写js语句或js方法-变量-算数运算-三元运算-逻辑判断# 4 只是单纯通过赋值&#xff0c;js中…

跨界融合,GIS如何赋能游戏商业——以《黑神话:悟空》为例

在数字化时代&#xff0c;地理信息系统&#xff08;GIS&#xff09;技术正以其独特的空间分析和可视化能力&#xff0c;为游戏产业带来革命性的变革。《黑神话&#xff1a;悟空》作为中国首款3A级别的动作角色扮演游戏&#xff0c;不仅在游戏设计和技术上取得了突破&#xff0c…

【华为杯】第二十一届中国研究生数学建模竞赛

“华为杯”第二十一届中国研究生数学建模竞赛即将开始&#xff0c;梦想科研社给大家整理一些比赛信息&#xff0c;在正式开赛后&#xff0c;我们也会持续分享一些课题的分析以及代码&#xff0c;有需要的可以联系我们获取资料信息哦 一、时间节点 1.加密赛题开始下载时间&…

大数据新视界 --大数据大厂之SaaS模式下的大数据应用:创新与变革

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

计算机三级网络技术总结(二)

RPR使用统计复用的方法传输IP分组IEEE802.16a用于固定结点接入ADSL技术为速率非对称型&#xff0c;上行速率为64kbps~640kbpsRAID是磁盘阵列技术在一定程度上可以提高磁盘存储容量但不能提高容错能力中继器工作在物理层VTP有三种工作模式:VTP Server、VTP Client 和VTP Transpa…

Spring4-IoC2-基于注解管理bean

目录 开启组件扫描 使用注解定义bean Autowired注入 场景一&#xff1a;属性注入 场景二&#xff1a;set注入 场景三&#xff1a;构造方法注入 场景四&#xff1a;形参注入 场景五&#xff1a;只有一个构造函数&#xff0c;无注解 场景六&#xff1a;Autowired和Quali…

通信工程学习:什么是HSS归属用户服务器

HSS&#xff1a;归属用户服务器 HSS&#xff08;归属用户服务器&#xff0c;Home Subscriber Server&#xff09;是IP多媒体子系统&#xff08;IMS&#xff09;中控制层的一个重要组成部分&#xff0c;它扮演着存储和管理用户相关信息的核心角色。以下是关于HSS归属用户服务器的…

计算机毕业设计选题推荐-校园车辆管理系统-Java/Python项目实战(亮点:数据可视化分析、账号锁定)

✨作者主页&#xff1a;IT研究室✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…

while循环及简单案例

//循环是流程控制中的一个重要分支 //流程控制 条件判断 循环 逻辑处理 //循环的目的和意义 //循环的目的是为了执行一块代码 //循环的意义是为了简化代码。增加代码的复用性 /* //例如输出0-100的数…