Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
1e195ed3b4 | ||
![]() |
aaf7ddbee8 | ||
![]() |
32d4e47184 | ||
![]() |
a2255b80cd | ||
![]() |
17a5d7425c | ||
![]() |
f64bb37706 | ||
![]() |
5cf6b8c034 | ||
![]() |
0397d0f01e | ||
![]() |
7bf081269c |
@@ -1,29 +0,0 @@
|
||||
# 介绍- Introduce
|
||||
|
||||
### TEngine
|
||||
<a style="text-decoration:none">
|
||||
<img src="https://img.shields.io/badge/Unity%20Ver-2021.3.20++-blue.svg?style=flat-square" alt="status" />
|
||||
</a>
|
||||
<a style="text-decoration:none">
|
||||
<img src="https://img.shields.io/github/license/ALEXTANGXIAO/TEngine" alt="license" />
|
||||
</a>
|
||||
<a style="text-decoration:none">
|
||||
<img src="https://img.shields.io/github/last-commit/ALEXTANGXIAO/TEngine" alt="last" />
|
||||
</a>
|
||||
<a style="text-decoration:none">
|
||||
<img src="https://img.shields.io/github/issues/ALEXTANGXIAO/TEngine" alt="issue" />
|
||||
</a>
|
||||
<a style="text-decoration:none">
|
||||
<img src="https://img.shields.io/github/languages/top/ALEXTANGXIAO/TEngine" alt="topLanguage" />
|
||||
</a>
|
||||
|
||||
TEngine是一套用于Unity框架解决方案,用于帮助研发团队快速进行开发。
|
||||
|
||||
### 开箱即用
|
||||
开箱即用、用法简洁,即用即上手.高可读性和详细的文档说明帮助你更快更好的进行游戏开发。您不需要关心框架的底层,分离独自实现您的GamePlay。
|
||||
|
||||
### 性能强大
|
||||
TEngine 底层使用基于UniTask的异步以及事件分发,可插件定制化,把复杂游戏简单化切以高性能、低耦合度实现。
|
||||
|
||||
### 高内聚低耦合
|
||||
内嵌了The Best 次时代热更新解决方案<a href="https://github.com/focus-creative-games/hybridclr"><strong>HybridCLR</strong></a>、百万DAU验证的资源解决方案<a href="https://github.com/tuyoogame/YooAsset"><strong>YooAsset</strong></a>、你的游戏最佳配置解决方案<a href="https://github.com/focus-creative-games/luban"><strong>Luban</strong></a>
|
@@ -1,63 +0,0 @@
|
||||
# 快速开始- Quickly Start
|
||||
快速上手
|
||||
本教程引导从空项目开始体验TEngine。出于简化起见,只演示目标平台为Windows的情况。
|
||||
|
||||
请在Standalone平台上正确跑通热更新流程后再自行尝试Android、iOS平台的热更新,它们的流程非常相似。
|
||||
|
||||
### 1.使用Unity2021.3.20f1c1打开项目工程。
|
||||
|
||||
### 2.默认选择顶部栏目EditorMode编辑器下的模拟模式并点击Launcher开始运行
|
||||

|
||||
|
||||
### 3.Editor编辑器下运行成功!
|
||||

|
||||
|
||||
### 4.打包运行
|
||||
* 1.运行菜单 HybridCLR/Install... 安装HybridCLR,每次更新HybridCLR版本需要重新执行一次安装。
|
||||
* 2.运行菜单 HybridCLR/Define Symbols/Enable HybridCLR 运行开启HybridCLR热更新。
|
||||
* 3.运行菜单 HybridCLR/Generate/All 进行必要的生成操作。这一步不可遗漏!!!
|
||||
* 4.运行菜单 HybridCLR/Build/BuildAssets And CopyTo AssemblyPath,生成热更新dll并copy到热更程序集中。
|
||||
* 5.运行菜单 YooAsset/AssetBundle Builder 构建AB。
|
||||
* 6.打开Build Settings对话框,点击Build And Run,打包并且运行热更新示例工程。
|
||||
|
||||
### 遇到问题请查看HybridlCLR的<a href="https://hybridclr.doc.code-philosophy.com/docs/help/commonerrors"><strong>常见错误(commonerrors)</strong></a>
|
||||
|
||||
### 系统需求
|
||||
默认版本:Unity2021.3.20f1c1
|
||||
|
||||
支持版本: Unity2019.4 & Unity2020.3 & Unity2021.3 & Unity2022.3
|
||||
|
||||
支持平台: Windows、OSX、Android、iOS、WebGL
|
||||
|
||||
开发环境: .NET4.x
|
||||
|
||||
### 目录结构
|
||||
```
|
||||
Assets
|
||||
├── AssetArt // 美术资源目录
|
||||
│ └── Atlas // 自动生成图集目录
|
||||
├── AssetRaw // 热更资源目录
|
||||
│ ├── UIRaw // UI图片目录
|
||||
│ │ ├── Atlas // 需要自动生成图集的UI素材目录
|
||||
│ │ └── Raw // 不需要自动生成图集的UI素材目录
|
||||
├── Editor // 编辑器脚本目录
|
||||
├── HybridCLRData // hybridclr相关目录
|
||||
├── Scenes // 主场景目录
|
||||
├── GameScripts // 程序集目录
|
||||
└── TEngine // 框架核心目录
|
||||
├── AssetSetting // YooAsset资源设置
|
||||
├── Editor // TEngine-Editor程序集
|
||||
└── Runtime // TEngine-Runtime程序集
|
||||
```
|
||||
|
||||
### 热更新程序集划分
|
||||
```
|
||||
Assets/GameScripts
|
||||
├── Main // 主程序程序集(启动器与流程)
|
||||
└── HotFix // 游戏热更程序集目录 [Folder]
|
||||
├── GameBase // 游戏基础框架程序集 [Dll]
|
||||
├── GameProto // 游戏配置协议程序集 [Dll]
|
||||
└── GameLogic // 游戏业务逻辑程序集 [Dll]
|
||||
├── GameApp.cs // 热更主入口
|
||||
└── GameApp_RegisterSystem.cs // 热更主入口注册系统
|
||||
```
|
@@ -1,82 +0,0 @@
|
||||
# TEngine
|
||||
|
||||
## TEngine-Runtime
|
||||
### AOT内核基于Gameframework,优化、最简化以及商业化适配。
|
||||

