当前位置:   article > 正文

GameFrameWork框架(Unity3D)使用笔记(九) AssetBundle和游戏打包_unity gamefreamwork

unity gamefreamwork

目录

前言:

整个流程:

一、配置路径

二、打包

三、初始化资源

四、测试打包


前言:

        如果使用了GameFrameWork框架的话,你会发现你点击Build And Run按钮打包运行大概是运行不起来的。本篇就讲了怎么打包游戏运行。

        我觉得我对于资源加载这块儿理解也不够深,所以本篇主要记录方法流程,不讲原理。想探究原理的可以先去看看官方手册,看看GF官网,然后看看其它GF大佬的B站视频啊,博客啊啥的(多看看,每一篇都有值得吸收的碎片,然后把这些碎片再拼成自己脑中的体系图景)。       

        废话不多说,开干!

整个流程:

  •    配置路径,准备用UGF自带的Editor打包
  •    打出AB包
  •    把打好的包复制进StreamingAssets文件夹(如果已经build了)    
  •    build工程

一、配置路径

        如过没有配置过路径的话,打开GameFramework的资源工具Resource Editor是这样的:

        

也就是最右边一列的资产列表是空的。

(关于这个打包工具官网有相关介绍可以先看看)

所以这里需要自己手动添加一个配置文件,告诉这个打包器需要打包的资源路径。

在Assets/GameMain/Configs下手动创建文件ResourceEditor.xml:

内容为:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <UnityGameFramework>
  3. <ResourceEditor>
  4. <Settings>
  5. <SourceAssetRootPath>Assets/GameMain</SourceAssetRootPath>
  6. <SourceAssetSearchPaths>
  7. <SourceAssetSearchPath RelativePath="" />
  8. </SourceAssetSearchPaths>
  9. <SourceAssetUnionTypeFilter>t:Scene t:Prefab t:Shader t:Model t:Material t:Texture t:AudioClip t:AnimationClip t:AnimatorController t:Font t:TextAsset t:ScriptableObject</SourceAssetUnionTypeFilter>
  10. <SourceAssetUnionLabelFilter>l:ResourceInclusive</SourceAssetUnionLabelFilter>
  11. <SourceAssetExceptTypeFilter>t:Script</SourceAssetExceptTypeFilter>
  12. <SourceAssetExceptLabelFilter>l:ResourceExclusive</SourceAssetExceptLabelFilter>
  13. <AssetSorter>Path</AssetSorter>
  14. </Settings>
  15. </ResourceEditor>
  16. </UnityGameFramework>

 (配置文件的内容看英文就明白个大概了,如果想弄懂的话)

配置文件创建了,然后要告诉框架这个配置文件的路径,需要使用一个叫“ResourceEditorConfigPath”的属性来配置。下面来搞。

在Assets/GameMain/Scripts路径下建立Editor文件夹:

文件夹里面手动创建GameFrameworkConfigs.cs(名字实际上应该无所谓):

 里面配置一下刚刚创建的配置文件的路径:

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using GameFramework;
  5. using UnityGameFramework.Editor.ResourceTools;
  6. using System.IO;
  7. namespace ShadowU
  8. {
  9. public static class GameFrameworkConfigs
  10. {
  11. [ResourceEditorConfigPath]
  12. public static string ResourceEditorConfig = Utility.Path.GetRegularPath(Path.Combine(Application.dataPath, "GameMain/Configs/ResourceEditor.xml"));
  13. }
  14. }

如果不懂为啥可以去恶补一下c#的Attribute的相关知识。

保存。

然后再打开打包的资源编辑器:

这样在右边一列就能够看到自己的资源了。


二、打包

然后打包的任务通俗的说就是把右边的资源放到左边。这个界面的操作说明官网有(官网为数不多的教程就有讲这个的。。。)

然后关于打AB包怎么组合比较好可以参考Unity的官方手册:为 AssetBundle 准备资源 - Unity 手册 (unity3d.com)

这里为了演示就不一个包一个包打了直接一把梭:

然后左边就是选择打包的文件:

 细节不管了,先跑起来再说。

点击右下角save(默认会在Assets/GameFramework/Configs路径下生成ResourceCollection.xml):

然后打开工具的builder:

自己设置好你的Output Directory。

(这里的Internal Resource Version每打一次包就会自增,所以我这里是10.。。。)

 save是保存这个界面填写的配置(默认会在Assets/GameFramework/Configs路径下生成ResourceBuilder.xml)。

