热乎的过万字GameFramework讲解笔记文档

news2025/1/12 20:47:05
往期文章分享
  • 点击跳转=>《导航贴》- Unity手册,系统实战学习
  • 点击跳转=>《导航贴》- Android手册,重温移动开发

本文约15千字,新手阅读需要27分钟,复习需要12分钟收藏随时查阅不再迷路

👉关于作者

众所周知,人生是一个漫长的流程,不断克服困难,不断反思前进的过程。在这个过程中会产生很多对于人生的质疑和思考,于是我决定将自己的思考,经验和故事全部分享出来,以此寻找共鸣 !!!
专注于Android/Unity和各种游戏开发技巧,以及各种资源分享(网站、工具、素材、源码、游戏等)
有什么需要欢迎私我,交流群让学习不再孤单

在这里插入图片描述

👉前提

这是小空坚持写的Unity新手向系列,欢迎品尝。

小空为了方便更多的人(新手)看明白,使用的汉字,真实项目尽量使用英文规则昂。

新手(√√√)

大佬(√)

这段时间学习个Unity框架并且准备应用到实际项目中,但是因为作者神龙见首不见尾,没有什么比较详细的文档,学习困难,不过好在作者将框架所有内容开源了,再次记录下学习过程。

👉实践过程

😜Game Framework简介导读

:她到底是个什么玩意?
:Game Framework 是一个基于 Unity 引擎的游戏框架,主要对游戏开发过程中常用模块进行了封装,很大程度地规范开发过程、加快开发速度并保证产品质量。
支持5.3以上到现在所有的Unity版本。
:那她到底有什么功能呢?
:相当多哦,包含全局配置,日志等工具集,数据表维护,提示器,下载,事件,文件系统,有限状态机,本地化,网络,对象池,流程,资源管理,场景管理,游戏配置,声音,界面,Web请求。-详情参见文末功能备注(链接)
:她能帮助我什么?
:帮你快速开发项目以及搭建良好的产品框架,顺便提高自己的业务能力。
:那应该怎么找到她,学习她呢?
:Github地址- https://github.com/EllanJiang/GameFramework/
API手册- https://gameframework.cn/api/

😜初识Game Framework

完整的 Game Framework 内容包含三部分:

  • GameFramework – 封装基础游戏逻辑,如数据管理、资源管理、文件系统、对象池、有限状态机、本地化、事件、实体、网络、界面、声音等,此部分逻辑实现不依赖于 Unity 引擎,以程序集的形式提供。

  • UnityGameFramework.Runtime – 依赖 UnityEngine.dll 进行对 GameFramework.dll 的补充实现。为了方便兼容 Unity 的各个版本,此部分已经以代码的形式包含在 Unity 插件中。

  • UnityGameFramework.Editor – 依赖 UnityEditor.dll 进行对工具、Inspector 的实现。为了方便兼容 Unity 的各个版本,此部分已经以代码的形式包含在 Unity 插件中。

我们直接从官网下载unitypackage插件包,我的是2020.7.30版本。导入后如下图:
image.png
image.png

😜如何使用?

工程目录及作用如下:
image.png

  • Libraries 存放 GameFramework.dll 核心框架和一些框架必需的第三方库(当前只有一个开源 zip 压缩算法库)
  • Prefabs 存放 GameFramework.prefab 预制体,用于快速创建一个游戏框架启动场景
  • Scripts 存放 UnityGameFramework 的全部 Runtime 和 Editor 代码
  • Example.unity 是一个含有 GameFramework.prefab 预制体的空场景,作为游戏启动的场景
  • ProcedureExample.cs 是一个示例流程代码文件,示例将以这个流程作为启动流程。

运行项目后发现Game场景有个浮动小窗口,这是框架提供的调试器窗口
image.png

  • Console 选项卡在运行时(当然可以在移动设备上)默认按不同日志类型,以不同的日志颜色回显最近的日志。点击某条日志可以查看详细的日志和堆栈详请
  • Information 选项卡显示设备硬件信息、游戏版本和资源信息,输入信息,传感器等
  • Profiler 选项卡显示性能调试相关的信息,内存,对象池,网络等信息
  • Other 选项卡可以用来配置调试框窗口的大小缩放(一般不用修改)、执行内存回收操作或者执行重启游戏操作等

