Godot.NET C# 工程化开发(1):通用Nuget 导入+ 模板文件导出,包含随机数生成,日志管理,数据库连接等功能
文章目录
- 前言
- Github项目地址,包含模板文件
- 后期思考补充
- 项目设置
- 编写失误
- 环境
- visual studio 配置
- 详细的配置看我这篇文章
- Nuget 推荐
- NewtonSoft 成功
- Bogus 成功
- Github文档地址
- 随机生成
- 构造器生成
- 构造器+接口(推荐)
- 文件夹设置
- Nlog 成功!
- Nlog.config
- NlogHelper.cs
- Nloghelper使用
- 测试
- FreeSql 以Sqlite为例
- FreeSql官方文档
- sqlite3 安装,CodeFrist则不需要安装。我这里用CodeFrist
- 生成Sqlite数据库文件,这里我取名为sqliteDb.db
- Nuget引入,FreeSql核心和FreeSql的Sqlite支持
- FreeSqlHelper CodeFrist模式
- T_ModelBase 数据库基类+Bogus随机生成
- T_Person,数据库插入类,我习惯用T开头带表数据库实体
- 连接,插入,查询测试使用
- GD_Extension项目打包,用于复用
- Icon封面准备
- visual studio 导出
- Github项目地址,包含模板文件
- 总结
前言
我们学编程,不要重复造工具。我之所以使用C# 开发Godot ,而不是Unity。很大的原因就是Godot.NET 支持Nuget的导入,因为Nuget是.NET Core 的第三方库。我也将Godot 的Visual Studio 项目的.NET 版本强制升级到的.NET Core 8.0版本,目前还没有任何问题。
Github项目地址,包含模板文件
Gclove2000/GodotNet_Csharp_IOC_SimpleTemplate
后期思考补充
我将项目分成3层,从上到下是
- Godot:只是单纯挂载脚本
- GD_Program:负责游戏逻辑
- GD_Extension:通用的工具类
但是我后面想了一下,游戏逻辑也有部分是可以通用的,所以我感觉我的三层构造应该是存在过度封装了。两层封装说不定好一些。我后面打算先用两层封装好一点。等后面项目复杂度上来之后,再细分好了。
项目设置
编写失误
我写到后面的时候发现,Interfaces应当放在GD_Extension中。读者记得修改

环境
- window 10
- .net core 8.0
- godot 4.2.1
- visual studio 2022
visual studio 配置
- GD_Extesion:Godot工具类,后面用于导出
- Assests:资源文件夹
- Utils:工具类
- Interfaces:接口类
- GD_Program:Godot运行逻辑
- SceneModels:场景脚本实际运行类,IOC装配生成
- Services:服务类
- Program.cs:IOC容器位置
- Godot:Godot引擎生成解决方案
- Scene:挂载脚本,只用于建立脚本连接关系

详细的配置看我这篇文章
Godot 学习笔记(5):彻底的项目工程化,解决GodotProjectDir is null+工程化范例
Nuget 推荐
| Nuget | 介绍 |
|---|---|
| Newtonsoft.Json | 高性能Json序列化库 |
| Bogus | 随机测试数据生成,比如随机数据,随机人民,地名,手机号,账号,密码 |
| Microsoft.Extensions.DependencyInjection | 微软IOC框架,个人推荐 |
| Autofac | 第三方IOC 框架,性能也不错 |
| Nlog | 日志管理 |
| FreeSql | 数据库ORM框架,个人推荐 |
| SqlSugar | 数据库ORM框架,一般来说够用了,游戏开发也不是高频并发操作 |
| MiniExcel | Excel ORM框架,简易操作。建议使用CSV |
| Microsoft.AspNetCore.SignalR.Common | 微软开发即时通讯框架,用于解决多人联网 |
| Grpc | 谷歌开发的即使通讯框架,用于解决多人联网 |
NewtonSoft 成功

//以匿名对象为例
GD.Print(JsonConvert.SerializeObject(new
{Name = "小王",Age = "24"
}));

Bogus 成功

Github文档地址
Bugous Github文档地址