|
||||
|
||||
## AOT游戏框架模块基类。
|
||||
#### 框架思路为面向接口编程,如Resource资源模块,开发白皮书为先定义IResourceManager的接口规范,然后编写ResourceManager继承框架具体实现(ModuleImp)以及实现接口。最后实现调用层Module,调用层可以拓展编辑器供开发者自定义模块参数。
|
||||
``` csharp
|
||||
/// <summary>
|
||||
/// 游戏框架模块抽象类。ModuleImp为具体框架模块实现。
|
||||
/// </summary>
|
||||
internal abstract class ModuleImp
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取游戏框架模块优先级。
|
||||
/// </summary>
|
||||
/// <remarks>优先级较高的模块会优先轮询,并且关闭操作会后进行。</remarks>
|
||||
internal virtual int Priority => 0;
|
||||
|
||||
/// <summary>
|
||||
/// 游戏框架模块轮询。
|
||||
/// </summary>
|
||||
/// <param name="elapseSeconds">逻辑流逝时间,以秒为单位。</param>
|
||||
/// <param name="realElapseSeconds">真实流逝时间,以秒为单位。</param>
|
||||
internal abstract void Update(float elapseSeconds, float realElapseSeconds);
|
||||
|
||||
/// <summary>
|
||||
/// 关闭并清理游戏框架模块。
|
||||
/// </summary>
|
||||
internal abstract void Shutdown();
|
||||
}
|
||||
|
||||
//=====================================================================//
|
||||
|
||||
/// <summary>
|
||||
/// 游戏框架模块抽象类。Module 为Mono调用层。
|
||||
/// </summary>
|
||||
public abstract class Module : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// 游戏框架模块初始化。
|
||||
/// </summary>
|
||||
protected virtual void Awake()
|
||||
{
|
||||
ModuleSystem.RegisterModule(this);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 热更域程序集设计与说明
|
||||
```
|
||||
Assets/GameScripts
|
||||
├── Main // 主程序程序集(启动器与流程)
|
||||
└── HotFix // 游戏热更程序集目录 [Folder]
|
||||
├── GameBase // 游戏基础框架程序集 [Dll]
|
||||
├── GameProto // 游戏配置协议程序集 [Dll]
|
||||
└── GameLogic // 游戏业务逻辑程序集 [Dll]
|
||||
├── GameApp.cs 热更主入口
|
||||
└── GameApp_RegisterSystem.cs 热更主入口注册系统
|
||||
```
|
||||
游戏内主要玩法逻辑包括UI会在GameLogic中编写,GameBase则存放一些通用性的逻辑,GameProto存放与服务区交互的协议以及配置表逻辑。若有项目需求完全可以进行自定义增删HotFix程序集。
|
||||
|
||||
PS:注意增删程序集后需要同步到HybridClr的Setting面板以及TEngineSetting的面板。TEngineSettings面板有按钮可以从HybridClr中同步AOT与热更程序集。
|
||||
|
||||
## 常用模块接口
|
||||
|
||||
<strong>[3-1-资源模块](./3-1-资源模块.md)<strong>
|
||||
|
||||
<strong>[3-2-事件模块](./3-2-事件模块.md)<strong>
|
||||
|
||||
<strong>[3-3-内存池模块](./3-3-内存池模块.md)<strong>
|
||||
|
||||
<strong>[3-4-对象池模块](./3-4-对象池模块.md)<strong>
|
||||
|
||||
<strong>[3-5-UI模块](./3-5-UI模块.md)<strong>
|
||||
|
||||
<strong>[3-6-配置表模块](./3-6-配置表模块.md)<strong>
|
||||
|
||||
<strong>[3-7-流程模块](./3-7-流程模块.md)<strong>
|
||||
|
||||
<strong>[3-8-网络模块](./3-8-网络模块.md)<strong>
|
@@ -1,200 +0,0 @@
|
||||
## 3-1.资源模块 - ResourceModule
|
||||
|
||||
#### 资源模块默认使用Addressable可寻址定位。(!注意需要打包的资源不可以重名)
|
||||
|
||||
资源模块运行模式有EditorSimulateMode、OfflinePlayMode以及HostPlayMode
|
||||
编辑器模式下以顶部导航栏的选项卡为优先选项,打包后以Scene场景中ResourceModule脚本的Enum选项卡为优先选项(打包后不会走EditorSimulateMode)
|
||||
|
||||
Scene窗口Resource对象可以设置一些资源模块的常用设置,比如打包后的资源模式、资源校验等级以及自动卸载资源间隔等。
|
||||

|
||||
|
||||
Menu窗口TEngineSetting可以设置一些资源模块的热更新设置,比如资源服务器地址以及在线参数等。备注在Luban目录下有一个基于Node的静态文件服务器,可以把在线参数以及AB放入用于做热更新测试。
|
||||

|
||||
|
||||
## 重要拓展概念
|
||||
* AssetReference (资源引用标识) 通用加载资源的时候绑定一个引用标识使你无需关心手动Dispose资源句柄。
|
||||
|
||||
* AssetGroup(资源组数据)进行资源分组绑定管理内存中的生命周期资源生命周期托管给资源组的根节点进行Dispose。
|
||||
|
||||
* LruCacheTable (Least Recently Used Cache缓存表)
|
||||
|
||||
* ArcCacheTable (Adaptive Replacement Cache缓存表)
|
||||
|
||||
## 加载资源示范
|
||||
注意!资源模块默认使用Addressable可寻址定位。传入资源名字无需后缀即可!!
|
||||
``` csharp
|
||||
|
||||
//同步加载。
|
||||
GameModule.Resource.LoadAsset<SkillDisplayData>(location);
|
||||
|
||||
//异步加载。
|
||||
GameModule.Resource.LoadAssetAsync<SkillDisplayData>(location, OnLoadSuccess);
|
||||
private void OnLoadSuccess(AssetOperationHandle assetOperationHandle){}
|
||||
|
||||
//使用UniTask异步加载。
|
||||
await GameModule.Resource.LoadAssetAsync<SkillDisplayData>(location,CancellationToken.None);
|
||||
```
|
||||
|
||||
## 常用接口
|
||||
remark:资源模块初始化的生命周期已经在流程模块实现了,具体有需求可以自定义开发。
|
||||
``` csharp
|
||||
/// <summary>
|
||||
/// 获取当前资源包版本。
|
||||
/// </summary>
|
||||
/// <returns>资源包版本。</returns>
|
||||
public string GetPackageVersion();
|
||||
|
||||
/// <summary>
|
||||
/// 异步更新最新包的版本。
|
||||
/// </summary>
|
||||
/// <param name="appendTimeTicks">请求URL是否需要带时间戳。</param>
|
||||
/// <param name="timeout">超时时间。</param>
|
||||
/// <returns>请求远端包裹的最新版本操作句柄。</returns>
|
||||
public UpdatePackageVersionOperation UpdatePackageVersionAsync(bool appendTimeTicks = false, int timeout = 60);
|
||||
|
||||
/// <summary>
|
||||
/// 向网络端请求并更新清单
|
||||
/// </summary>
|
||||
/// <param name="packageVersion">更新的包裹版本</param>
|
||||
/// <param name="autoSaveVersion">更新成功后自动保存版本号,作为下次初始化的版本。</param>
|
||||
/// <param name="timeout">超时时间(默认值:60秒)</param>
|
||||
public UpdatePackageManifestOperation UpdatePackageManifestAsync(string packageVersion, bool autoSaveVersion = true, int timeout = 60);
|
||||
|
||||
/// <summary>
|
||||
/// 创建资源下载器,用于下载当前资源版本所有的资源包文件。
|
||||
/// </summary>
|
||||
public ResourceDownloaderOperation CreateResourceDownloader();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 清理包裹未使用的缓存文件。
|
||||
/// </summary>
|
||||
public ClearUnusedCacheFilesOperation ClearUnusedCacheFilesAsync();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 清理沙盒路径。
|
||||
/// </summary>
|
||||
public void ClearSandbox();
|
||||
|
||||
/// <summary>
|
||||
/// 强制执行释放未被使用的资源。
|
||||
/// </summary>
|
||||
/// <param name="performGCCollect">是否使用垃圾回收。</param>
|
||||
public void ForceUnloadUnusedAssets(bool performGCCollect);
|
||||
|
||||
/// <summary>
|
||||
/// 检查资源是否存在。
|
||||
/// </summary>
|
||||
/// <param name="assetName">要检查资源的名称。</param>
|
||||
/// <returns>检查资源是否存在的结果。</returns>
|
||||
public HasAssetResult HasAsset(string assetName);
|
||||
|
||||
/// 同步加载资源。
|
||||
/// </summary>
|
||||
/// <param name="assetName">要加载资源的名称。</param>
|
||||
/// <typeparam name="T">要加载资源的类型。</typeparam>
|
||||
/// <returns>资源实例。</returns>
|
||||
T LoadAsset<T>(string assetName) where T : Object;
|
||||
|
||||
/// <summary>
|
||||
/// 同步加载资源。
|
||||
/// </summary>
|
||||
/// <param name="assetName">要加载资源的名称。</param>
|
||||
/// <param name="parent">父节点位置。</param>
|
||||
/// <typeparam name="T">要加载资源的类型。</typeparam>
|
||||
/// <returns>资源实例。</returns>
|
||||
T LoadAsset<T>(string assetName, Transform parent) where T :Object;
|
||||
|
||||
/// <summary>
|
||||
/// 同步加载资源。
|
||||
/// </summary>
|
||||
/// <param name="handle">资源操作句柄。</param>
|
||||
/// <param name="assetName">要加载资源的名称。</param>
|
||||
/// <typeparam name="T">要加载资源的类型。</typeparam>
|
||||
/// <returns>资源实例。</returns>
|
||||
T LoadAsset<T>(string assetName,out AssetOperationHandle handle) where T : Object;
|
||||
|
||||
/// <summary>
|
||||
/// 同步加载资源。
|
||||
/// </summary>
|
||||
/// <param name="assetName">要加载资源的名称。</param>
|
||||
/// <param name="handle">资源操作句柄。</param>
|
||||
/// <param name="parent">父节点位置。</param>
|
||||
/// <typeparam name="T">要加载资源的类型。</typeparam>
|
||||
/// <returns>资源实例。</returns>
|
||||
T LoadAsset<T>(string assetName, Transform parent,out AssetOperationHandle handle) where T :Object;
|
||||
|
||||
/// <summary>
|
||||
/// 异步加载资源。
|
||||
/// </summary>
|
||||
/// <param name="assetName">要加载资源的名称。</param>
|
||||
/// <param name="cancellationToken">取消操作Token。</param>
|
||||
/// <typeparam name="T">要加载资源的类型。</typeparam>
|
||||
/// <returns>异步资源实例。</returns>
|
||||
UniTask<T> LoadAssetAsync<T>(string assetName,CancellationToken cancellationToken) where T : Object;
|
||||
|
||||
/// <summary>
|
||||
/// 异步加载游戏物体。
|
||||
/// </summary>
|
||||
/// <param name="assetName">要加载的游戏物体名称。</param>
|
||||
/// <param name="cancellationToken">取消操作Token。</param>
|
||||
/// <returns>异步游戏物体实例。</returns>
|
||||
UniTask<UnityEngine.GameObject> LoadGameObjectAsync(string assetName,CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// 同步加载资源并获取句柄。
|
||||
/// </summary>
|
||||
/// <param name="assetName">要加载资源的名称。</param>
|
||||
/// <typeparam name="T">要加载资源的类型。</typeparam>
|
||||
/// <returns>同步加载资源句柄。</returns>
|
||||
AssetOperationHandle LoadAssetGetOperation<T>(string assetName) where T : Object;
|
||||
|
||||
/// <summary>
|
||||
/// 异步加载资源并获取句柄。
|
||||
/// </summary>
|
||||
/// <param name="assetName">要加载资源的名称。</param>
|
||||
/// <typeparam name="T">要加载资源的类型。</typeparam>
|
||||
/// <returns>异步加载资源句柄。</returns>
|
||||
AssetOperationHandle LoadAssetAsyncHandle<T>(string assetName) where T : Object;
|
||||
|
||||
/// <summary>
|
||||
/// 同步加载子资源对象
|
||||
/// </summary>
|
||||
/// <typeparam name="TObject">资源类型</typeparam>
|
||||
/// <param name="location">资源的定位地址</param>
|
||||
public SubAssetsOperationHandle LoadSubAssetsSync<TObject>(string location) where TObject : UnityEngine.Object;
|
||||
|
||||
/// <summary>
|
||||
/// 异步加载子资源对象
|
||||
/// </summary>
|
||||
/// <typeparam name="TObject">资源类型</typeparam>
|
||||
/// <param name="location">资源的定位地址</param>
|
||||
public SubAssetsOperationHandle LoadSubAssetsAsync<TObject>(string location) where TObject : UnityEngine.Object;
|
||||
|
||||
/// <summary>
|
||||
/// 同步加载子资源对象
|
||||
/// </summary>
|
||||
/// <param name="assetInfo">资源信息。</param>
|
||||
public SubAssetsOperationHandle LoadSubAssetsSync(AssetInfo assetInfo);
|
||||
|
||||
/// <summary>
|
||||
/// 异步加载场景。
|
||||
/// </summary>
|
||||
/// <param name="location">场景的定位地址</param>
|
||||
/// <param name="sceneMode">场景加载模式</param>
|
||||
/// <param name="activateOnLoad">加载完毕时是否主动激活</param>
|
||||
/// <param name="priority">优先级</param>
|
||||
/// <returns>异步加载场景句柄。</returns>
|
||||
SceneOperationHandle LoadSceneAsync(string location, LoadSceneMode sceneMode = LoadSceneMode.Single, bool activateOnLoad = true, int priority = 100);
|
||||
|
||||
/// <summary>
|
||||
/// 异步加载场景
|
||||
/// </summary>
|
||||
/// <param name="assetInfo">场景的资源信息</param>
|
||||
/// <param name="sceneMode">场景加载模式</param>
|
||||
/// <param name="activateOnLoad">加载完毕时是否主动激活</param>
|
||||
/// <param name="priority">优先级</param>
|
||||
/// <returns>异步加载场景句柄。</returns>
|
||||
SceneOperationHandle LoadSceneAsync(AssetInfo assetInfo, LoadSceneMode sceneMode = LoadSceneMode.Single, bool activateOnLoad = true, int priority = 100);
|
||||
```
|
@@ -1,69 +0,0 @@
|
||||
# 3-2.事件模块 - GameEvent
|
||||
高效且无GC的事件系统GameEvent,可以指定事件ID/事件String监听和分发事件。通过事件来驱动模块,如战斗的角色身上的事件流、UI和网络以及Model的数据流、开发中的绝大部分情况都可以通过事件来进行驱动。(配合UI模块或者拓展的战斗模块实现MVE[Model - View - Event]事件驱动架构)
|
||||
|
||||
事件模块支持string和int作为事件Id,但推荐是使用int因为可以避免事件字典的哈希碰撞。这里实现了StringId.StringToHash的方法来定义事件ID达到事件系统的最佳性能。
|
||||
|
||||
<strong>注:UI模块的事件和UI生命周期存在绑定,销毁UI时可以自动移除UI所监听的事件,开发过程中只需要关心添加事件,避免了关闭UI但没有移除事件监听的问题,角色模块也可以参考实现。(AddUIEvent)</strong>
|
||||
``` csharp
|
||||
public static readonly int Hellp = StringId.StringToHash("Hellp.Hellp");
|
||||
|
||||
class A
|
||||
{
|
||||
public A()
|
||||
{
|
||||
//添加事件监听string
|
||||
GameEvent.AddEventListener("TEngine很好用",TodoSomeThings);
|
||||
//添加事件监听int 事件ID
|
||||
GameEvent.AddEventListener(Hellp,TodoSomeThings2);
|
||||
}
|
||||
}
|
||||
|
||||
class B
|
||||
{
|
||||
private void SaySomeThings()
|
||||
{
|
||||
//发送事件流
|
||||
GameEvent.Send("TEngine很好用");
|
||||
GameEvent.Send(Hellp);
|
||||
}
|
||||
}
|
||||
|
||||
【举个例子:游戏中血量扣除的时候,服务器发来了一个减少Hp的消息包,
|
||||
我们可以在收到这个消息包的时候发送一个事件流,在玩家头顶的HP进度
|
||||
条组件/左上角Hp的UI血条组件添加一个监听事件,各个模块负责自己监听后的逻辑】
|
||||
Server -> SendMessage(ReduceHP)
|
||||
|
||||
class ClientHandle
|
||||
{
|
||||
private void HandleMessage(MainPack mainpack)
|
||||
{
|
||||
...
|
||||
HpPack hpPack = mainpack.hpPack;
|
||||
int playerId = mainpack.playerId;
|
||||
var player = PlayerMgr.Instance.GetPlayer(playerId);
|
||||
if(player != null){
|
||||
player.Event.Send("Hpchange",hpPack); //局部的事件管理器
|
||||
GameEvent.Send("Hpchange",hpPack); //全局事件中心
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class PlayerHp
|
||||
{
|
||||
public ECSEventCmpt Event { get; set; }
|
||||
PlayerHp(){
|
||||
Event.AddEventListener<HpPack>(Hellp,HandleUpChange);
|
||||
}
|
||||
}
|
||||
|
||||
[Window(UILayer.UI)]
|
||||
class BattleMainUI: UIWindow
|
||||
{
|
||||
public override void RegisterEvent()
|
||||
{
|
||||
AddUIEvent<HpPack>(Hellp,HandleUpChange);
|
||||
}
|
||||
|
||||
public void HandleUpChange(HpPack pack){}
|
||||
}
|
||||
```
|
@@ -1,23 +0,0 @@
|
||||
# 3-3.内存池模块 - MemoryPool
|
||||
内存池更为轻量化,相对于对象池更适合一些更抽象碎片化的内存对象。
|
||||
|
||||
Scene窗口MemoryPool对象可以设置内存池检查,防止回收问题与内存泄漏问题。
|
||||

|
||||
|
||||
使用案例
|
||||
``` csharp
|
||||
/// <summary>
|
||||
/// 资源组数据。
|
||||
/// <remarks>DisposeGroup。</remarks>
|
||||
/// </summary>
|
||||
public class AssetGroup : IMemory
|
||||
{
|
||||
public void Clear(){}
|
||||
}
|
||||
|
||||
//内存池中获取/生成内存对象。
|
||||
AssetGroup assetGroup = MemoryPool.Acquire<AssetGroup>();
|
||||
|
||||
//释放内存对象还给内存池。
|
||||
MemoryPool.Release(assetGroup);
|
||||
```
|
@@ -1,64 +0,0 @@
|
||||
# 3-4.对象池模块 - ObjectModule
|
||||
对象池较中量级,在客户端开发中是一个经常使用的技术,技术点我相信大家都懂,这里不过多讨论。
|
||||
|
||||
使用案例
|
||||
``` csharp
|
||||
/// <summary>
|
||||
/// Actor对象。
|
||||
/// </summary>
|
||||
public class Actor : ObjectBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 释放对象。
|
||||
/// </summary>
|
||||
/// <param name="isShutdown">是否是关闭对象池时触发。</param>
|
||||
protected override void Release(bool isShutdown){}
|
||||
|
||||
/// <summary>
|
||||
/// 创建Actor对象。
|
||||
/// </summary>
|
||||
/// <param name="actorName">对象名称。</param>
|
||||
/// <param name="target">对象持有实例。</param>
|
||||
/// <returns></returns>
|
||||
public static Actor Create(string name, object target)
|
||||
{
|
||||
var actor = MemoryPool.Acquire<Actor>();
|
||||
actor.Initialize(name, target);
|
||||
return actor;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Actor对象池。
|
||||
/// </summary>
|
||||
private IObjectPool<Actor> _actorPool;
|
||||
|
||||
void Start()
|
||||
{
|
||||
//创建允许单次获取的对象池。
|
||||
_actorPool = GameModule.ObjectPool.CreateSingleSpawnObjectPool<Actor>(Utility.Text.Format("Actor Instance Pool ({0})", name));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建Actor对象。
|
||||
/// </summary>
|
||||
/// <param name="actorName">对象名称。</param>
|
||||
/// <param name="target">对象持有实例。</param>
|
||||
/// <returns>Actor对象实例</returns>
|
||||
public Actor CreateActor(string actorName, GameObject target)
|
||||
{
|
||||
Actor ret = null;
|
||||
if (_actorPool.CanSpawn())
|
||||
{
|
||||
ret = _actorPool.Spawn();
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = Actor.Create(actorName, target);
|
||||
_actorPool.Register(ret,true);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
```
|
@@ -1,126 +0,0 @@
|
||||
# 3-5.UI模块 - UIModule
|
||||
一个游戏70%都是UI,剩下30%才是GamePlay,所以有一套简洁强大的商业化UI模块以及UI开发工作流将是项目的一大利器,能够提高至少一倍的开发效率。(配合事件模块实现MVE[Model - View - Event]事件驱动架构)
|
||||
|
||||
UI脚本为纯C#实现,脱离Mono的生命周期,由UIModule的帧更新驱动并管理UI的生命周期。
|
||||
|
||||
IUIBehaviour为UI通用行为接口、UIBase为UI基类、UIWindow为UI窗口基类,UIWidget为UI组件基类。
|
||||
|
||||
## 前期配置:
|
||||
注意!!!!m_item节点为特殊节点表示是UI下的UIWidget组件,不会继续往下遍历生成UI代码。若需要这个UIWidget组件m_item的代码则在m_item右键生成这个组件的UI脚本。
|
||||
|
||||
Scene窗口下右键ScriptGenerator菜单下About目录有默认UI命名前缀规范。
|
||||

|
||||
|
||||
有自定义需求可以在TEngineSetting下进行自定义。
|
||||

|
||||
### 开发工作流:
|
||||
1.遵守前期默认配置或者自定义配置进行UI编排
|
||||

|
||||
|
||||
2.在UI的根节点右键ScriptGenerator生成UI代码到剪贴板上!!!(注-使用-UniTask的生成代码可以做异步事件流驱动的UI。)
|
||||

|
||||
|
||||
3.自行创建UI脚本到需要的目录下并复制UI脚本。
|
||||
|
||||
## 举例示范
|
||||
``` csharp
|
||||
// 同步打开面板
|
||||
GameModule.UI.ShowUI<GameMainUI>([nullable]userData);
|
||||
|
||||
// 异步打开面板
|
||||
GameModule.UI.ShowUIAsync<GameMainUI>([nullable]userData);
|
||||
|
||||
namespace GameLogic
|
||||
{
|
||||
/// <summary>
|
||||
/// BattleMainUI面板
|
||||
/// <remarks>UIWindow需要以下特性,UILayer可以自行定义,fullScreen表示为全屏面板会停止和隐藏这个面板堆栈后面的面板。</remarks>
|
||||
/// </summary>
|
||||
[Window(UILayer.Bottom,fullScreen:true)]
|
||||
class BattleMainUI : UIWindow
|
||||
{
|
||||
private TouchMove m_touchView;
|
||||
|
||||
#region 脚本工具生成的代码
|
||||
private RectTransform m_rectContainer;
|
||||
private GameObject m_itemTouch;
|
||||
private Button m_btnLeaveBattle;
|
||||
private GameObject m_goTopInfo;
|
||||
private Button m_btnPause;
|
||||
public override void ScriptGenerator()
|
||||
{
|
||||
m_rectContainer = FindChildComponent<RectTransform>("m_rectContainer");
|
||||
m_itemTouch = FindChild("m_rectContainer/m_itemTouch").gameObject;
|
||||
m_btnLeaveBattle = FindChildComponent<Button>("m_btnLeaveBattle");
|
||||
m_goTopInfo = FindChild("m_goTopInfo").gameObject;
|
||||
m_btnPause = FindChildComponent<Button>("m_goTopInfo/m_btnPause");
|
||||
m_btnLeaveBattle.onClick.AddListener(OnClickLeaveBattleBtn);
|
||||
m_btnPause.onClick.AddListener(OnClickPauseBtn);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 事件
|
||||
|
||||
private void OnClickPauseBtn()
|
||||
{
|
||||
BattleSys.Instance.Pause = !BattleSys.Instance.Pause;
|
||||
}
|
||||
|
||||
private void OnClickLeaveBattleBtn()
|
||||
{
|
||||
BattleSys.Instance.StopBattle(isBattleEnd:false,isWin:false);
|
||||
}
|
||||
#endregion
|
||||
|
||||
//注册事件举例
|
||||
public override void RegisterEvent()
|
||||
{
|
||||
//通过AddUIEvent这样注册事件会把事件的生命周期绑定给面板,面板销毁的时候自动移除监听。
|
||||
AddUIEvent(ActorLogicEventDefined.OnMainPlayerBagDataChange, RefreshUI);
|
||||
}
|
||||
|
||||
public override void BindMemberProperty()
|
||||
{
|
||||
//特殊的m_item节点的域不属于父级UIWindows,所以如注意所说需要同样创建这个UIWidget的脚本并生成代码过去。 可以如下创建或者走type、path创建。
|
||||
m_touchView = CreateWidget<TouchMove>(m_itemTouch);
|
||||
}
|
||||
|
||||
......
|
||||
}
|
||||
}
|
||||
|
||||
namespace GameLogic
|
||||
{
|
||||
/// <summary>
|
||||
/// 移动操作UIWidget。
|
||||
/// </summary>
|
||||
class TouchMove : UIWidget, IUICtrlMove
|
||||
{
|
||||
public override void BindMemberProperty()
|
||||
{
|
||||
}
|
||||
|
||||
//注意Update只有在重写了此方法才会驱动这个Widget或者面板的Update。
|
||||
public override void OnUpdate()
|
||||
{
|
||||
TProfiler.BeginSample("CheckMoveTouchFinger");
|
||||
CheckMoveTouchFinger();
|
||||
TProfiler.EndSample();
|
||||
|
||||
TProfiler.BeginSample("UpdateTouchMovePos");
|
||||
UpdateTouchMovePos();
|
||||
TProfiler.EndSample();
|
||||
|
||||
TProfiler.BeginSample("UpdateKeyMove");
|
||||
UpdateKeyMove();
|
||||
TProfiler.EndSample();
|
||||
}
|
||||
......
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## UI进阶
|
||||
UI面板需要标记UIWindowAttribute,以标识层级(可以自行定义)和是否全屏。全屏面板则会把下层面板的Visible设置为false。
|
||||

|
||||
|
@@ -1,63 +0,0 @@
|
||||
# 3-6.配置表模块 - ConfigSystem
|
||||
接入最佳游戏配置解决方案 - <a href="https://github.com/focus-creative-games/luban"><strong>Luban</strong></a>
|
||||
|
||||
<a href="https://luban.doc.code-philosophy.com/#/manual/traits"><strong>Luban文档 </strong></a>
|
||||
|
||||
### 在TEngine中Luban配置表目录位于以下目录
|
||||

|
||||
|
||||
### 安装luban配置表
|
||||
1.在TEngine根目录同级克隆下最新的luban-next仓库。
|
||||

|
||||
2.Tools目录执行build-luban完成
|
||||

|
||||
|
||||
3.转表则去luban配置目录执行对应bat
|
||||
|
||||
TEngine内置默认使用懒加载配置,也支持基于UniTask的异步加载,同步加载,包括服务器的Task异步加载,使用对应转表的bat即可。
|
||||
|
||||
### 介绍
|
||||
luban是你的最佳游戏配置解决方案。
|
||||
|
||||
luban高效地处理游戏开发中常见的excel、json、xml之类的数据,检查数据错误,生成c#等各种语言的代码,导出成bytes或json等多种格式。
|
||||
|
||||
luban统一了游戏配置开发工作流,极大提升了策划和程序的工作效率。
|
||||
|
||||
核心特性
|
||||
强大的数据解析和转换能力 {excel(csv,xls,xlsx)、json、bson、xml、yaml、lua、unity ScriptableObject} => {binary、json、bson、xml、lua、yaml、erlang、 custom format}
|
||||
增强的excel格式,可以简洁地配置出像简单列表、子结构、结构列表,以及任意复杂的深层次的嵌套结构。
|
||||
完备的类型系统,支持OOP类型继承,搭配excel、json、lua、xml等格式数据灵活优雅表达行为树、技能、剧情、副本之类复杂GamePlay数据
|
||||
支持生成c#、java、go、c++、lua、python、javascript、typescript、erlang、rust、gdscript 代码
|
||||
支持生成 protobuf(schema + binary + json)、flatbuffers(schema + json)、msgpack(binary)
|
||||
强大的数据校验能力。ref引用检查、path资源路径、range范围检查等等
|
||||
完善的本地化支持。静态文本值本地化、动态文本值本地化、时间本地化、main-patch多地区版本
|
||||
强大灵活的自定义能力,支持自定义代码模板和数据模板
|
||||
通用型生成和缓存工具。也可以用于生成协议、数据库之类的代码,甚至可以用作对象缓存服务。
|
||||
|
||||
|
||||
---
|
||||
|
||||
使用案例
|
||||
``` csharp
|
||||
/// <summary>
|
||||
/// 道具配置表管理器。
|
||||
/// </summary>
|
||||
public class ItemConfigMgr: Singleton<ItemConfigMgr>
|
||||
{
|
||||
/// <summary>
|
||||
/// 道具Table。
|
||||
/// </summary>
|
||||
private TbItem TbItem => ConfigLoader.Instance.Tables.TbItem;
|
||||
|
||||
/// <summary>
|
||||
/// 获取道具配置表。
|
||||
/// </summary>
|
||||
/// <param name="itemId">道具Id。</param>
|
||||
/// <returns>道具配置表。</returns>
|
||||
public ItemConfig GetItemConfig(int itemId)
|
||||
{
|
||||
TbItem.DataMap.TryGetValue(itemId, out var config);
|
||||
return config;
|
||||
}
|
||||
}
|
||||
```
|
@@ -1,27 +0,0 @@
|
||||
# 7.流程模块 - ProcedureModule
|
||||
|
||||
### ProcedureLaunch - 流程启动
|
||||
|
||||
### ProcedureSplash - 流程闪屏
|
||||
|
||||
### ProcedureInitPackage - 流程初始化Package
|
||||
|
||||
### ProcedurePreload - 流程预加载
|
||||
|
||||
### ProcedureInitResources - 流程初始化Resources
|
||||
|
||||
### ProcedureUpdateVersion - 流程更新版本Version
|
||||
|
||||
### ProcedureUpdateManifest - 流程更新Mainfest清单
|
||||
|
||||
### ProcedureCreateDownloader - 流程创建下载器
|
||||
|
||||
### ProcedureDownloadFile - 流程下载文件
|
||||
|
||||
### ProcedureDownloadOver - 流程下载文件结束
|
||||
|
||||
### ProcedureClearCache - 流程清理缓存
|
||||
|
||||
### ProcedureLoadAssembly - 流程加载进入热更新程序集
|
||||
|
||||
### ProcedureStartGame - 流程开始游戏
|
@@ -1,2 +0,0 @@
|
||||
# 8.网络模块 - Network
|
||||
待补充
|
@@ -1,26 +0,0 @@
|
||||
# TEngine各平台下运行
|
||||
|
||||
### 日志记录编辑器下运行
|
||||

|
||||
|
||||
---
|
||||
### Win64位包运行
|
||||
|
||||

|
||||
|
||||
---
|
||||
### 安卓真机运行
|
||||

|
||||
|
||||
### IOS真机运行
|
||||

|
||||
|
||||
### WebGL真机运行
|
||||

|
||||
|
||||
### 索尼 PS5 真机运行
|
||||
|
||||

|
||||
|
||||
|
||||

|
@@ -1,16 +0,0 @@
|
||||
## <strong>Buy me a coffee.
|
||||
|
||||
您的赞助会让我们做得更快更好,如果觉得TEngine对您有帮助,不妨赞助我买杯咖啡吧~
|
||||
|
||||
|
||||
<p align="center">
|
||||
|
||||
<img src="src/Donate-微信.jpg" alt="logo" width="384" height="562">
|
||||
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
|
||||
<img src="src/Donate-支付宝.jpg" alt="logo" width="384" height="562">
|
||||
|
||||
</p>
|
Before Width: | Height: | Size: 133 KiB |
Before Width: | Height: | Size: 218 KiB |
Before Width: | Height: | Size: 140 KiB |
Before Width: | Height: | Size: 222 KiB |
Before Width: | Height: | Size: 181 KiB |
Before Width: | Height: | Size: 315 KiB |
Before Width: | Height: | Size: 63 KiB |
Before Width: | Height: | Size: 98 KiB |
Before Width: | Height: | Size: 68 KiB |
Before Width: | Height: | Size: 114 KiB |
Before Width: | Height: | Size: 176 KiB |
Before Width: | Height: | Size: 74 KiB |
Before Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 236 KiB |
Before Width: | Height: | Size: 124 KiB |
Before Width: | Height: | Size: 477 KiB |
Before Width: | Height: | Size: 113 KiB |
Before Width: | Height: | Size: 214 KiB |
Before Width: | Height: | Size: 302 KiB |
Before Width: | Height: | Size: 1.1 MiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 101 KiB |
Before Width: | Height: | Size: 308 KiB |
@@ -1,9 +0,0 @@
|
||||
cd /d %~dp0
|
||||
|
||||
call path_define.bat
|
||||
|
||||
%UNITYEDITOR_PATH%/Unity.exe %WORKSPACE% -logFile %BUILD_LOGFILE% -executeMethod TEngine.ReleaseTools.AutomationBuildAndroid -quit -batchmode -CustomArgs:Language=en_US; %WORKSPACE%
|
||||
|
||||
@REM for /f "delims=[" %%i in (%BUILD_LOGFILE%) do echo %%i
|
||||
|
||||
pause
|
@@ -1,18 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
source ./path_define.sh
|
||||
|
||||
"${UNITYEDITOR_PATH}/Unity" "${WORKSPACE}" \
|
||||
-logFile "${BUILD_LOGFILE}" \
|
||||
-executeMethod TEngine.ReleaseTools.AutomationBuildAndroid \
|
||||
-quit -batchmode \
|
||||
-CustomArgs:Language=en_US "${WORKSPACE}"
|
||||
|
||||
while IFS= read -r line; do
|
||||
echo "$line"
|
||||
done < "${BUILD_LOGFILE}"
|
||||
|
||||
echo "按任意键继续..."
|
||||
read -k1
|
@@ -1,6 +0,0 @@
|
||||
cd /d %~dp0
|
||||
|
||||
set WORKSPACE=G:/github/TEngine/UnityProject
|
||||
set UNITYEDITOR_PATH=G:/UnityEditor/2021.3.20f1c1/Editor
|
||||
set BUILD_DLL_LOGFILE=./build_dll.log
|
||||
set BUILD_LOGFILE=./build.log
|
@@ -1,14 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
export WORKSPACE="/Users/your_user/github/TEngine/UnityProject" # 请替换为 macOS 上的实际路径
|
||||
export UNITYEDITOR_PATH="/Applications/Unity/Hub/Editor/2021.3.20f1c1/Unity.app/Contents/MacOS" # 请替换为 macOS 上的 Unity 路径
|
||||
export BUILD_DLL_LOGFILE="./build_dll.log"
|
||||
export BUILD_LOGFILE="./build.log"
|
||||
|
||||
echo "环境变量已设置:"
|
||||
echo "WORKSPACE=${WORKSPACE}"
|
||||
echo "UNITYEDITOR_PATH=${UNITYEDITOR_PATH}"
|
||||
echo "BUILD_DLL_LOGFILE=${BUILD_DLL_LOGFILE}"
|
||||
echo "BUILD_LOGFILE=${BUILD_LOGFILE}"
|
@@ -1,50 +0,0 @@
|
||||
using Luban;
|
||||
using GameBase;
|
||||
using GameConfig;
|
||||
using TEngine;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 配置加载器。
|
||||
/// </summary>
|
||||
public class ConfigSystem : Singleton<ConfigSystem>
|
||||
{
|
||||
private bool _init = false;
|
||||
|
||||
private Tables _tables;
|
||||
|
||||
public Tables Tables
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_init)
|
||||
{
|
||||
Load();
|
||||
}
|
||||
|
||||
return _tables;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载配置。
|
||||
/// </summary>
|
||||
public void Load()
|
||||
{
|
||||
_tables = new Tables(LoadByteBuf);
|
||||
_init = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载二进制配置。
|
||||
/// </summary>
|
||||
/// <param name="file">FileName</param>
|
||||
/// <returns>ByteBuf</returns>
|
||||
private ByteBuf LoadByteBuf(string file)
|
||||
{
|
||||
TextAsset textAsset = GameModule.Resource.LoadAsset<TextAsset>(file);
|
||||
byte[] bytes = textAsset.bytes;
|
||||
GameModule.Resource.UnloadAsset(textAsset);
|
||||
return new ByteBuf(bytes);
|
||||
}
|
||||
}
|
@@ -1,55 +0,0 @@
|
||||
using Luban;
|
||||
|
||||
{{namespace_with_grace_begin __namespace}}
|
||||
public partial class {{__name}}
|
||||
{
|
||||
#region The Tables
|
||||
|
||||
{{~for table in __tables ~}}
|
||||
{{~if table.comment != '' ~}}
|
||||
/// <summary>
|
||||
/// {{escape_comment table.comment}}
|
||||
/// </summary>
|
||||
{{~end~}}
|
||||
private {{table.full_name}} m_{{table.name}};
|
||||
public {{table.full_name}} {{format_property_name __code_style table.name}}
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_{{table.name}} == null)
|
||||
{
|
||||
m_{{table.name}} = new {{table.full_name}}(defaultLoader("{{table.output_data_file}}"));
|
||||
m_{{table.name}}.ResolveRef(this);
|
||||
}
|
||||
return m_{{table.name}};
|
||||
}
|
||||
set
|
||||
{
|
||||
m_{{table.name}} = value;
|
||||
m_{{table.name}}.ResolveRef(this);
|
||||
}
|
||||
}
|
||||
{{~end~}}
|
||||
|
||||
#endregion
|
||||
|
||||
System.Func<string, ByteBuf> defaultLoader;
|
||||
|
||||
public {{__name}}(System.Func<string, ByteBuf> loader)
|
||||
{
|
||||
SetDefaultLoader(loader);
|
||||
Init();
|
||||
}
|
||||
|
||||
public void SetDefaultLoader(System.Func<string, ByteBuf> loader)
|
||||
{
|
||||
defaultLoader = null;
|
||||
defaultLoader = loader;
|
||||
}
|
||||
|
||||
//public partial void Init();
|
||||
|
||||
public void Init(){}
|
||||
}
|
||||
|
||||
{{namespace_with_grace_end __namespace}}
|
@@ -1,17 +0,0 @@
|
||||
<module name="">
|
||||
<bean name="vector2" valueType="1" sep=",">
|
||||
<var name="x" type="float"/>
|
||||
<var name="y" type="float"/>
|
||||
</bean>
|
||||
<bean name="vector3" valueType="1" sep=",">
|
||||
<var name="x" type="float"/>
|
||||
<var name="y" type="float"/>
|
||||
<var name="z" type="float"/>
|
||||
</bean>
|
||||
<bean name="vector4" valueType="1" sep=",">
|
||||
<var name="x" type="float"/>
|
||||
<var name="y" type="float"/>
|
||||
<var name="z" type="float"/>
|
||||
<var name="w" type="float"/>
|
||||
</bean>
|
||||
</module>
|
@@ -1,20 +0,0 @@
|
||||
Cd /d %~dp0
|
||||
echo %CD%
|
||||
|
||||
set WORKSPACE=../..
|
||||
set LUBAN_DLL=%WORKSPACE%\Tools\Luban\Luban.dll
|
||||
set CONF_ROOT=.
|
||||
set DATA_OUTPATH=%WORKSPACE%/UnityProject/Assets/AssetRaw/Configs/bytes/
|
||||
set CODE_OUTPATH=%WORKSPACE%/UnityProject/Assets/GameScripts/HotFix/GameProto/GameConfig/
|
||||
|
||||
xcopy /s /e /i /y "%CONF_ROOT%\CustomTemplate\ConfigSystem.cs" "%WORKSPACE%\UnityProject\Assets\GameScripts\HotFix\GameProto\ConfigSystem.cs"
|
||||
|
||||
dotnet %LUBAN_DLL% ^
|
||||
-t client ^
|
||||
-c cs-bin ^
|
||||
-d bin^
|
||||
--conf %CONF_ROOT%\luban.conf ^
|
||||
-x outputCodeDir=%CODE_OUTPATH% ^
|
||||
-x outputDataDir=%DATA_OUTPATH%
|
||||
pause
|
||||
|
@@ -1,24 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
echo "当前目录: $(pwd)"
|
||||
|
||||
export WORKSPACE="$(realpath ../../)"
|
||||
export LUBAN_DLL="${WORKSPACE}/Tools/Luban/Luban.dll"
|
||||
export CONF_ROOT="$(pwd)"
|
||||
export DATA_OUTPATH="${WORKSPACE}/UnityProject/Assets/AssetRaw/Configs/bytes/"
|
||||
export CODE_OUTPATH="${WORKSPACE}/UnityProject/Assets/GameScripts/HotFix/GameProto/GameConfig/"
|
||||
|
||||
cp -R "${CONF_ROOT}/CustomTemplate/ConfigSystem.cs" \
|
||||
"${WORKSPACE}/UnityProject/Assets/GameScripts/HotFix/GameProto/ConfigSystem.cs"
|
||||
|
||||
dotnet "${LUBAN_DLL}" \
|
||||
-t client \
|
||||
-c cs-bin \
|
||||
-d bin \
|
||||
--conf "${CONF_ROOT}/luban.conf" \
|
||||
-x outputCodeDir="${CODE_OUTPATH}" \
|
||||
-x outputDataDir="${DATA_OUTPATH}"
|
||||
|
||||
echo "操作完成,按任意键退出..."
|
||||
read -k1
|
@@ -1,21 +0,0 @@
|
||||
Cd /d %~dp0
|
||||
echo %CD%
|
||||
|
||||
set WORKSPACE=../..
|
||||
set LUBAN_DLL=%WORKSPACE%\Tools\Luban\Luban.dll
|
||||
set CONF_ROOT=.
|
||||
set DATA_OUTPATH=%WORKSPACE%/UnityProject/Assets/AssetRaw/Configs/bytes/
|
||||
set CODE_OUTPATH=%WORKSPACE%/UnityProject/Assets/GameScripts/HotFix/GameProto/GameConfig/
|
||||
|
||||
xcopy /s /e /i /y "%CONF_ROOT%\CustomTemplate\ConfigSystem.cs" "%WORKSPACE%\UnityProject\Assets\GameScripts\HotFix\GameProto\ConfigSystem.cs"
|
||||
|
||||
dotnet %LUBAN_DLL% ^
|
||||
-t client ^
|
||||
-c cs-bin ^
|
||||
-d bin^
|
||||
--conf %CONF_ROOT%\luban.conf ^
|
||||
--customTemplateDir %CONF_ROOT%\CustomTemplate\CustomTemplate_Client_LazyLoad ^
|
||||
-x outputCodeDir=%CODE_OUTPATH% ^
|
||||
-x outputDataDir=%DATA_OUTPATH%
|
||||
pause
|
||||
|
@@ -1,25 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
echo "当前目录: $(pwd)"
|
||||
|
||||
export WORKSPACE="$(realpath ../../)"
|
||||
export LUBAN_DLL="${WORKSPACE}/Tools/Luban/Luban.dll"
|
||||
export CONF_ROOT="$(pwd)"
|
||||
export DATA_OUTPATH="${WORKSPACE}/UnityProject/Assets/AssetRaw/Configs/bytes/"
|
||||
export CODE_OUTPATH="${WORKSPACE}/UnityProject/Assets/GameScripts/HotFix/GameProto/GameConfig/"
|
||||
|
||||
cp -R "${CONF_ROOT}/CustomTemplate/ConfigSystem.cs" \
|
||||
"${WORKSPACE}/UnityProject/Assets/GameScripts/HotFix/GameProto/ConfigSystem.cs"
|
||||
|
||||
dotnet "${LUBAN_DLL}" \
|
||||
-t client \
|
||||
-c cs-bin \
|
||||
-d bin \
|
||||
--conf "${CONF_ROOT}/luban.conf" \
|
||||
--customTemplateDir "${CONF_ROOT}/CustomTemplate/CustomTemplate_Client_LazyLoad" \
|
||||
-x outputCodeDir="${CODE_OUTPATH}" \
|
||||
-x outputDataDir="${DATA_OUTPATH}"
|
||||
|
||||
echo "操作完成,按任意键退出..."
|
||||
read -k1
|
@@ -1,18 +0,0 @@
|
||||
Cd /d %~dp0
|
||||
echo %CD%
|
||||
|
||||
set WORKSPACE=../../
|
||||
set LUBAN_DLL=%WORKSPACE%/Tools/Luban/Luban.dll
|
||||
set CONF_ROOT=.
|
||||
set DATA_OUTPATH=%WORKSPACE%/Server/GameConfig
|
||||
set CODE_OUTPATH=%WORKSPACE%/Server/Hotfix/Config/GameConfig
|
||||
|
||||
dotnet %LUBAN_DLL% ^
|
||||
-t server^
|
||||
-c cs-bin ^
|
||||
-d bin^
|
||||
--conf %CONF_ROOT%\luban.conf ^
|
||||
-x outputCodeDir=%CODE_OUTPATH% ^
|
||||
-x outputDataDir=%DATA_OUTPATH%
|
||||
pause
|
||||
|
@@ -1,21 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
echo "当前目录: $(pwd)"
|
||||
|
||||
export WORKSPACE="$(realpath ../../)"
|
||||
export LUBAN_DLL="${WORKSPACE}/Tools/Luban/Luban.dll"
|
||||
export CONF_ROOT="$(pwd)"
|
||||
export DATA_OUTPATH="${WORKSPACE}/Server/GameConfig"
|
||||
export CODE_OUTPATH="${WORKSPACE}/Server/Hotfix/Config/GameConfig"
|
||||
|
||||
dotnet "${LUBAN_DLL}" \
|
||||
-t server \
|
||||
-c cs-bin \
|
||||
-d bin \
|
||||
--conf "${CONF_ROOT}/luban.conf" \
|
||||
-x outputCodeDir="${CODE_OUTPATH}" \
|
||||
-x outputDataDir="${DATA_OUTPATH}"
|
||||
|
||||
echo "操作完成,按任意键退出..."
|
||||
read -k1
|
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"groups":
|
||||
[
|
||||
{"names":["c"], "default":true},
|
||||
{"names":["s"], "default":true},
|
||||
{"names":["e"], "default":true}
|
||||
],
|
||||
"schemaFiles":
|
||||
[
|
||||
{"fileName":"Defines", "type":""},
|
||||
{"fileName":"Datas/__tables__.xlsx", "type":"table"},
|
||||
{"fileName":"Datas/__beans__.xlsx", "type":"bean"},
|
||||
{"fileName":"Datas/__enums__.xlsx", "type":"enum"}
|
||||
],
|
||||
"dataDir": "Datas",
|
||||
"targets":
|
||||
[
|
||||
{"name":"server", "manager":"Tables", "groups":["s"], "topModule":"GameConfig"},
|
||||
{"name":"client", "manager":"Tables", "groups":["c"], "topModule":"GameConfig"},
|
||||
{"name":"all", "manager":"Tables", "groups":["c,s,e"], "topModule":"GameConfig"}
|
||||
]
|
||||
}
|
51
README.md
@@ -33,6 +33,9 @@
|
||||
|
||||
#### TEngine是一个简单(新手友好开箱即用)且强大的Unity框架全平台解决方案,对于需要一套上手快、文档清晰、高性能且可拓展性极强的商业级解决方案的开发者或者团队来说是一个很好的选择。
|
||||
|
||||
|
||||
## <a href="http://1.12.241.46:5000/"><strong>文档快速入门 »</strong></a>
|
||||
|
||||
## 文档快速预览 - 5分钟
|
||||
* [全平台跑通示意](Books/99-各平台运行RunAble.md): 全平台跑通示意。
|
||||
* [01_介绍](Books/0-介绍.md): 简单介绍。
|
||||
@@ -43,54 +46,49 @@
|
||||
* [06_对象池模块](Books/3-4-%E5%AF%B9%E8%B1%A1%E6%B1%A0%E6%A8%A1%E5%9D%97.md): 展示对象池模块概览。
|
||||
* [07_配置表模块](Books/3-6-%E9%85%8D%E7%BD%AE%E8%A1%A8%E6%A8%A1%E5%9D%97.md): 展示配置表模块概览。
|
||||
* [08_流程模块](Books/3-7-%E6%B5%81%E7%A8%8B%E6%A8%A1%E5%9D%97.md): 展示商业化流程模块。
|
||||
* [09_UI模块](Books/3-5-UI模块.md): 展示商业化UI模块。
|
||||
|
||||
|
||||
## <strong>为什么要使用TEngine
|
||||
0. 开箱即用5分钟即可上手整套开发流程,代码整洁,思路清晰,功能强大。高内聚低耦合。您可以很轻易的把您不需要的模块进行移除替换。
|
||||
1. 严格按照商业要求使用次世代的HybridClr进行热更新、最佳的Luban配置表(TEngine支持懒加载、异步加载、同步加载配置。)、百万DAU游戏验证过的YooAsset资源框架(框架管理资源引用与释放。),全平台热更新流程已跑通。
|
||||
2. 严格按照商业化流程执行的热更新、商业化的UI开发流程、以及资源管理等等,设计并实现了YooAsset资源自动释放、支持LRU、ARC严格管理资源内存。
|
||||
3. 支持全平台,已有项目使用TEngine上架Steam、Wechat-minigame、AppStore。
|
||||
3. C#双端解决方案,服务器使用Fantasy,是一套源于ETServer,但极为简洁,性能更强,更好上手的一套商业级服务器框架。
|
||||
4. 支持全平台,已有项目使用TEngine上架Steam、Wechat-minigame、AppStore。
|
||||
|
||||
## <strong>最新的Demo飞机大战位于demo分支
|
||||
## <strong>资源重要拓展概念
|
||||
* AssetReference (资源引用标识) 通用加载资源的时候绑定一个引用标识使你无需关心手动Dispose资源句柄。
|
||||
|
||||
## <strong>服务器相关
|
||||
TEngine本身为纯净的客户端。不强绑定任何服务器。但是个人开发以及中小型公司开发双端则推荐C#服务器。
|
||||
* AssetGroup(资源组数据)进行资源分组绑定管理内存中的生命周期资源生命周期托管给资源组的根节点进行Dispose。
|
||||
|
||||
* LruCacheTable (Least Recently Used Cache缓存表)
|
||||
|
||||
* ArcCacheTable (Adaptive Replacement Cache缓存表)
|
||||
|
||||
## <strong>为什么服务器使用C#
|
||||
Net Core现在已经更新到了8.0的版本,在性能和设计上其实是远超JAVA和GO。在JAVAER还在为JVM更新和添加更多功能时,其实他们已经被国内大环境所包围了,看不到.Net Core的性能之强,组件化的结构。国内大环境是JAVA和GO的天下这个不可否认,但是国外C#也确实很多。其实.Net Core最大的问题是大多数自己人都不知道他的优点(AOT、JIT混合编译、热重载等等),甚至很多守旧派抵制core。GO喜欢吹性能,但其实目前来看,除了协程的轻量级,大多数性能测试其实不如JAVA和.Net。简单可以说出了C++的性能以外,Net Core其实都打得过。
|
||||
|
||||
需要服务器可以合并<a href="https://github.com/ALEXTANGXIAO/GameNetty"><strong>GameNetty</strong></a>过来,或者分支Fantasy为接好的带有Fantasy服务器的双端分支。
|
||||
<strong>当然作为商业级解决方案服务器的耦合度也极低,如果不喜欢您也可以很轻松直接移除替换成你的服务器。</strong>
|
||||
|
||||
## <strong>项目结构概览
|
||||
```
|
||||
Assets
|
||||
├── AssetArt // 美术资源目录
|
||||
│ └── Atlas // 自动生成图集目录
|
||||
├── AssetRaw // 热更资源目录
|
||||
│ ├── UIRaw // UI图片目录
|
||||
│ │ ├── Atlas // 需要自动生成图集的UI素材目录
|
||||
│ │ └── Raw // 不需要自动生成图集的UI素材目录
|
||||
├── Editor // 编辑器脚本目录
|
||||
├── Atlas // 自动生成图集目录
|
||||
├── HybridCLRData // hybridclr相关目录
|
||||
├── Scenes // 主场景目录
|
||||
├── TEngine // 框架核心目录
|
||||
└── GameScripts // 程序集目录
|
||||
├── Editor // 编辑器程序集
|
||||
├── Main // 主程序程序集(启动器与流程)
|
||||
└── HotFix // 游戏热更程序集目录 [Folder]
|
||||
├── GameBase // 游戏基础框架程序集 [Dll]
|
||||
├── GameProto // 游戏配置协议程序集 [Dll]
|
||||
├── GameProto // 游戏配置协议程序集 [Dll]
|
||||
├── BattleCore // 游戏核心战斗程序集 [Dll]
|
||||
└── GameLogic // 游戏业务逻辑程序集 [Dll]
|
||||
├── GameApp.cs // 热更主入口
|
||||
└── GameApp_RegisterSystem.cs // 热更主入口注册系统
|
||||
|
||||
|
||||
TEngine
|
||||
├── Editor // TEngine编辑器核心代码
|
||||
└── Runtime // TEngine运行时核心代码
|
||||
└── GameApp_RegisterSystem.cs // 热更主入口注册系统
|
||||
```
|
||||
|
||||
- 必要:项目使用了以下第三方插件,请自行购买导入:
|
||||
- /UnityProject/Assets/Plugins/Sirenix
|
||||
- /Unity/Assets/Plugins/Sirenix
|
||||
|
||||
---
|
||||
## <strong>优质开源项目推荐
|
||||
@@ -101,11 +99,4 @@ TEngine
|
||||
|
||||
#### <a href="https://github.com/focus-creative-games/hybridclr"><strong>HybridCLR</strong></a> - 特性完整、零成本、高性能、低内存的近乎完美的Unity全平台原生c#热更方案
|
||||
|
||||
#### <a href="https://github.com/qq362946/Fantasy"><strong>Fantasy</strong></a> - Fantasy是一套源于ETServer但极为简洁,更好上手的一套商业级服务器框架。
|
||||
|
||||
#### <a href="https://github.com/ALEXTANGXIAO/GameNetty"><strong>GameNetty</strong></a> - GameNetty是一套源于ETServer,首次拆分最新的ET8.1的前后端解决方案(包),客户端最精简大约750k,完美做成包的形式,几乎零成本 无侵入的嵌入进你的框架。
|
||||
|
||||
|
||||
## <strong>Buy me a 奶茶.
|
||||
|
||||
[您的赞助会让我们做得更快更好,如果觉得TEngine对您有帮助,不妨请我可爱的女儿买杯奶茶吧~](Books/Donate.md)
|
||||
#### <a href="https://github.com/qq362946/Fantasy"><strong>Fantasy</strong></a> - Fantasy是一套源于ETServer但极为简洁,性能更强,更好上手的一套商业级服务器框架。
|
||||
|
8
Tools/FileServer/.gitignore
vendored
@@ -1,8 +0,0 @@
|
||||
node_modules
|
||||
*.swap
|
||||
.idea
|
||||
.DS_Store
|
||||
*.log
|
||||
.vscode
|
||||
*-lock.json
|
||||
AssetsRoot
|
@@ -1,42 +0,0 @@
|
||||
## 使用node搭建静态资源服务器
|
||||
|
||||
### 安装
|
||||
|
||||
```bash
|
||||
npm install yumu-static-server -g
|
||||
```
|
||||
|
||||
### 使用
|
||||
|
||||
```bash
|
||||
server # 会在当前目录下启动一个静态资源服务器,默认端口为8080
|
||||
|
||||
server -p[port] 3000 # 会在当前目录下启动一个静态资源服务器,端口为3000
|
||||
|
||||
server -i[index] index.html # 设置文件夹在默认加载的文件
|
||||
|
||||
server -c[charset] UTF-8 # 设置文件默认加载的字符编码
|
||||
|
||||
server -cors # 开启文件跨域
|
||||
|
||||
server -h[https] # 开启https服务
|
||||
|
||||
server --openindex # 是否打开默认页面
|
||||
|
||||
server --no-openbrowser # 关闭自动打开浏览器
|
||||
```
|
||||
|
||||
### 基本功能
|
||||
|
||||
1. 启动静态资源服务器
|
||||
2. 端口可配置
|
||||
3. 字符编码可配置
|
||||
4. 文件夹下默认加载文件可配置
|
||||
5. 是否跨域可配置
|
||||
6. 开启https服务
|
||||
|
||||
### TODO
|
||||
|
||||
- [x] 引入handlerbars编译模板
|
||||
- [x] 支持文件是否跨域
|
||||
- [x] 支持https服务
|
@@ -1,26 +0,0 @@
|
||||
const StaticServer = require('../src/static-server');
|
||||
|
||||
const options = require('yargs')
|
||||
.option('p', { alias: 'port', describe: '设置服务启动的端口号', type: 'number' })
|
||||
.option('i', { alias: 'index', describe: '设置默认打开的主页', type: 'string' })
|
||||
.option('c', { alias: 'charset', describe: '设置文件的默认字符集', type: 'string' })
|
||||
.option('o', { alias: 'openindex', describe: '是否打开默认页面', type: 'boolean' })
|
||||
.option('h', { alias: 'https', describe: '是否启用https服务', type: 'boolean' })
|
||||
.option('cors', { describe: '是否开启文件跨域', type: 'boolean' })
|
||||
.option('openbrowser', { describe: '是否默认打开浏览器', type: 'boolean' })
|
||||
|
||||
// 默认参数
|
||||
.default('openbrowser', true)
|
||||
// .default('https', true)
|
||||
.default('port', 8080)
|
||||
.default('index', 'index.html')
|
||||
.default('openindex', 'index.html')
|
||||
.default('charset', 'UTF-8')
|
||||
|
||||
.help()
|
||||
.alias('?', 'help')
|
||||
|
||||
.argv;
|
||||
|
||||
const server = new StaticServer(options);
|
||||
server.start();
|
@@ -1,3 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
module.exports = require('./bin/app.js');
|
@@ -1 +0,0 @@
|
||||
npm install yumu-static-server -g
|
@@ -1,3 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
npm install yumu-static-server -g
|
@@ -1,30 +0,0 @@
|
||||
{
|
||||
"name": "static-server",
|
||||
"version": "0.0.1",
|
||||
"description": "使用node搭建静态资源服务器",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"dev": "supervisor bin/app.js",
|
||||
"start": "npm run dev"
|
||||
},
|
||||
"bin": {
|
||||
"server": "index.js"
|
||||
},
|
||||
"author": "Alex",
|
||||
"license": "ISC",
|
||||
"keywords": [
|
||||
"static-server",
|
||||
"server"
|
||||
],
|
||||
"dependencies": {
|
||||
"chalk": "^2.3.2",
|
||||
"handlebars": "^4.0.11",
|
||||
"mime": "^2.2.0",
|
||||
"open": "^7.1.0",
|
||||
"pem": "^1.12.5",
|
||||
"yargs": "^6.6.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"supervisor": "^0.12.0"
|
||||
}
|
||||
}
|
@@ -1,12 +0,0 @@
|
||||
const path = require('path');
|
||||
const mime = require('mime');
|
||||
|
||||
const lookup = (pathName) => {
|
||||
let ext = path.extname(pathName);
|
||||
ext = ext.split('.').pop();
|
||||
return mime.getType(ext) || mime.getType('txt');
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
lookup
|
||||
};
|
@@ -1,334 +0,0 @@
|
||||
const http = require('http');
|
||||
const https = require('https');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const url = require('url');
|
||||
const zlib = require('zlib');
|
||||
const chalk = require('chalk');
|
||||
const os = require('os');
|
||||
const open = require("open");
|
||||
const Handlebars = require('handlebars');
|
||||
const pem = require('pem');
|
||||
const mime = require('./mime');
|
||||
const Template = require('./templates');
|
||||
|
||||
const _defaultTemplate = Handlebars.compile(Template.page_dafault);
|
||||
const _404TempLate = Handlebars.compile(Template.page_404);
|
||||
|
||||
const hasTrailingSlash = url => url[url.length - 1] === '/';
|
||||
|
||||
const ifaces = os.networkInterfaces();
|
||||
|
||||
class StaticServer {
|
||||
constructor(options) {
|
||||
this.port = options.port;
|
||||
this.indexPage = options.index;
|
||||
this.openIndexPage = options.openindex;
|
||||
this.openBrowser = options.openbrowser;
|
||||
this.charset = options.charset;
|
||||
this.cors = options.cors;
|
||||
this.protocal = options.https ? 'https' : 'http';
|
||||
this.zipMatch = '^\\.(css|js|html)$';
|
||||
}
|
||||
|
||||
/**
|
||||
* 响应错误
|
||||
*
|
||||
* @param {*} err
|
||||
* @param {*} res
|
||||
* @returns
|
||||
* @memberof StaticServer
|
||||
*/
|
||||
respondError(err, res) {
|
||||
res.writeHead(500);
|
||||
return res.end(err);
|
||||
}
|
||||
|
||||
/**
|
||||
* 响应404
|
||||
*
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
* @memberof StaticServer
|
||||
*/
|
||||
respondNotFound(req, res) {
|
||||
res.writeHead(404, {
|
||||
'Content-Type': 'text/html'
|
||||
});
|
||||
const html = _404TempLate();
|
||||
res.end(html);
|
||||
}
|
||||
|
||||
respond(pathName, req, res) {
|
||||
fs.stat(pathName, (err, stat) => {
|
||||
if (err) return respondError(err, res);
|
||||
this.responseFile(stat, pathName, req, res);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否需要解压
|
||||
*
|
||||
* @param {*} pathName
|
||||
* @returns
|
||||
* @memberof StaticServer
|
||||
*/
|
||||
shouldCompress(pathName) {
|
||||
return path.extname(pathName).match(this.zipMatch);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解压文件
|
||||
*
|
||||
* @param {*} readStream
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
* @returns
|
||||
* @memberof StaticServer
|
||||
*/
|
||||
compressHandler(readStream, req, res) {
|
||||
const acceptEncoding = req.headers['accept-encoding'];
|
||||
if (!acceptEncoding || !acceptEncoding.match(/\b(gzip|deflate)\b/)) {
|
||||
return readStream;
|
||||
} else if (acceptEncoding.match(/\bgzip\b/)) {
|
||||
res.setHeader('Content-Encoding', 'gzip');
|
||||
return readStream.pipe(zlib.createGzip());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 响应文件路径
|
||||
*
|
||||
* @param {*} stat
|
||||
* @param {*} pathName
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
* @memberof StaticServer
|
||||
*/
|
||||
responseFile(stat, pathName, req, res) {
|
||||
// 设置响应头
|
||||
res.setHeader('Content-Type', `${mime.lookup(pathName)}; charset=${this.charset}`);
|
||||
res.setHeader('Accept-Ranges', 'bytes');
|
||||
|
||||
// 添加跨域
|
||||
if (this.cors) res.setHeader('Access-Control-Allow-Origin', '*');
|
||||
|
||||
let readStream;
|
||||
readStream = fs.createReadStream(pathName);
|
||||
if (this.shouldCompress(pathName)) { // 判断是否需要解压
|
||||
readStream = this.compressHandler(readStream, req, res);
|
||||
}
|
||||
readStream.pipe(res);
|
||||
}
|
||||
|
||||
/**
|
||||
* 响应重定向
|
||||
*
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
* @memberof StaticServer
|
||||
*/
|
||||
respondRedirect(req, res) {
|
||||
const location = req.url + '/';
|
||||
res.writeHead(301, {
|
||||
'Location': location,
|
||||
'Content-Type': 'text/html'
|
||||
});
|
||||
const html = _defaultTemplate({
|
||||
htmlStr: `Redirecting to <a href='${location}'>${location}</a>`,
|
||||
showFileList: false
|
||||
})
|
||||
res.end(html);
|
||||
}
|
||||
|
||||
/**
|
||||
* 响应文件夹路径
|
||||
*
|
||||
* @param {*} pathName
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
* @memberof StaticServer
|
||||
*/
|
||||
respondDirectory(pathName, req, res) {
|
||||
const indexPagePath = path.join(pathName, this.indexPage);
|
||||
// 如果文件夹下存在index.html,则默认打开
|
||||
if (this.openIndexPage && fs.existsSync(indexPagePath)) {
|
||||
this.respond(indexPagePath, req, res);
|
||||
} else {
|
||||
fs.readdir(pathName, (err, files) => {
|
||||
if (err) {
|
||||
respondError(err, res);
|
||||
}
|
||||
const requestPath = url.parse(req.url).pathname;
|
||||
const fileList = [];
|
||||
files.forEach(fileName => {
|
||||
let itemLink = path.join(requestPath, fileName);
|
||||
let isDirectory = false;
|
||||
const stat = fs.statSync(path.join(pathName, fileName));
|
||||
if (stat && stat.isDirectory()) {
|
||||
itemLink = path.join(itemLink, '/');
|
||||
isDirectory = true;
|
||||
}
|
||||
fileList.push({
|
||||
link: itemLink,
|
||||
name: fileName,
|
||||
isDirectory
|
||||
});
|
||||
});
|
||||
// 排序,目录在前,文件在后
|
||||
fileList.sort((prev, next) => {
|
||||
if (prev.isDirectory && !next.isDirectory) {
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
});
|
||||
res.writeHead(200, {
|
||||
'Content-Type': 'text/html'
|
||||
});
|
||||
const html = _defaultTemplate({
|
||||
requestPath,
|
||||
fileList,
|
||||
showFileList: true
|
||||
})
|
||||
res.end(html);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 路由处理
|
||||
*
|
||||
* @param {*} pathName
|
||||
* @param {*} req
|
||||
* @param {*} res
|
||||
* @memberof StaticServer
|
||||
*/
|
||||
routeHandler(pathName, req, res) {
|
||||
const realPathName = pathName.split('?')[0];
|
||||
fs.stat(realPathName, (err, stat) => {
|
||||
this.logGetInfo(err, pathName);
|
||||
if (!err) {
|
||||
const requestedPath = url.parse(req.url).pathname;
|
||||
// 检查url
|
||||
// 如果末尾有'/',且是文件夹,则读取文件夹
|
||||
// 如果是文件夹,但末尾没'/',则重定向至'xxx/'
|
||||
// 如果是文件,则判断是否是压缩文件,是则解压,不是则读取文件
|
||||
if (hasTrailingSlash(requestedPath) && stat.isDirectory()) {
|
||||
this.respondDirectory(realPathName, req, res);
|
||||
} else if (stat.isDirectory()) {
|
||||
this.respondRedirect(req, res);
|
||||
} else {
|
||||
this.respond(realPathName, req, res);
|
||||
}
|
||||
} else {
|
||||
this.respondNotFound(req, res);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 打印ip地址
|
||||
*
|
||||
* @memberof StaticServer
|
||||
*/
|
||||
logUsingPort() {
|
||||
const me = this;
|
||||
console.log(`${chalk.yellow(`Starting up your server\nAvailable on:`)}`);
|
||||
Object.keys(ifaces).forEach(function (dev) {
|
||||
ifaces[dev].forEach(function (details) {
|
||||
if (details.family === 'IPv4') {
|
||||
console.log(` ${me.protocal}://${details.address}:${chalk.green(me.port)}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
console.log(`${chalk.cyan(Array(50).fill('-').join(''))}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打印占用端口
|
||||
*
|
||||
* @param {*} oldPort
|
||||
* @param {*} port
|
||||
* @memberof StaticServer
|
||||
*/
|
||||
logUsedPort(oldPort, port) {
|
||||
const me = this;
|
||||
console.log(`${chalk.red(`The port ${oldPort} is being used, change to port `)}${chalk.green(me.port)} `);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打印https证书友好提示
|
||||
*
|
||||
* @memberof StaticServer
|
||||
*/
|
||||
logHttpsTrusted() {
|
||||
console.log(chalk.green('Currently is using HTTPS certificate (Manually trust it if necessary)'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 打印路由路径输出
|
||||
*
|
||||
* @param {*} isError
|
||||
* @param {*} pathName
|
||||
* @memberof StaticServer
|
||||
*/
|
||||
logGetInfo(isError, pathName) {
|
||||
if (isError) {
|
||||
console.log(chalk.red(`404 ${pathName}`));
|
||||
} else {
|
||||
console.log(chalk.cyan(`200 ${pathName}`));
|
||||
}
|
||||
}
|
||||
|
||||
startServer(keys) {
|
||||
const me = this;
|
||||
let isPostBeUsed = false;
|
||||
const oldPort = me.port;
|
||||
const protocal = me.protocal === 'https' ? https : http;
|
||||
const options = me.protocal === 'https' ? { key: keys.serviceKey, cert: keys.certificate } : null;
|
||||
const callback = (req, res) => {
|
||||
const pathName = path.join(process.cwd(), path.normalize(decodeURI(req.url)));
|
||||
me.routeHandler(pathName, req, res);
|
||||
};
|
||||
const params = [callback];
|
||||
if (me.protocal === 'https') params.unshift(options);
|
||||
const server = protocal.createServer(...params).listen(me.port);
|
||||
server.on('listening', function () { // 执行这块代码说明端口未被占用
|
||||
if (isPostBeUsed) {
|
||||
me.logUsedPort(oldPort, me.port);
|
||||
}
|
||||
me.logUsingPort();
|
||||
if (me.openBrowser) {
|
||||
open(`${me.protocal}://127.0.0.1:${me.port}`);
|
||||
}
|
||||
});
|
||||
|
||||
server.on('error', function (err) {
|
||||
if (err.code === 'EADDRINUSE') { // 端口已经被使用
|
||||
isPostBeUsed = true;
|
||||
me.port = parseInt(me.port) + 1;
|
||||
server.listen(me.port);
|
||||
} else {
|
||||
console.log(err);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
start() {
|
||||
const me = this;
|
||||
if (this.protocal === 'https') {
|
||||
pem.createCertificate({ days: 1, selfSigned: true }, function (err, keys) {
|
||||
if (err) {
|
||||
throw err
|
||||
}
|
||||
me.logHttpsTrusted();
|
||||
me.startServer(keys);
|
||||
})
|
||||
} else {
|
||||
me.startServer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = StaticServer;
|
@@ -1,44 +0,0 @@
|
||||
module.exports = `
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge"/>
|
||||
<title>node静态服务器</title>
|
||||
<style>
|
||||
.not-found-content {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
min-height: 500px;
|
||||
align-items: center;
|
||||
}
|
||||
.not-found-content .img-notfound {
|
||||
margin-right: 50px;
|
||||
}
|
||||
.not-found-content h3 {
|
||||
color: #333;
|
||||
font-size: 24px;
|
||||
margin: 20px 0;
|
||||
font-weight: 400;
|
||||
line-height: 24px;
|
||||
}
|
||||
.not-found-content p {
|
||||
color: #666;
|
||||
font-size: 16px;
|
||||
line-height: 20px;
|
||||
margin-bottom: 7px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="not-found-content">
|
||||
<img src="https://img.alicdn.com/tfs/TB1txw7bNrI8KJjy0FpXXb5hVXa-260-260.png" class="img-notfound" alt="not found">
|
||||
<div class="prompt">
|
||||
<h3>抱歉,你访问的路径不存在</h3>
|
||||
<p>您要找的页面没有找到,请返回<a class="link-font" href="/">首页</a>继续浏览</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
`
|
@@ -1,93 +0,0 @@
|
||||
module.exports = `
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<title>node静态服务器</title>
|
||||
<style>
|
||||
html, body, ul, li, p{
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
html, body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.app {
|
||||
padding: 20px 50px 0;
|
||||
min-height: calc(100% - 70px);
|
||||
overflow: hidden;
|
||||
color: #333;
|
||||
}
|
||||
.directory li {
|
||||
list-style: circle;
|
||||
margin-left: 20px;
|
||||
}
|
||||
.directory li p {
|
||||
line-height: 1.7;
|
||||
margin: 14px 0;
|
||||
}
|
||||
.directory li p a{
|
||||
color: #333;
|
||||
font-weight: 400;
|
||||
text-decoration: none;
|
||||
}
|
||||
.directory li p span{
|
||||
color: #3dcccc;
|
||||
}
|
||||
.directory li p a:hover {
|
||||
color: red;
|
||||
}
|
||||
.footer {
|
||||
text-align: center;
|
||||
height: 50px;
|
||||
font-size: 12px;
|
||||
}
|
||||
.footer span {
|
||||
display: block;
|
||||
line-height: 24px;
|
||||
}
|
||||
.footer .bold {
|
||||
font-weight: 600;
|
||||
}
|
||||
.footer a {
|
||||
color: #333;
|
||||
}
|
||||
.footer a:hover {
|
||||
color: red;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="app">
|
||||
<h3>当前目录:<span>{{requestPath}}</span></h3>
|
||||
{{#if showFileList}}
|
||||
<ul class="directory">
|
||||
{{#each fileList}}
|
||||
<li>
|
||||
<p>
|
||||
{{#if isDirectory }}
|
||||
<span>「目录」</span>
|
||||
{{else}}
|
||||
<span>「文件」</span>
|
||||
{{/if}}
|
||||
<a href='{{link}}'>{{name}}</a>
|
||||
</p>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
{{else}}
|
||||
{{htmlStr}}
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="footer">
|
||||
<span>Github地址: <a target="_blank" href="https://github.com/WisestCoder/static-server">https://github.com/WisestCoder/static-server</a></span>
|
||||
<span class="bold">By <a target="_blank" href="https://github.com/WisestCoder">WisestCoder</a></span>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
`;
|
Before Width: | Height: | Size: 12 KiB |
@@ -1,7 +0,0 @@
|
||||
const page_dafault = require('./default');
|
||||
const page_404 = require('./404');
|
||||
|
||||
module.exports = {
|
||||
page_dafault,
|
||||
page_404
|
||||
};
|
@@ -1 +0,0 @@
|
||||
server -p 8081 -cors
|
@@ -1,3 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
server -p 8081 -cors
|
@@ -1 +0,0 @@
|
||||
使用luban-next, 请前往Tools/build-luban编译或者自行导入
|
@@ -1,5 +0,0 @@
|
||||
rd /s /q Luban
|
||||
|
||||
dotnet build ../../luban/src/Luban/Luban.csproj -c Release -o Luban
|
||||
|
||||
pause
|
@@ -1,5 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
[ -d Luban ] && rm -rf Luban
|
||||
|
||||
dotnet build ../../luban/src/Luban/Luban.csproj -c Release -o Luban
|
1
UnityProject/.gitignore
vendored
@@ -90,7 +90,6 @@ Sandbox/
|
||||
# [Aa]ssets/Plugins/Sirenix.meta
|
||||
|
||||
#YooAssets
|
||||
package/
|
||||
yoo/
|
||||
[Aa]ssets/TEngine/AssetSetting/Resources/BuiltinFileManifest.asset
|
||||
[Aa]ssets/TEngine/AssetSetting/Resources/BuiltinFileManifest.asset.meta
|
@@ -0,0 +1,52 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!612988286 &4096168566840163508
|
||||
SpriteAtlasAsset:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: UIRaw_Atlas_Battle
|
||||
m_MasterAtlas: {fileID: 0}
|
||||
m_ImporterData:
|
||||
serializedVersion: 2
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
anisoLevel: 0
|
||||
compressionQuality: 0
|
||||
maxTextureSize: 0
|
||||
textureCompression: 0
|
||||
filterMode: 1
|
||||
generateMipMaps: 0
|
||||
readable: 0
|
||||
crunchedCompression: 0
|
||||
sRGB: 1
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
m_BuildTarget: iPhone
|
||||
m_MaxTextureSize: 2048
|
||||
m_ResizeAlgorithm: 0
|
||||
m_TextureFormat: 49
|
||||
m_TextureCompression: 1
|
||||
m_CompressionQuality: 100
|
||||
m_CrunchedCompression: 0
|
||||
m_AllowsAlphaSplitting: 0
|
||||
m_Overridden: 1
|
||||
m_AndroidETC2FallbackOverride: 0
|
||||
m_ForceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
packingSettings:
|
||||
serializedVersion: 2
|
||||
padding: 2
|
||||
blockOffset: 1
|
||||
allowAlphaSplitting: 0
|
||||
enableRotation: 1
|
||||
enableTightPacking: 0
|
||||
enableAlphaDilation: 0
|
||||
secondaryTextureSettings: {}
|
||||
variantMultiplier: 1
|
||||
packables:
|
||||
- {fileID: 21300000, guid: b76b8b216adf64f4bbdb78f7977f0310, type: 3}
|
||||
bindAsDefault: 1
|
||||
isAtlasV2: 1
|
||||
cachedData: {fileID: 0}
|
||||
m_IsVariant: 0
|
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 736bc06e2873e08418fef3194a34eeaf
|
||||
SpriteAtlasImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,13 +1,14 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!687078895 &4343727234628468602
|
||||
SpriteAtlas:
|
||||
--- !u!612988286 &4096168566840163508
|
||||
SpriteAtlasAsset:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: UIRaw_Atlas_Common
|
||||
m_EditorData:
|
||||
m_MasterAtlas: {fileID: 0}
|
||||
m_ImporterData:
|
||||
serializedVersion: 2
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
@@ -33,30 +34,6 @@ SpriteAtlas:
|
||||
m_Overridden: 1
|
||||
m_AndroidETC2FallbackOverride: 0
|
||||
m_ForceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
m_BuildTarget: Android
|
||||
m_MaxTextureSize: 2048
|
||||
m_ResizeAlgorithm: 0
|
||||
m_TextureFormat: 50
|
||||
m_TextureCompression: 1
|
||||
m_CompressionQuality: 100
|
||||
m_CrunchedCompression: 0
|
||||
m_AllowsAlphaSplitting: 0
|
||||
m_Overridden: 1
|
||||
m_AndroidETC2FallbackOverride: 0
|
||||
m_ForceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
m_BuildTarget: WebGL
|
||||
m_MaxTextureSize: 2048
|
||||
m_ResizeAlgorithm: 0
|
||||
m_TextureFormat: 50
|
||||
m_TextureCompression: 1
|
||||
m_CompressionQuality: 50
|
||||
m_CrunchedCompression: 0
|
||||
m_AllowsAlphaSplitting: 0
|
||||
m_Overridden: 1
|
||||
m_AndroidETC2FallbackOverride: 0
|
||||
m_ForceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
packingSettings:
|
||||
serializedVersion: 2
|
||||
padding: 2
|
||||
@@ -73,19 +50,6 @@ SpriteAtlas:
|
||||
- {fileID: 21300000, guid: d623a2b7e069a4c4592d3da48f476189, type: 3}
|
||||
- {fileID: 21300000, guid: 57e4117f4cd6ae54284898652e70d553, type: 3}
|
||||
bindAsDefault: 1
|
||||
isAtlasV2: 0
|
||||
isAtlasV2: 1
|
||||
cachedData: {fileID: 0}
|
||||
m_MasterAtlas: {fileID: 0}
|
||||
m_PackedSprites:
|
||||
- {fileID: 21300000, guid: 2761fc23b4aa7e34187ac5ffbc3fad9b, type: 3}
|
||||
- {fileID: 21300000, guid: f9a06e163014f4f46b14f4499d3e7240, type: 3}
|
||||
- {fileID: 21300000, guid: d623a2b7e069a4c4592d3da48f476189, type: 3}
|
||||
- {fileID: 21300000, guid: 57e4117f4cd6ae54284898652e70d553, type: 3}
|
||||
m_PackedSpriteNamesToIndex:
|
||||
- red_button
|
||||
- blue_button
|
||||
- white_background
|
||||
- white_button
|
||||
m_RenderDataMap: {}
|
||||
m_Tag: UIRaw_Atlas_Common
|
||||
m_IsVariant: 0
|
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b9eaf6bdacd0683468b1dd697e3d2bce
|
||||
SpriteAtlasImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,59 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!612988286 &4096168566840163508
|
||||
SpriteAtlasAsset:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: UIRaw_Atlas_arrows
|
||||
m_MasterAtlas: {fileID: 0}
|
||||
m_ImporterData:
|
||||
serializedVersion: 2
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
anisoLevel: 0
|
||||
compressionQuality: 0
|
||||
maxTextureSize: 0
|
||||
textureCompression: 0
|
||||
filterMode: 1
|
||||
generateMipMaps: 0
|
||||
readable: 0
|
||||
crunchedCompression: 0
|
||||
sRGB: 1
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
m_BuildTarget: iPhone
|
||||
m_MaxTextureSize: 2048
|
||||
m_ResizeAlgorithm: 0
|
||||
m_TextureFormat: 49
|
||||
m_TextureCompression: 1
|
||||
m_CompressionQuality: 100
|
||||
m_CrunchedCompression: 0
|
||||
m_AllowsAlphaSplitting: 0
|
||||
m_Overridden: 1
|
||||
m_AndroidETC2FallbackOverride: 0
|
||||
m_ForceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
packingSettings:
|
||||
serializedVersion: 2
|
||||
padding: 2
|
||||
blockOffset: 1
|
||||
allowAlphaSplitting: 0
|
||||
enableRotation: 1
|
||||
enableTightPacking: 0
|
||||
enableAlphaDilation: 0
|
||||
secondaryTextureSettings: {}
|
||||
variantMultiplier: 1
|
||||
packables:
|
||||
- {fileID: 21300000, guid: 9871e4d5e19cea6419d057b79ce1a1a8, type: 3}
|
||||
- {fileID: 21300000, guid: b1e9e5e05f0067f469e748e46985c269, type: 3}
|
||||
- {fileID: 21300000, guid: 6d7b5d72581e8ca48b333e83a25d1514, type: 3}
|
||||
- {fileID: 21300000, guid: e05004e4bcd8b3e49bb0cbaab0215760, type: 3}
|
||||
- {fileID: 21300000, guid: a9ef9e2f50f97a84bbd269b5f7cc5ea4, type: 3}
|
||||
- {fileID: 21300000, guid: 5d663ef25d3d5514a8d099e72353244b, type: 3}
|
||||
- {fileID: 21300000, guid: e9b8cd94ede145942a15f9e164af30a9, type: 3}
|
||||
- {fileID: 21300000, guid: 36909c7c187739945aecb80f7c59fa4c, type: 3}
|
||||
bindAsDefault: 1
|
||||
isAtlasV2: 1
|
||||
cachedData: {fileID: 0}
|
||||
m_IsVariant: 0
|
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 30b2151baa80324468b12076c6025e5c
|
||||
SpriteAtlasImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,55 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!612988286 &4096168566840163508
|
||||
SpriteAtlasAsset:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: UIRaw_Atlas_bars
|
||||
m_MasterAtlas: {fileID: 0}
|
||||
m_ImporterData:
|
||||
serializedVersion: 2
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
anisoLevel: 0
|
||||
compressionQuality: 0
|
||||
maxTextureSize: 0
|
||||
textureCompression: 0
|
||||
filterMode: 1
|
||||
generateMipMaps: 0
|
||||
readable: 0
|
||||
crunchedCompression: 0
|
||||
sRGB: 1
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
m_BuildTarget: iPhone
|
||||
m_MaxTextureSize: 2048
|
||||
m_ResizeAlgorithm: 0
|
||||
m_TextureFormat: 49
|
||||
m_TextureCompression: 1
|
||||
m_CompressionQuality: 100
|
||||
m_CrunchedCompression: 0
|
||||
m_AllowsAlphaSplitting: 0
|
||||
m_Overridden: 1
|
||||
m_AndroidETC2FallbackOverride: 0
|
||||
m_ForceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
packingSettings:
|
||||
serializedVersion: 2
|
||||
padding: 2
|
||||
blockOffset: 1
|
||||
allowAlphaSplitting: 0
|
||||
enableRotation: 1
|
||||
enableTightPacking: 0
|
||||
enableAlphaDilation: 0
|
||||
secondaryTextureSettings: {}
|
||||
variantMultiplier: 1
|
||||
packables:
|
||||
- {fileID: 21300000, guid: ba523fd85bea1e448944fe8cabed4b59, type: 3}
|
||||
- {fileID: 21300000, guid: 20960a9e1f7b68c4f80d5078f5964057, type: 3}
|
||||
- {fileID: 21300000, guid: be40ff228ca528248b495d5025a1e327, type: 3}
|
||||
- {fileID: 21300000, guid: fcabe002e685bc147918c97e9538d17f, type: 3}
|
||||
bindAsDefault: 1
|
||||
isAtlasV2: 1
|
||||
cachedData: {fileID: 0}
|
||||
m_IsVariant: 0
|
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7180c75b26a0aa046b5743fbddb78c45
|
||||
SpriteAtlasImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,57 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!612988286 &4096168566840163508
|
||||
SpriteAtlasAsset:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: UIRaw_Atlas_buttons
|
||||
m_MasterAtlas: {fileID: 0}
|
||||
m_ImporterData:
|
||||
serializedVersion: 2
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
anisoLevel: 0
|
||||
compressionQuality: 0
|
||||
maxTextureSize: 0
|
||||
textureCompression: 0
|
||||
filterMode: 1
|
||||
generateMipMaps: 0
|
||||
readable: 0
|
||||
crunchedCompression: 0
|
||||
sRGB: 1
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
m_BuildTarget: iPhone
|
||||
m_MaxTextureSize: 2048
|
||||
m_ResizeAlgorithm: 0
|
||||
m_TextureFormat: 49
|
||||
m_TextureCompression: 1
|
||||
m_CompressionQuality: 100
|
||||
m_CrunchedCompression: 0
|
||||
m_AllowsAlphaSplitting: 0
|
||||
m_Overridden: 1
|
||||
m_AndroidETC2FallbackOverride: 0
|
||||
m_ForceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
packingSettings:
|
||||
serializedVersion: 2
|
||||
padding: 2
|
||||
blockOffset: 1
|
||||
allowAlphaSplitting: 0
|
||||
enableRotation: 1
|
||||
enableTightPacking: 0
|
||||
enableAlphaDilation: 0
|
||||
secondaryTextureSettings: {}
|
||||
variantMultiplier: 1
|
||||
packables:
|
||||
- {fileID: 21300000, guid: fcab35236e33438448805a9211b0cc19, type: 3}
|
||||
- {fileID: 21300000, guid: 8a6f536f4b2392f40afb62df609f6e40, type: 3}
|
||||
- {fileID: 21300000, guid: 67c34bb955c72e6419b7528e10e73c53, type: 3}
|
||||
- {fileID: 21300000, guid: 03cbfa7fbded80a479f24add4a997757, type: 3}
|
||||
- {fileID: 21300000, guid: 379c45e0c5ba5e54e8df03f52e4c7680, type: 3}
|
||||
- {fileID: 21300000, guid: 3b8db7241fc8ff54e9dea6fc64cfd7e5, type: 3}
|
||||
bindAsDefault: 1
|
||||
isAtlasV2: 1
|
||||
cachedData: {fileID: 0}
|
||||
m_IsVariant: 0
|
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d6c291e122fdd1b4f8338aa5a955cc67
|
||||
SpriteAtlasImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,53 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!612988286 &4096168566840163508
|
||||
SpriteAtlasAsset:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: UIRaw_Atlas_window
|
||||
m_MasterAtlas: {fileID: 0}
|
||||
m_ImporterData:
|
||||
serializedVersion: 2
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
anisoLevel: 0
|
||||
compressionQuality: 0
|
||||
maxTextureSize: 0
|
||||
textureCompression: 0
|
||||
filterMode: 1
|
||||
generateMipMaps: 0
|
||||
readable: 0
|
||||
crunchedCompression: 0
|
||||
sRGB: 1
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
m_BuildTarget: iPhone
|
||||
m_MaxTextureSize: 2048
|
||||
m_ResizeAlgorithm: 0
|
||||
m_TextureFormat: 49
|
||||
m_TextureCompression: 1
|
||||
m_CompressionQuality: 100
|
||||
m_CrunchedCompression: 0
|
||||
m_AllowsAlphaSplitting: 0
|
||||
m_Overridden: 1
|
||||
m_AndroidETC2FallbackOverride: 0
|
||||
m_ForceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
packingSettings:
|
||||
serializedVersion: 2
|
||||
padding: 2
|
||||
blockOffset: 1
|
||||
allowAlphaSplitting: 0
|
||||
enableRotation: 1
|
||||
enableTightPacking: 0
|
||||
enableAlphaDilation: 0
|
||||
secondaryTextureSettings: {}
|
||||
variantMultiplier: 1
|
||||
packables:
|
||||
- {fileID: 21300000, guid: 06edc4e02f9c48647adfed0a778cb8aa, type: 3}
|
||||
- {fileID: 21300000, guid: 78e3daf76621d66448e594d6993adbd8, type: 3}
|
||||
bindAsDefault: 1
|
||||
isAtlasV2: 1
|
||||
cachedData: {fileID: 0}
|
||||
m_IsVariant: 0
|
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: acf10131b937dab4c86d63939aecd2ab
|
||||
SpriteAtlasImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 615ca01c7a524654c91935631f39f570
|
||||
guid: 9f9f9848e17e5eb46b596a07391a42cc
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
29
UnityProject/Assets/AssetArt/Effect/fx_bolt_cyan_mat.mat
Normal file
@@ -0,0 +1,29 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 6
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name: fx_bolt_cyan_mat
|
||||
m_Shader: {fileID: 10720, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ShaderKeywords:
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 2800000, guid: 6e3730451fa077346abd4ac642ea71d8, type: 3}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Floats:
|
||||
- _InvFade: 1
|
||||
m_Colors:
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _TintColor: {r: 0.5, g: 0.5, b: 0.5, a: 0.5}
|
@@ -0,0 +1,6 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 63fe6ff9ab9e1433f8db4ebd940f2442
|
||||
NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
29
UnityProject/Assets/AssetArt/Effect/fx_bolt_orange_mat.mat
Normal file
@@ -0,0 +1,29 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 6
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name: fx_bolt_orange_mat
|
||||
m_Shader: {fileID: 10720, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ShaderKeywords:
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 2800000, guid: fd3cbf51780694849b9b019b36a3938e, type: 3}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Floats:
|
||||
- _InvFade: 1
|
||||
m_Colors:
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _TintColor: {r: 0.5, g: 0.5, b: 0.5, a: 0.5}
|
@@ -0,0 +1,6 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8e27380ee68aa4a219b4db9018e7da31
|
||||
NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,29 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 6
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name: fx_enemyShip_engines_mat
|
||||
m_Shader: {fileID: 10720, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ShaderKeywords:
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 2800000, guid: eabb37cb6d738b443b398b701a64cd88, type: 3}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Floats:
|
||||
- _InvFade: 1
|
||||
m_Colors:
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _TintColor: {r: 0.5, g: 0.5, b: 0.5, a: 0.5}
|
@@ -0,0 +1,6 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1b4bad6cea5a94611b21f9757fe41444
|
||||
NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
BIN
UnityProject/Assets/AssetArt/Effect/fx_lazer_cyan_dff.tif
Normal file
@@ -0,0 +1,53 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6e3730451fa077346abd4ac642ea71d8
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
serializedVersion: 2
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
linearTexture: 0
|
||||
correctGamma: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: .25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 0
|
||||
cubemapConvolution: 0
|
||||
cubemapConvolutionSteps: 8
|
||||
cubemapConvolutionExponent: 1.5
|
||||
seamlessCubemap: 0
|
||||
textureFormat: -1
|
||||
maxTextureSize: 128
|
||||
textureSettings:
|
||||
filterMode: 1
|
||||
aniso: 0
|
||||
mipBias: -1
|
||||
wrapMode: 1
|
||||
nPOTScale: 1
|
||||
lightmap: 0
|
||||
rGBM: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: .5, y: .5}
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spritePixelsToUnits: 100
|
||||
alphaIsTransparency: 0
|
||||
textureType: -1
|
||||
buildTargetSettings: []
|
||||
spriteSheet:
|
||||
sprites: []
|
||||
spritePackingTag:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
BIN
UnityProject/Assets/AssetArt/Effect/fx_lazer_orange_dff.tif
Normal file
@@ -0,0 +1,53 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fd3cbf51780694849b9b019b36a3938e
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
serializedVersion: 2
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
linearTexture: 0
|
||||
correctGamma: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: .25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 0
|
||||
cubemapConvolution: 0
|
||||
cubemapConvolutionSteps: 8
|
||||
cubemapConvolutionExponent: 1.5
|
||||
seamlessCubemap: 0
|
||||
textureFormat: -1
|
||||
maxTextureSize: 128
|
||||
textureSettings:
|
||||
filterMode: 1
|
||||
aniso: 0
|
||||
mipBias: -1
|
||||
wrapMode: 1
|
||||
nPOTScale: 1
|
||||
lightmap: 0
|
||||
rGBM: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: .5, y: .5}
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spritePixelsToUnits: 100
|
||||
alphaIsTransparency: 0
|
||||
textureType: -1
|
||||
buildTargetSettings: []
|
||||
spriteSheet:
|
||||
sprites: []
|
||||
spritePackingTag:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
39
UnityProject/Assets/AssetArt/Effect/part_blast_mat.mat
Normal file
@@ -0,0 +1,39 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 6
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name: part_blast_mat
|
||||
m_Shader: {fileID: 200, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ShaderKeywords:
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _DecalTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 2800000, guid: 3e504a46a8fcec34db3c4776530c6eb2, type: 3}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _Mask:
|
||||
m_Texture: {fileID: 2800000, guid: fe79948256c8b8e44a175b9ec97c6f07, type: 3}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Floats:
|
||||
- _InvFade: 1
|
||||
- _ScrollSpeed: 10
|
||||
m_Colors:
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _EmisColor: {r: 0.2, g: 0.2, b: 0.2, a: 0}
|
||||
- _TintColor: {r: 1, g: 1, b: 1, a: 0.49803922}
|
@@ -0,0 +1,6 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1cfe02ffd0b74854ea5bcd1a3c63ac3c
|
||||
NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|