作者英语不是很好,为了用起来快捷将里面部分英文翻译成了中文,看起来确实顺畅多了,哈哈
image.png

😜场景

我们先把从官方下载的.unitypackage包导入,然后新建一个场景对应新建一个脚本。

然后打开GameFramework/Prefabs目录,将里面的GameFramework预制体拖到Hierarchy视图里(预制体里面包含了多种基本组件)
image.png
接着打开【ScriptSceneStart】脚本,让她继承自【ProcedureBase】,看过案例教程后我们知道框架是用流程来管理的,所以我们的场景第一步就要继承【ProcedureBase】,让她成为流程。
image.png
之后我们将场景和框架中的流程绑定起来。
image.png
然后打开框架日志,运行程序即可看到效果
image.png
注:Unity已经有打印日志的工具了,为什么我们还要用框架中的呢。

因为我们不仅仅需要在编译器中查看,有时候发布出去后在其他平台或设备上查看日志就需要你自己写一套日志方案(这多不符合懒的思想啊)。既然框架提供了这些,为什么不用呢?现成的他不香吗?
image.png
难道我们游戏只有一个场景吗?不存在的,必然是多个场景存在,那多个场景在框架中又怎么切换呢?或者说怎么切换流程呢?

我们再新建个场景【Scene_Set】,脚本为【ScriptSceneSet
image.png
运行场景【Scene_Start】后直接切换场景到【Scene_Set】,但是你会发现场景【Scene_Start】没有卸载
image.png
原因在于基础场景里挂载着框架的组件【GameFramework】,你用人家的框架,还想干掉人家的框架,开玩笑呢?销毁了你还框什么架,所以这个场景在整个程序运行过程中不销毁的。

除了这个普通的场景加载后或者切换场景后,发现也没销毁,原因是框架不会自动销毁,需要你主动销毁。

使用Scene.GetLoadedSceneAssetNames();可以获得加载的场景数组

Scene.UnloadScene(“场景资源名称”);来卸载,当然了框架会自动排除上面说的挂载着框架的场景

有一点要记得,切换场景的时候Scene.LoadScene(“这需要完整的路径和后缀名”,this);

思路接着往下走,场景切换后我们对应的控制和逻辑脚本也就应该切换到对应的了,所以我试了试:
image.png
就这张图的代码来看,切换场景后,下一个场景也有打印日志消息,但是实际的运行结果却没有,这令小空疑惑。而且去检查了流程组件的内容,都打对勾了。
image.png
等等,流程!既然是流程,那是不是得自己控制流程的切换,框架将场景切换和流程切换分开,留给开发人员实现,岂不有更多的实现空间?然后小空去翻找官方案例,果然有个继承自【ProcedureBase】的【ProcedureChangeScene】类,往下翻找到了关键句【ChangeState(procedureOwner);】,关键字【ChangeState】这个必定是切换流程的,至于切换到哪个就需要在<>符号里写进去了。回去改小空的Demo:
image.png
运行后:(成功,果然Nice,框架方便之处渐渐浮出)
image.png

😜UI

经过上一节搞定了场景,接着就要开搞UI了,UI也不是直接就在场景中全部展示出来了,有些需要我们动态从资源中加载。
我直接上个步骤图,看的更形象一些。

  1. 代码中用UIComponent组件加载UI预制体,重点注意第二个参数,将UI进行了分组和层级管理
  2. 回到编辑器中找到GameFramework-UI物体,里面有个UI Groups属性要设置
  3. 预制体需要挂载脚本,脚本需要继承UIFormLogic脚本,这是UI控制脚本,这样才能交给框架进行管理

image.png

这一套下来,真的是如行云流水般顺畅,越来越方便了。继续学习看看框架到底还有多少惊喜。
1A144D0E.jpg

顺畅个屁啊,小空又跑回来更新了,学到后面发现怎么UI也出不来,哎,就是跟你玩,就是不出。不小心踩了个坑。

UI,UI,都说了是UI,我竟然没搞Cnavas,糊涂啊。根据上图步骤,第三步预制体是你布局好UI控件然后将整个Canvas做成预制体。成功后是这样的(下图):
image.png
还有一点要留意,运行后你会发现在场景里并没有找到UI组件,其实不然,框架通过UIComponent 创建的的UI 统统都会跑到Framework 里面 UI下面。无论你打开几个场景UI始终都是在框架所在场景内的。
image.png
如上图所示,全部在【UI-UI Form Instances】下