按Start Build Resources开始打包!

打包后,到自己设置的输出文件夹里:

 各个文件夹的介绍官网都有写:使用 AssetBundle 构建工具 | Game Framework

然后我们只需要把 Package(单机模式)或 Packed(可更新模式)中对应版本(如 0_1_0_1)、对应平台的内容(如 windows),完整拷贝至 Unity 工程的 Assets/StreamingAssets 中,即可Build了。(StreamingAssets文件夹自己创建):

 然后打包之前可以先在编译器运行一下非编译器资源模式。

把这个取消勾选:

然后运行。。。。。

你会发现报错,运行不了。

因为还有一步。


三、初始化资源

虽然已经把游戏所需要的资源打包放好了,但是要让程序使用它们还得通过框架对这些资源进行初始化。

不过初始化很简单,就一个语句:

GameEntry.Resource.InitResources(OnInitResourcesComplete);

其中传入的OnInitResourcesComplete是初始化完成的回调函数。

用一个标记来判断是否初始化完成:

m_InitResourcesComplete = false;

 回调函数就这么写:

  1. private void OnInitResourcesComplete()
  2. {
  3. m_InitResourcesComplete = true;
  4. Log.Info("Init resources complete.");
  5. }

 因为我流程写得相对于StarForce的精简了很多,所以我初始化资源、加载资源、启动游戏等逻辑都放在了ProcedureLaunch.cs里面,所以我加了一点处理来保证初始化资源-->初始化完成-->加载资源-->加载资源完成-->启动游戏这些操作按顺序执行。所以代码如下:

