文章目录
- 前言
- 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资源库了。