随机生成
//以随机数为例
var faker = new Faker();
for(var i = 0; i < 10; i++)
{GD.Print($"Bogus,int 0-10:[{faker.Random.Int(0, 10)}]");
}

构造器生成
public class MyStudent
{public int Id { get; set; }public string? Name { get; set; }public int Age { get; set; }/// <summary>/// 构建faker构造器/// </summary>public static Faker<MyStudent> Faker = new Faker<MyStudent>().RuleFor(t=>t.Id,f=>f.IndexFaker).RuleFor(t=>t.Name,f=>f.Name.FindName()).RuleFor(t=>t.Age,f=>f.Random.Int(10,30));}
//以构造器为例
for (var i = 0; i < 10; i++)
{var stu = MyStudent.Faker.Generate();GD.Print($"Bogus:[{JsonConvert.SerializeObject(stu)}]");
}

构造器+接口(推荐)
个人建议,上个接口,更规范一点
public interface IModelFaker<T> where T : class
{public T FakerOne();public IEnumerable<T> FakeMany(int num);
}
public class MyStudent : IModelFaker<MyStudent>
{public int Id { get; set; }public string? Name { get; set; }public int Age { get; set; }/// <summary>/// 构建faker构造器/// </summary>private Faker<MyStudent> faker = new Faker<MyStudent>().RuleFor(t => t.Id, f => f.IndexFaker).RuleFor(t => t.Name, f => f.Name.FindName()).RuleFor(t => t.Age, f => f.Random.Int(10, 30));public MyStudent FakerOne(){return faker.Generate();}public IEnumerable<MyStudent> FakeMany(int num){return faker.Generate(num);}
}
文件夹设置
因为后面会涉及到文件夹的设置问题,我这里简单说明一下

添加配置

Visual Studio C# 项目生成时复制项目资源目录到生成目录
Nlog 成功!

Nlog.config
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ><targets><!--将Debug导出为每小时一个--><target name="debug"xsi:type="File"fileName="${basedir}/Logs/${date:format=yyyy}/${date:format=MM}/${date:format=dd}/${date:format=HH}.log"layout="${date:format=yyyy-MM-dd HH\:mm\:ss} [${uppercase:${level}}] : ${message}" /><!--将Error导出为每天一个,而且存放在一个Error文件夹中--><target name="error"xsi:type="File"fileName="${basedir}/Logs/${date:format=yyyy}/${date:format=MM}/Error/${date:format=dd}.log"layout="${date:format=yyyy-MM-dd HH\:mm\:ss} [${uppercase:${level}}] : ${message}" /></targets><rules><logger name="*"minlevel="Debug"writeTo="debug" /><logger name="*"minlevel="Error"writeTo="error" /></rules>
</nlog>
NlogHelper.cs
Godot的输出比较特别,需要特别处理一下
public class NlogHelper
{private Logger logger;public NlogHelper(){var url = string.Format("{0}Assests/NLog.config", AppDomain.CurrentDomain.BaseDirectory.ToString());GD.Print($"Nlog加载完毕,url地址为[{url}]");LogManager.Configuration = new XmlLoggingConfiguration(url);logger = NLog.LogManager.GetCurrentClassLogger();}public void Debug(string msg){GD.Print(msg);logger.Debug(msg);}public void Info(string msg){GD.Print($"[info]:{msg}");logger.Info(msg);}public void Error(string msg){GD.PrintErr(msg);GD.PushError(msg);logger.Error(msg);}public void Warning(string msg){GD.Print($"[warning]:{msg}");GD.PushWarning(msg);logger.Warn(msg);}
}
Nloghelper使用


测试
nlogHelper.Debug("Debug");
nlogHelper.Info("Info");
nlogHelper.Warning("Warning");
nlogHelper.Error("Error");




FreeSql 以Sqlite为例
FreeSql官方文档
FreeSql官方文档

sqlite3 安装,CodeFrist则不需要安装。我这里用CodeFrist
SQLite 安装
生成Sqlite数据库文件,这里我取名为sqliteDb.db
sqlite3 sqliteDb.db
.open sqliteDb.db

Nuget引入,FreeSql核心和FreeSql的Sqlite支持


FreeSqlHelper CodeFrist模式
C# FreeSql使用,基于Sqlite的DB Frist和Code First测试
T_ModelBase 数据库基类+Bogus随机生成
/// <summary>
/// 基类
/// </summary>
public abstract class T_ModelBase
{/// <summary>/// 主键自增/// </summary>[Column(IsPrimary =true,IsIdentity =true)]public long Id { get; set; }/// <summary>/// 创建时间/// </summary>public DateTime CreateTime { get; set; } = DateTime.Now;/// <summary>/// 更新时间/// </summary>public DateTime UpdateTime { get; set; } = DateTime.Now;/// <summary>/// 假删除/// </summary>public bool IsDelete { get; set; } = false;public DateTime DeleteTime { get; set; }
}
T_Person,数据库插入类,我习惯用T开头带表数据库实体
public class T_Person : T_ModelBase, IModelFaker<T_Person>
{public int Age { get; set; }public string Name { get; set; }private Faker<T_Person> faker = new Faker<T_Person>().RuleFor(t => t.Id, f => f.IndexFaker).RuleFor(t => t.CreateTime, f => f.Date.Between(new DateTime(2024, 1, 1), DateTime.Now)).RuleFor(t => t.Name, f => f.Name.FindName()).RuleFor(t => t.Age, f => f.Random.Int(10, 30));public IEnumerable<T_Person> FakeMany(int num){return faker.Generate(num);}public T_Person FakerOne(){return faker.Generate();}
}
连接,插入,查询测试使用
var isConnect = freeSqlHelper.SqliteDb.Ado.ExecuteConnectTest(10);
GD.Print($"数据库连接状态:[{isConnect}]");var insertLists = new T_Person().FakeMany(10);var insertName = freeSqlHelper.SqliteDb.Insert(insertLists).ExecuteAffrows();
GD.Print($"数据库插入[{insertName}]行数据");var selectLists = freeSqlHelper.SqliteDb.Queryable<T_Person>().OrderByDescending(t=>t.Id).Take(10).ToList();foreach (var item in selectLists)
{GD.Print(JsonConvert.SerializeObject(item));
}


GD_Extension项目打包,用于复用
我写到后面的时候发现,Interfaces应当放在GD_Extension中。读者记得修改

Icon封面准备
【VisualStudio 】VisualStudio2022 项目模板
准备一个Godot Icon的图片,用于封面展示

visual studio 导出







Github项目地址,包含模板文件
Gclove2000/GodotNet_Csharp_IOC_SimpleTemplate
总结
我这里就是简单引入了几个通用的Nuget,这个我后期是会日常去维护的。这个就是我们的脚手架了。而且我在GD_Extension中尽量少的使用Godot的Api。基本只使用了Godot Api 的输出语句。所以这个随着Godot 版本的更新,基本不需要大改。这个以后就是我们宝贵的Godot资源库了。
相关文章:
Godot.NET C# 工程化开发(1):通用Nuget 导入+ 模板文件导出,包含随机数生成,日志管理,数据库连接等功能
文章目录 前言Github项目地址,包含模板文件后期思考补充项目设置编写失误环境visual studio 配置详细的配置看我这篇文章 Nuget 推荐NewtonSoft 成功Bogus 成功Github文档地址随机生成构造器生成构造器接口(推荐) 文件夹设置Nlog 成功!Nlog.configNlogHe…...
数据仓库——雪花模式以及层次递归
层次结构 钻取 向下钻取:对某些代表事实的报表中添加维度细节 向上钻取:从某些代表事实的报表中去除维度细节 属性层次 提供了一种自然方法,用于顺序地在不断深入的层次上组织事实。许多维度可以被理解为包含连续主从关系的属性层次。此类…...
Transformer的前世今生 day09(Transformer的框架概述)
前情提要 编码器-解码器结构 如果将一个模型分为两块:编码器和解码器那么编码器-解码器结构为:编码器负责处理输入,解码器负责生成输出流程:我们先将输入送入编码器层,得到一个中间状态state,并送入解码器…...
Qt 压缩/解压文件
前面讲了很多Qt的文件操作,文件操作自然就包括压缩与解压缩文件了,正好最近项目里要用到压缩以及解压缩文件,所以就研究了一下Qt如何压缩与解压缩文件。 QZipReader/QZipWriter QZipReader 和 QZipWriter 类提供了用于读取和写入 ZIP 格式文…...
【leetcode刷题之路】面试经典150题(8)——位运算+数学+一维动态规划+多维动态规划
文章目录 20 位运算20.1 【位运算】二进制求和20.2 【位运算】颠倒二进制位20.3 【位运算】位1的个数20.4 【位运算】只出现一次的数字20.5 【哈希表】【位运算】只出现一次的数字 II20.6 【位运算】数字范围按位与 21 数学21.1 【双指针】回文数21.2 【数学】加一21.3 【数学】…...
JetBrains全家桶激活,分享 WebStorm 2024 激活的方案
大家好,欢迎来到金榜探云手! WebStorm公司简介 JetBrains 是一家专注于开发工具的软件公司,总部位于捷克。他们以提供强大的集成开发环境(IDE)而闻名,如 IntelliJ IDEA、PyCharm、和 WebStorm等。这些工具…...
Sublime 彻底解决中文乱码
1. 按ctrl,打开Console,输入如下代码: import urllib.request,os; pf Package Control.sublime-package; ipp sublime.installed_packages_path(); urllib.request.install_opener( urllib.request.build_opener( urllib.request.ProxyHand…...
复旦大学EMBA校友出席两会建言献策助力中国发展
阳春三月,备受瞩目的全国两会如期召开。期间,复旦大学EMBA多位校友作为第十四届全国人民代表大会代表、第十四届全国政协委员与全国各地代表共商国是。 无论是作为大型央企负责人,还是作为科创企业的中坚力量,复旦大学EM…...
virtualbox导入vdi
新建虚拟机 点击新建 输入新建属性 配置cpu和内存 虚拟硬盘 这里选择已有的vdi文件 摘要 这里点击完成 虚拟机添加成功 点击启动,启动虚拟机 注意 这个时候的ip,还是以前镜像的ip,如果两个镜像一起启动,则需要修 改ip地…...
【信号处理】基于DGGAN的单通道脑电信号增强和情绪检测(tensorflow)
关于 情绪检测,是脑科学研究中的一个常见和热门的方向。在进行情绪检测的分类中,真实数据不足,经常导致情绪检测模型的性能不佳。因此,对数据进行增强,成为了一个提升下游任务的重要的手段。本项目通过DCGAN模型实现脑…...
使用 Docker Compose 部署 Spring Boot 应用
使用 Docker Compose 部署 Spring Boot 应用 第一步:创建 Spring Boot 应用的 Dockerfile 在您的 Spring Boot 项目根目录中创建一个 Dockerfile。 编辑 Dockerfile,添加以下内容: # 基础镜像使用 OpenJDK FROM openjdk:11-jdk-slim# 维护者…...
nginx 正向代理 https
问题背景 因为网络环境受限,应用服务器无法直接访问外网,需要前置机上中转一下,这种情况可在应用服务器修改/etc/hosts文件指向前置机,在前置机上的nginx设置四层代理,从而出站。 方案 根据How to Use NGINX as an …...
vue3从其他页面跳转页面头部组件菜单el-menu菜单高亮
主要代码 import { ref, onMounted, watch } from vue; const activeIndex ref("/"); const route useRoute();onMounted(() > {updateActiveMenu(); });watch(() > route.path, updateActiveMenu);function updateActiveMenu() {// 根据路由更新activeMenu…...
python 条件循环语句
python 条件循环语句 一、条件控制语句1. Python3 条件控制2. if 语句3. if 嵌套4. match...case5. 注意: 二、循环控制语句1. Python3 循环语句2. while 循环3. 无限循环4. while 循环使用 else 语句5. 简单语句组6. for 语句7. for...else8. break 和 continue 语…...
CIM搭建实现发送消息的效果
目录 背景过程1、下载代码2、进行配置3、直接启动项目4、打开管理界面5、启动web客户端实例项目6、发送消息 项目使用总结 背景 公司项目有许多需要发送即时消息的场景,之前一直采用的是传统的websocket连接,它会存在掉线严重,不可重连&…...
C++第十三弹---内存管理(下)
✨个人主页: 熬夜学编程的小林 💗系列专栏: 【C语言详解】 【数据结构详解】【C详解】 目录 1、operator new与operator delete函数 1.1、operator new与operator delete函数 2、new和delete的实现原理 2.1、内置类型 2.2、自定义类型 …...
Python爬虫学习完整版
一、什么是爬虫 网络爬虫,是一种按照一定规则,自动抓取互联网信息的程序或者脚本。由于互联网数据的多样性和资源的有限性,根据用户需求定向抓取相关网页并分析也成为如今主流的爬取策略。 1 爬虫可以做什么 你可以爬取网络上的的图片&#…...
JavaScript中的继承方式详解
Question JavaScript实现继承的方式? 包含原型链继承、构造函数继承、组合继承、原型式继承、寄生式继承、寄生组合式继承和ES6 类继承 JavaScript实现继承的方式 在JavaScript中,实现继承的方式多种多样,每种方式都有其优势和适用场景。以下…...
Git基础(23):Git分支合并实战保姆式流程
文章目录 前言准备正常分支合并1. 创建两个不冲突分支2. 将dev合并到test 冲突分支合并1. 制造分支冲突2. 冲突合并 前言 Git分支合并操作 准备 这里先在Gitee创建了一个空仓库,方便远程查看内容。 正常分支合并 1. 创建两个不冲突分支 (1…...
为什么有些前端一直用 div 当按钮,而不是用 button?
1. HTML 中的 <div> 和 <button> 在了解为什么有些前端开发者更喜欢使用 <div> 作为按钮之前,让我们先来了解一下 <div> 和 <button> 标签在 HTML 中的作用和区别。 <div>:是 HTML 中的一个通用容器元素࿰…...
前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...
1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
基于matlab策略迭代和值迭代法的动态规划
经典的基于策略迭代和值迭代法的动态规划matlab代码,实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...
深度学习习题2
1.如果增加神经网络的宽度,精确度会增加到一个特定阈值后,便开始降低。造成这一现象的可能原因是什么? A、即使增加卷积核的数量,只有少部分的核会被用作预测 B、当卷积核数量增加时,神经网络的预测能力会降低 C、当卷…...
【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案
目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后,迭代器会失效,因为顺序迭代器在内存中是连续存储的,元素删除后,后续元素会前移。 但一些场景中,我们又需要在执行删除操作…...
Leetcode33( 搜索旋转排序数组)
题目表述 整数数组 nums 按升序排列,数组中的值 互不相同 。 在传递给函数之前,nums 在预先未知的某个下标 k(0 < k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k1], …, nums[n-1], nums[0], nu…...
9-Oracle 23 ai Vector Search 特性 知识准备
很多小伙伴是不是参加了 免费认证课程(限时至2025/5/15) Oracle AI Vector Search 1Z0-184-25考试,都顺利拿到certified了没。 各行各业的AI 大模型的到来,传统的数据库中的SQL还能不能打,结构化和非结构的话数据如何和…...
stm32wle5 lpuart DMA数据不接收
配置波特率9600时,需要使用外部低速晶振...
如何配置一个sql server使得其它用户可以通过excel odbc获取数据
要让其他用户通过 Excel 使用 ODBC 连接到 SQL Server 获取数据,你需要完成以下配置步骤: ✅ 一、在 SQL Server 端配置(服务器设置) 1. 启用 TCP/IP 协议 打开 “SQL Server 配置管理器”。导航到:SQL Server 网络配…...
6️⃣Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙
Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙 一、前言:离区块链还有多远? 区块链听起来可能遥不可及,似乎是只有密码学专家和资深工程师才能涉足的领域。但事实上,构建一个区块链的核心并不复杂,尤其当你已经掌握了一门系统编程语言,比如 Go。 要真正理解区…...