😜日志管理工具

在任何编程语言中,日志都是重中之重,是逻辑分析的首要工具,所以我们首要任务就是要学会使用框架的日志工具。

首先是基础的Log日志(如图),和系统的一样输出到Unity编辑器的控制台
image.png
发布的产品,最好关闭所有日志或者仅开启错误及以上级别日志,自己开发调试的时候可以自定义开启日志级别。
image.png
除了在控制台打印,我们使用框架更多的可能是将日志保存到文件的功能。

自定义一个类继承DefaultLogHelper

using GameFramework;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEngine;
using UnityGameFramework.Runtime;
 
internal class FileLogHelper : DefaultLogHelper
{
//设置日志文件保存路径-你可以自定义,也可以使用系统的
private readonly string CurrentLogPath = Utility.Path.GetRegularPath(Path.Combine(Application.persistentDataPath, "current.log"));
private readonly string PreviousLogPath = Utility.Path.GetRegularPath(Path.Combine(Application.persistentDataPath, "previous.log"));
public FileLogHelper()
{
    Application.logMessageReceived += OnLogMessageReceived;
    try
    {
        //每次运行的时候将日志替换,就像队列一样
        if (File.Exists(PreviousLogPath))
        {
            File.Delete(PreviousLogPath);
        }
        if (File.Exists(CurrentLogPath))
        {
            File.Move(CurrentLogPath, PreviousLogPath);
        }
    }
    catch
    {
    }
}
 
    private void OnLogMessageReceived(string logMessage, string stackTrace, LogType logType)
    {
        string log = Utility.Text.Format("[{0}][{1}] {2}{4}{3}{4}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"), logType.ToString(), logMessage ?? "<Empty Message>", stackTrace ?? "<Empty StackTrace>", Environment.NewLine);
        try
        {
            File.AppendAllText(CurrentLogPath, log, Encoding.UTF8);
        }
        catch
        {
        }
    }
}

然后在挂在了Base脚本的物体中选择使用即可,就这么简单!!!
image.png
运行的时候,也可以在调试器窗口中找到各个路径位置。
image.png

😜事件订阅

既然咱要用她就一定要先说说她的优点:

她简化了组件间的通信,分离了事件的发送者和接收者,大大降低了耦合度。举个栗子:
image.png
前段时间的【黑悟空】实机演示,比如悟空的状态,经验值,怪物的血量等内容,会随时有着对应的变化,比如怪物死亡,人物获得经验以及结束判断等等,一次事件发生N多事件要对应变化,要是一个个主动修改你调我/我调你的,调来调去逻辑线不混乱才怪,又不玩捆绑S。所以我们要由主动变被动,我发个广播,谁想听我号令谁就注册下,不想听你不注册没影响,解耦效果显著。小空是Android出身,Android里的EventBus订阅用的贼爽,所以第一时间就学习了这个框架的订阅事件

这就达到了,某件事件变化,执行了注册的地方会收到消息,自己处理自己的逻辑。被订阅者发,多个订阅者接收。

来来来,我们看看到底怎么使用;
image.png

😜第一步

需要先获得Event组件

EventComponent eventComponent = UnityGameFramework.Runtime.GameEntry.GetComponent();

😜第二步

订阅事件

eventComponent.Subscribe(OpenUIFormSuccessEventArgs.EventId, InitUISuccess);

订阅事件第一个参数是内置的,【OpenUIFormSuccessEventArgs】是初始化打开界面成功事件,第二个参数是你自己声明的函数,界面完成后会触发这个函数。官方还有更多内置函数,详情看下方表格图。

😜第三步

加载UI
image.png

😜第四步

在回调函数中打印下,看看有没有接收到消息。
image.png

😜第五步