(如果觉得乱直接去学习StarForce的代码即可)

  1. using GameFramework.Fsm;
  2. using GameFramework.Event;
  3. using UnityGameFramework.Runtime;
  4. using System.Collections.Generic;
  5. using UnityEngine;
  6. namespace ShadowU
  7. {
  8. public class ProcedureLaunch : ProcedureBase
  9. {
  10. public override bool UseNativeDialog
  11. {
  12. get
  13. {
  14. return true;
  15. }
  16. }
  17. private Dictionary<string, bool> m_LoadedFlag = new Dictionary<string, bool>();//用来标记是否已经加载
  18. private bool m_InitResourcesComplete = false;
  19. private bool temp = false;
  20. public static readonly string[] DataTableNames = new string[]
  21. {
  22. "Scene",
  23. "Character",
  24. "Entity",
  25. "Enemy"
  26. };
  27. protected override void OnEnter(IFsm<GameFramework.Procedure.IProcedureManager> procedureOwner)
  28. {
  29. base.OnEnter(procedureOwner);
  30. Debug.Log("launch!");
  31. //初始化资源标记
  32. m_InitResourcesComplete = false;
  33. temp = false;
  34. // 注意:使用单机模式并初始化资源前,需要先构建 AssetBundle 并复制到 StreamingAssets 中,否则会产生 HTTP 404 错误
  35. GameEntry.Resource.InitResources(OnInitResourcesComplete);
  36. //注册事件
  37. GameEntry.Event.Subscribe(LoadConfigSuccessEventArgs.EventId, OnLoadConfigSuccess);
  38. GameEntry.Event.Subscribe(LoadConfigFailureEventArgs.EventId, OnLoadConfigFailure);
  39. GameEntry.Event.Subscribe(LoadDataTableSuccessEventArgs.EventId, OnLoadDataTableSuccess);
  40. GameEntry.Event.Subscribe(LoadDataTableFailureEventArgs.EventId, OnLoadDataTableFailure);
  41. }
  42. protected override void OnLeave(IFsm<GameFramework.Procedure.IProcedureManager> procedureOwner, bool isShutdown)
  43. {
  44. base.OnLeave(procedureOwner, isShutdown);
  45. //注销事件
  46. GameEntry.Event.Unsubscribe(LoadConfigSuccessEventArgs.EventId, OnLoadConfigSuccess);
  47. GameEntry.Event.Unsubscribe(LoadConfigFailureEventArgs.EventId, OnLoadConfigFailure);
  48. GameEntry.Event.Unsubscribe(LoadDataTableSuccessEventArgs.EventId, OnLoadDataTableSuccess);
  49. GameEntry.Event.Unsubscribe(LoadDataTableFailureEventArgs.EventId, OnLoadDataTableFailure);
  50. }
  51. protected override void OnUpdate(IFsm<GameFramework.Procedure.IProcedureManager> procedureOwner, float elapseSeconds, float realElapseSeconds)
  52. {
  53. base.OnUpdate(procedureOwner, elapseSeconds, realElapseSeconds);
  54. if (!m_InitResourcesComplete)
  55. {
  56. // 初始化资源未完成则继续等待
  57. return;
  58. }
  59. if (!temp)//temp用于保证这里的代码只执行一次
  60. {
  61. m_LoadedFlag.Clear();
  62. //预加载配置
  63. PreloadResources();
  64. //加载数据表
  65. foreach (string dataTableName in DataTableNames)
  66. {
  67. LoadDataTable(dataTableName);
  68. }
  69. temp = true;
  70. }
  71. foreach (KeyValuePair<string,bool> loadedFlag in m_LoadedFlag)
  72. {
  73. if (!loadedFlag.Value)
  74. {
  75. return;//说明有资源没有加载成功
  76. }
  77. }
  78. //通过加载的配置表来设置下一个转换场景的ID
  79. procedureOwner.SetData<VarInt32>("NextSceneId",GameEntry.Config.GetInt("Scene.Menu"));
  80. //一帧后直接转到菜单流程
  81. ChangeState<ProcedureChangeScene>(procedureOwner);
  82. }
  83. private void PreloadResources()
  84. {
  85. LoadConfig("DefaultConfig");
  86. }
  87. private void LoadConfig(string configName)
  88. {
  89. string configAssetName = AssetUtility.GetConfigAsset(configName, false);
  90. m_LoadedFlag.Add(configAssetName, false);
  91. GameEntry.Config.ReadData(configAssetName, this);
  92. }
  93. private void LoadDataTable(string dataTableName)
  94. {
  95. string dataTableAssetName = AssetUtility.GetDataTableAsset(dataTableName, false);
  96. m_LoadedFlag.Add(dataTableAssetName, false);
  97. GameEntry.DataTable.LoadDataTable(dataTableName, dataTableAssetName, this);
  98. }
  99. private void OnLoadConfigSuccess(object sender, GameEventArgs e)
  100. {
  101. LoadConfigSuccessEventArgs ne = (LoadConfigSuccessEventArgs)e;
  102. if (ne.UserData != this)
  103. {
  104. return;
  105. }
  106. m_LoadedFlag[ne.ConfigAssetName] = true; //资源加载成功了则设置一下标记为true
  107. Log.Info("Load config '{0}' OK.", ne.ConfigAssetName);
  108. }
  109. private void OnLoadConfigFailure(object sender, GameEventArgs e)
  110. {
  111. LoadConfigFailureEventArgs ne = (LoadConfigFailureEventArgs)e;
  112. if (ne.UserData != this)
  113. {
  114. return;
  115. }
  116. Log.Error("Can not load config '{0}' from '{1}' with error message '{2}'.", ne.ConfigAssetName, ne.ConfigAssetName, ne.ErrorMessage);
  117. }
  118. private void OnLoadDataTableSuccess(object sender, GameEventArgs e)
  119. {
  120. LoadDataTableSuccessEventArgs ne = (LoadDataTableSuccessEventArgs)e;
  121. if (ne.UserData != this)
  122. {
  123. return;
  124. }
  125. m_LoadedFlag[ne.DataTableAssetName] = true;
  126. Log.Info("Load data table '{0}' OK.", ne.DataTableAssetName);
  127. }
  128. private void OnLoadDataTableFailure(object sender, GameEventArgs e)
  129. {
  130. LoadDataTableFailureEventArgs ne = (LoadDataTableFailureEventArgs)e;
  131. if (ne.UserData != this)
  132. {
  133. return;
  134. }
  135. Log.Error("Can not load data table '{0}' from '{1}' with error message '{2}'.", ne.DataTableAssetName, ne.DataTableAssetName, ne.ErrorMessage);
  136. }
  137. private void OnInitResourcesComplete()
  138. {
  139. m_InitResourcesComplete = true;
  140. Log.Info("Init resources complete.");
  141. }
  142. }
  143. }

 搞定。


四、测试打包

再在编译器运行一下非编译器资源模式:

 可以启动,点击开始后也能正常运行。

那下面就可以打包了:

Build And Run,选择好文件夹,打包,运行!

 搞定!

同时StreamingAssets文件夹的内容会同时拷贝到打包好的工程的StreamingAssets文件夹:

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/81921
推荐阅读
相关标签
  

闽ICP备14008679号