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