记得在OnLeave方法解除注册昂。你都离开这个流程了,就不要再费心去监听别的事情了。否则会造成内存垃圾昂。
运行结果:
image.png
成了。就这么简单?爱作妖的小空这时候又有想法了:实际开发不可能这么简单,可能有N多个UI,N多个时间,这要是多了又是什么样的?不急,接着试验
image.png
一运行发现哎都回调了方法啊。这个不错,如果再利用第四个参数传递自定义数据,返回后根据不同的数据做不同的处理岂不快哉。
image.png
666,但是还有个疑问,仔细看上面【OpenUIForm】里面的第三个参数-优先级,我尝试输入不同的级别运行后发现并没有想象中的那样【这是一只猫】最先执行。小空就去赶紧看了官方案例,又有发现:官方案例区分的是资源优先级-字体、声音音乐/场景等这种大类别。应该不是用于小小的同级(比如都是UI)。这个留待后续再深入。
image.png
小空学到这感觉基本使用可以了,这和Android的EventBus类似啊,在以后的实践学习中希望能发现框架也有EventBus的粘性事件和跨组件监听。补充一个框架内置组件图:
image.png
怎么样?使用起来是不是很简单?仿佛在那遥远的山村听到了有人说,
image.png

😜创建实体

经历前面文章创建UI的过程,这一步操作起来就顺心多了,坑也少了。

😜第一步

同样需要创建预制体(物体模型)
image.png

😜第二步

预制体上需要挂载继承了【EntityLogic】的脚本
image.png

😜第三步

走走走,预制体出来我们就要开始创建了,代码先获取实体组件再创建实体
image.png
这和UI基本如出一辙昂,再回忆回忆和UI都是预制体,传递的参数都是预制体路径和分组。等等-分组,差点忘记了需要在框架的基础组件中添加分组

小空在学习木头前辈的教程中留意到:这种带有路径的预制体加载方式,实际打包后会不会出现调用不到的问题。给出的答案是:不管是打不打包,框架都会处理好,无需操心。

第四个参数需要注意下,她可以传递【this】,进而在控制中调用流程中的方法。

官网案例也是这么做的:【ProcedureMenu】流程打开UI【GameEntry.UI.OpenUIForm(UIFormId.MenuForm, this);】传递的是【this】,进而【MenuForm】中可以在【OnOpen】方法获取这个流程类【m_ProcedureMenu = (ProcedureMenu)userData;】,这样就可以调用流程中的方法,比如切换另一个流程,事实上官网也是这么做的。

😜第四步

分组机制管理器很多物体超级方便,不可缺少
image.png
组里面还有四个参数,小空暂时还没学到这些,保留知识。

instance auto release inerval】-实例自动释放间隔

instance auto release inerval】-实例容量

instance expire time】-实例过期/失效时间

instance priority】-实例优先级

😜第五步

运行成功
image.png
在这强调下,时刻要记得创建的东西都是在【GameFramework】框架组件下。

😜第六步

操作起来怎么这么顺利,就没遇到个让人劈叉的问题?

小空还真疏忽了,在UI中就说过创建后一定要在框架下写上分组,在这小空又忘了,报错如下:不过小空现在已经记住了,时刻保持组名和代码中的参数保持一致。
image.png
image.png

在这进了一个坑(不承认我学艺不精),找搞C++的姐请教后实践,详情请看文章:

快速代码补全-不同关键字权限,不同程序集自动生成的有微差别

补充:当一个物体有灯光信息的话,不适合做成预制体,这会导致从预制体初始化出来的物体效果不对。

原因是:在一个物体或者光源从场景中变成一个prefab的时候,那些和烘焙相关的信息被重置,是一个稳妥的做法,因为你做成一个prefab,意味着它可能被使用于不同场景,那残留的之前的烘焙信息也就没有意义了。反过来说,如果保留,你在别的场景中apply了这些信息,那其他场景的效果就错了。无法通用的信息,保留在prefab中,是危险的。

烘焙信息是跟着场景走的,如果一个物体或者光源和场景没有关联了,那它身上存储的烘焙信息也就没有意义了。

所以推荐布置在场景中,用切换流程切换场景来实现,普通的物体可以设置成预制体。官方案例也是这么搞的。

👉其他

📢作者:小空和小芝中的小空
📢转载说明-务必注明来源:https://zhima.blog.csdn.net/
📢这位道友请留步☁️,我观你气度不凡,谈吐间隐隐有王者霸气💚,日后定有一番大作为📝!!!旁边有点赞👍收藏🌟今日传你,点了吧,未来你成功☀️,我分文不取,若不成功⚡️,也好回来找我。

