服务端关键步骤归纳
- 创建.Net控制台项目
- 修改app项目设置文件
BestGame\Server\App\FantasySettings.json
- 导出配置表与消息协议
- 编译运行服务端程序,在生成的app程序目录下打开命令行:
BestGame\Bin\App>Fantasy.App.exe --AppType Game
如果想看到打印输出用develop模式:
BestGame\Bin\App>Fantasy.App.exe --AppType Game --Mode Develop
Fantasy创建项目引入框架三篇:
[Fantasy起步]创建前端项目引入Fantasy.Unity
[Fantasy 起步] 创建后端项目引入 Fantasy.Net
[Fantasy 起步]导出配置表与消息协议
下载安装.Net https://dotnet.microsoft.com/zh-cn/download
创建App项目
在Server目录下新建App目录 \BestGame\Server\App\
如果你不太会用vs或vs code软件创建.Net项目到指定位置,可以在App目录下直接新建文件:
App.csproj
NLog.config
Program.cs
\BestGame\Server\App\App.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>default</LangVersion>
<AssemblyName>App</AssemblyName>
</PropertyGroup>
<PropertyGroup>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<SatelliteResourceLanguages>en</SatelliteResourceLanguages>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<OutputPath>../../Bin/App/</OutputPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<OutputPath>../../Bin/App/</OutputPath>
</PropertyGroup>
<!-- 后端起动项目引入框架Fantasy.Net与自建的Hotfix.csproj项目 -->
<ItemGroup>
<ProjectReference Include="..\..\..\..\Fantasy.Net\Fantasy.Net.csproj" />
<ProjectReference Include="..\Hotfix\Hotfix.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="FantasySettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="NLog.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
\BestGame\Server\App\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"
xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd">
<targets async="true">
<target name="ServerDebug" xsi:type="File"
encoding="UTF-8"
createDirs="true"
autoFlush="false"
keepFileOpen="true"
concurrentWrites="true"
openFileCacheTimeout="30"
openFileFlushTimeout="60"
fileName="${basedir}/../Logs/Server/Server${date:format=yyyyMMdd}/${logger}.${var:appId}.${date:format=yyyyMMddHH}.Debug.log"
layout="${longdate} ${callsite:className=false:methodName=false:fileName=true:includeSourcePath=false:skipFrames=2} ${message}"/>
</targets>
<targets async="true">
<target name="ServerInfo" xsi:type="File"
encoding="UTF-8"
createDirs="true"
autoFlush="false"
keepFileOpen="true"
concurrentWrites="true"
openFileCacheTimeout="30"
openFileFlushTimeout="60"
fileName="${basedir}/../Logs/Server/Server${date:format=yyyyMMdd}/${logger}.${var:appId}.${date:format=yyyyMMddHH}.Info.log"
layout="${longdate} ${message}"/>
</targets>
<targets async="true">
<target name="ServerWarn" xsi:type="File"
encoding="UTF-8"
createDirs="true"
autoFlush="false"
keepFileOpen="true"
concurrentWrites="true"
openFileCacheTimeout="30"
openFileFlushTimeout="60"
fileName="${basedir}/../Logs/Server/Server${date:format=yyyyMMdd}/${logger}.${var:appId}.${date:format=yyyyMMddHH}.Warn.log"
layout="${longdate} ${message}"/>
</targets>
<targets async="true">
<target name="ServerError" xsi:type="File"
encoding="UTF-8"
createDirs="true"
autoFlush="false"
keepFileOpen="true"
concurrentWrites="true"
openFileCacheTimeout="30"
openFileFlushTimeout="60"
fileName="${basedir}/../Logs/Server/Server${date:format=yyyyMMdd}/${logger}.${var:appId}.${date:format=yyyyMMddHH}.Error.log"
layout="${longdate} ${message}"/>
</targets>
<targets async="true">
<target name="ServerTrace" xsi:type="File"
encoding="UTF-8"
createDirs="true"
autoFlush="false"
keepFileOpen="true"
concurrentWrites="true"
openFileCacheTimeout="30"
openFileFlushTimeout="60"
fileName="${basedir}/../Logs/Server/Server${date:format=yyyyMMdd}/${logger}.${var:appId}.${date:format=yyyyMMddHH}.Trace.log"
layout="${longdate} ${message}"/>
</targets>
<targets async="true">
<target name="ConsoleColor" xsi:type="ColoredConsole"
useDefaultRowHighlightingRules="false"
layout="${longdate} ${message}">
<highlight-row condition="level == LogLevel.Debug" foregroundColor="DarkGreen" />
<highlight-row condition="level == LogLevel.Info" foregroundColor="Gray" />
<highlight-row condition="level == LogLevel.Warn" foregroundColor="Yellow" />
<highlight-row condition="level == LogLevel.Error" foregroundColor="DarkRed" />
<highlight-row condition="level == LogLevel.Fatal" foregroundColor="Red" />
</target>
</targets>
<rules>
<!-- 控制台 调试或编辑器启动的时候会调用-->
<logger ruleName="ConsoleTrace" name="Server" level="Trace" writeTo="ConsoleColor" />
<logger ruleName="ConsoleDebug" name="Server" level="Debug" writeTo="ConsoleColor" />
<logger ruleName="ConsoleInfo" name="Server" level="Info" writeTo="ConsoleColor" />
<logger ruleName="ConsoleWarn" name="Server" level="Warn" writeTo="ConsoleColor" />
<logger ruleName="ConsoleError" name="Server" level="Error" writeTo="ConsoleColor" />
<!-- 服务端日志输出文件 发布到服务器后会调用-->
<logger ruleName="ServerDebug" name="Server" level="Debug" writeTo="ServerDebug" />
<logger ruleName="ServerTrace" name="Server" level="Trace" writeTo="ServerTrace" />
<logger ruleName="ServerInfo" name="Server" level="Info" writeTo="ServerInfo" />
<logger ruleName="ServerWarn" name="Server" level="Warn" writeTo="ServerWarn" />
<logger ruleName="ServerError" name="Server" level="Error" writeTo="ServerError" />
</rules>
</nlog>
\BestGame\Server\App\Program.cs
using Fantasy;
try
{
// 初始化框架
Application.Initialize();
// 加载需要的程序集
AssemblyHelper.Initialize();
// 绑定框架需要的配置文件
ConfigTableHelper.Bind();
// 启动框架
Application.Start().Coroutine();
// 自定义框架启动后需要执行的逻辑
Entry.Start().Coroutine();
for (;;)
{
Thread.Sleep(1);
ThreadSynchronizationContext.Main.Update();
SingletonSystem.Update();
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
创建app项目配置文件
BestGame\Server\App\FantasySettings.json
{
"Export": {
"ExcelServerBinaryDirectory": {
"Value": "../../Config/Binary/",
"Comment": "Excel生成服务器二进制数据文件夹位置"
}
},
"Network": {
"SessionIdleCheckerInterval": {
"Value": 5000,
"Comment": "每隔多久检查一个Session的对话时间"
},
"SessionIdleCheckerTimeout": {
"Value": 8000,
"Comment": "距上一次接收对话的时间如果超过设定的时间会自定断开Session"
}
}
}
创建Hotfix项目
在Server目录下新建Hotfix目录 \BestGame\Server\Hotfix\
如果你不太会用vs或vs code软件创建.Net项目到指定位置,可以在Hotfix目录下直接新建文件:
Hotfix.csproj
Entry.cs
OnCreateScene.cs
\BestGame\Server\Hotfix\Hotfix.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>default</LangVersion>
</PropertyGroup>
<PropertyGroup>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<SatelliteResourceLanguages>en</SatelliteResourceLanguages>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<OutputPath>../../Bin/App/</OutputPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<OutputPath>../../Bin/App/</OutputPath>
</PropertyGroup>
<!-- 后端项目引入Fantasy.Net -->
<ItemGroup>
<ProjectReference Include="..\..\..\..\Fantasy.Net\Fantasy.Net.csproj" />
</ItemGroup>
<!-- 后端项目引入一些前后端共用的目录下的文件,这里是举例注释了 -->
<!-- <ItemGroup>
<Compile Include="..\..\Unity\Assets\Scripts\Network\Helper\**\*.cs">
<Link>Common\Helper\%(RecursiveDir)%(FileName)%(Extension)</Link>
</Compile>
</ItemGroup> -->
<!-- 后端项目引入一些第三方库,这里是举例注释了 -->
<!-- <ItemGroup>
<PackageReference Include="PinYinConverterCore" Version="1.0.2" />
</ItemGroup> -->
</Project>
\BestGame\Server\Hotfix\Entry.cs
namespace Fantasy;
public static class Entry
{
public static async FTask Start()
{
// 自定义框架启动后需要执行的逻辑
// ...
await FTask.CompletedTask;
}
}
\BestGame\Server\Hotfix\OnCreateScene.cs
using Fantasy;
using BestGame;
/// <summary>
/// 当Scene创建时需要干什么
/// </summary>
public class OnCreateScene : AsyncEventSystem<Fantasy.OnCreateScene>
{
public override async FTask Handler(Fantasy.OnCreateScene self)
{
// Fantasy服务器是以Scene为单位的、所以Scene下有什么组件都可以自己添加定义
// OnCreateScene这个事件就是给开发者使用的
var scene = self.Scene;
scene.AddComponent<GuiderComponent>();
switch (scene.SceneType)
{
case SceneType.Addressable:
{
// 挂载管理Address地址组件
scene.AddComponent<AddressableManageComponent>();
break;
}
case SceneType.Gate:
{
// 添加网关组件
break;
}
case SceneType.Map:
{
// 添加地图组件
break;
}
}
await FTask.CompletedTask;
}
}
导出配置表与消息协议
[Fantasy 起步]导出配置表与消息协议