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 中的一个通用容器元素࿰…...

XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容
基于 UniApp + WebSocket实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建
华为云FlexusDeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色,华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型,能助力我们轻松驾驭 DeepSeek-V3/R1,本文中将分享如何…...

OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...

以光量子为例,详解量子获取方式
光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...
智能AI电话机器人系统的识别能力现状与发展水平
一、引言 随着人工智能技术的飞速发展,AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术,在客户服务、营销推广、信息查询等领域发挥着越来越重要…...

JVM 内存结构 详解
内存结构 运行时数据区: Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器: 线程私有,程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 每个线程都有一个程序计数…...

基于SpringBoot在线拍卖系统的设计和实现
摘 要 随着社会的发展,社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统,主要的模块包括管理员;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...

MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...