温馨提示点击下方卡片获取更多意想不到的资源。
空名先生

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

YOLOv5改进系列(5)——替换主干网络之 MobileNetV3

【YOLOv5改进系列】前期回顾: YOLOv5改进系列(0)——重要性能指标与训练结果评价及分析 YOLOv5改进系列(1)——添加SE注意力机制 YOLOv5改进系列(2&#

【数据结构与算法篇】栈与队列(详解)附加Leetcode经典笔试题

​&#x1f47b;内容专栏&#xff1a;《数据结构与算法专栏》 &#x1f428;本文概括&#xff1a; 讲述数据结构栈与队列基本知识。 &#x1f43c;本文作者&#xff1a;花 碟 &#x1f438;发布时间&#xff1a;2023.5.23 文章目录 一、栈1.栈的概念及结构2.栈的实现 二、有效的…

C++中的函数模板

目录 1. 什么是函数模板&#xff1f; 2. 如何定义函数模板&#xff1f; 3. 如何使用函数模板&#xff1f; 4. 函数模板与函数重载的区别是什么&#xff1f; 5. 函数模板与类模板有何异同点&#xff1f; 1. 什么是函数模板&#xff1f; - 函数模板是一种通用的函数描述&…

STM32的SPI外设

文章目录 1. STM32 的 SPI 外设简介2. STM32 的 SPI 架构剖析2.1 通讯引脚2.2 时钟控制逻辑2.3 数据控制逻辑2.4 整体控制逻辑 3. 通讯过程4. SPI 初始化结构体详解 1. STM32 的 SPI 外设简介 STM32 的 SPI 外设可用作通讯的主机及从机&#xff0c;支持最高的 SCK 时钟频率为 …

语义分割实战项目(从原理到代码环境配置)

MMsegmentation是一个基于PyTorch的图像分割工具库,它提供了多种分割算法的实现,包括语义分割、实例分割、轮廓分割等。MMsegmentation的目标是提供一个易于使用、高效、灵活且可扩展的平台,以便开发者可以轻松地使用最先进的分割算法进行研究和开发。 看下结果 MMsegmenta…

安卓基础巩固(三)多线程、IO操作、数据存储

文章目录 多线程Handler相关概念UI线程/主线程MessageMessage QueueLooperHandler 使用步骤Handler.sendMessage&#xff08;&#xff09;Handler.post&#xff08;&#xff09; Handler 机制工作原理Handler内存泄露前置知识案例分析解决方案一&#xff1a;静态内部类弱引用解…

day09 MyBatis基础操作

为什么使用框架 框架的作用:可以直接调用写好的API,提高开发效率,框架是一种经过校验,有一定功能的半成品软件 为什么选择mybatis框架 它几乎避免了所有的JDBC的代码和手动设置参数及获取结果集.作用于持久层,支持定制化sql,存储过程及高级映射 项目所需要的jar包: lombok…

PowerShell系列(四):PowerShell进入交互环境的三种方式

目录 1、Win键X 方式 2、使用微软自带的搜索功能 3、命令行运行方式 4、命令行窗口方式 5、使用第三方命令行软件&#xff08;Terminal&#xff09;开启PowerShell环境 6、PowerShell交互环境执行脚本的一些优势 7、小技巧 今天继续给大家讲解PowerShell相关的知识&…

IMX6ULL裸机篇之DDR3实验-更新 imxdownload.h

一. DDR实验 之前关于 IMX6ULL开发板&#xff0c;有关DDR实验。做了DDR内存芯片的初始化&#xff0c;校验与超频测试。 博文链接如下&#xff1a; IMX6ULL裸机篇之DDR3初始化_凌雪舞的博客-CSDN博客 IMX6ULL裸机篇之DDR3校验与超频测试_凌雪舞的博客-CSDN博客 经过了初始化…

C Primer Plus第二章编程练习答案

学完C语言之后&#xff0c;我就去阅读《C Primer Plus》这本经典的C语言书籍&#xff0c;对每一章的编程练习题都做了相关的解答&#xff0c;仅仅代表着我个人的解答思路&#xff0c;如有错误&#xff0c;请各位大佬帮忙点出&#xff01; 1.编写一个程序&#xff0c;调用一次 …

【Linux系列P3】Linux的权限有什么重点?一文带你理清!

前言 大家好&#xff0c;这里是YY的Linux系列part3&#xff1b;本章主要内容面向能使用Linux的老铁&#xff0c;主要内容是【Linux的用户&用户指令】【文件属性】【权限&权限值的两者表达方式】【权限相关指令】【起始权限问题与掩码问题】【粘滞位的概念与特殊权限-t解…

[Ext JS3.9] 标签面板(TabPanel )介绍与开发

标签面板 标签面板是RIA 类应用使用较多的组件, 因为其可以显示的内容比较多。 标签面板的效果如下图: 标签面板开发也很简单, 配置式的开发代码类似: {xtype: tabpanel,items: [{title: 标签页1,html:标签页1内容}, {title: 标签页2,html:标签页2内容}, {title: 标签页…

【教学类-34-05】拼图(数字学号0X-长方块拼图-双色深灰浅灰)3*3格子(中班主题《个别化拼图》偏艺术-美术)

作品展示 背景需求 难点&#xff1a;如何让生成图片带两个颜色的数字&#xff1f; 上一次学习活动中&#xff0c;发现03、04、05、06、08、09 、 23、26、28拼图都有困境&#xff0c;教师帮助。这些数字都包含圆弧结构&#xff0c;幼儿对于大量的圆弧碎片图形的多重组合&…

【Java-Crawler】一文学会使用WebMagic爬虫框架

WebMagic 爬虫主要分为采集、处理、存储三个部分。 在学 WebMagic 框架之前&#xff0c;需要了解 HttpClient、Jsoup&#xff08;Java HTML Parse&#xff09; 库&#xff0c;或者说会他们的基本使用。因为 WebMagic 框架内部运用了他们&#xff0c;在你出现问题看源码去查错时…

MySQL主从复制配置

一、MySQL主从概念 MysSQL主从复制是一个异步的复制过程&#xff0c;底层是基于Mysql数据库自带的二进制日志功能。就是一台或多台AysQL数据库(slave&#xff0c;即从库&#xff09;从另一台MysQL数据库(master&#xff0c;即主库&#xff09;进行日志的复制然后再解析日志并应…

一、尚医通排班管理

文章目录 一、排班管理1、页面效果2、接口分析3、实现分析 二、排班管理实现1、科室列表1.1 api接口1.1.1 添加service接口与实现1.1.2 添加controller接口 1.2 科室前端1.2.1 添加路由1.2.2 添加按钮1.2.3封装api请求1.2.4 部门展示 2、排班日期分页列表2.1 api接口2.1.1 添加…

Net跨平台UI框架Avalonia入门-DataGrid的使用

Avalonia中的DataGrid的使用 DataGrid 数据表格是客户端UI中很重要的一个控件&#xff0c;Avalonia中的DataGrid是单独一个包Avalonia.Controls.DataGrid&#xff0c;要使用DataGrid&#xff0c;需要另外在Nuget中按这个包&#xff0c;下面介绍一下DataGrid的安装和使用 Data…

android/ios 一键抽取硬编码字符串

由于老项目 做国际化困难,抽取繁琐 最终实在蛋疼 最终开放插件来解决 android studio 插件 一键抽取硬编码字符串 xcode 一键抽取硬编码字符串 环境配置android studio ,appcode idea 环境类似1.安装插件 插件下载点击 2. 配置生成文件路径 android 就是string.xml ios Loca…

搭建stm32电机控制代码框架(一)

也是挑战一下自己吧&#xff0c;看看多久能够把自己的代码框架搭建起来&#xff0c;今天是5月23日&#xff0c;看看最终搭建成功的时候是什么时候&#xff0c;目标其实这个阶段很简单&#xff0c;电机转一个双闭环FOC就行。 这次的任务是基于stm32f405芯片进行展开&#xff0c…

STM32单片机(一)STM32简介

❤️ 专栏简介&#xff1a;本专栏记录了从零学习单片机的过程&#xff0c;其中包括51单片机和STM32单片机两部分&#xff1b;建议先学习51单片机&#xff0c;其是STM32等高级单片机的基础&#xff1b;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 &#xff1a;适用于想要…