記事ディレクトリ
-
-
- ゼロ。
- 1.私が作ったホットアップデートのデモ
- 2. ホット アップデートが必要な理由は何ですか?
- 3. Unity はホット アップデートをどのようにサポートしていますか
- 4. Unity に統合された tolua フレームワーク: LuaFramewrk
- 五、toluaフレームワークのワークフロー
- 6. ホット アップデート デモの紹介
-
- 1. ウェブサーバー
- 2. コード構造: Scripts ディレクトリ
- 3. リソース ディレクトリ構造: RawAssets ディレクトリ、GameRes ディレクトリ
- 4. リソース構成: resources.bytes、ResourcesCfg.cs
- 5. リソース マネージャー: ResourceMgr.cs
- 6. インターフェイス マネージャー: PanelMgr.cs、BasePanel.cs
- 7. ホット アップデート ロジック: HotUpdater.cs
- 8. ダウンローダー: Downloader.cs
- 9. ファイルの解凍と圧縮
- 10. AES 対称暗号化と復号化
- 11.パッケージ全体を梱包する
- 12.ホットアップデートパッケージ
- セブン、終了
-
ゼロ。
こんにちは、私は新しいです。
クラスメートが個人的な手紙を送ってくれて、ホット アップデートに関するチュートリアルを書いてもらえないかと尋ねてきましたToLua
。
今日は詳しくお話ししますが、内容は比較的長くなりますので、ブックマークしてゆっくり読むことをお勧めします。
1.私が作ったホットアップデートのデモ
バージョン管理、リソースのパッケージ化、リソースのロード、コードの暗号化と復号化、ホット アップデート パッケージのダウンロード、ブレークポイント レジュームなどの機能を含むDemo
、完全なホット アップデート プロセスを実現する方法を使用して、時間をかけて作成しました。Unity + tolua
lua
1.効果のデモンストレーション
その効果は次のとおりです。複数の増分パッケージをダウンロードします:
メジャー バージョンの更新をスキップ:
ブレークポイントの再開:
2.フローチャート
対応するフローチャートは次のとおりです (画像は拡大できます):
まず、最新の現在のバージョンを記録するバージョン マネージャー;
インターフェイス リソースの読み込みを伴う起動時に更新インターフェイスが表示されます. リソース マネージャーをカプセル化し、インターフェイス マネージャー、リソース マネージャーは最初にホット アップデート ディレクトリ ( persistentDataPath
of update
) からリソースを検索し、見つからない場合は、パッケージ内のディレクトリに移動してStreamingAssets
リソースを見つけます。
次に、ホット アップデート ロジックを実行し、最初にWeb
サーバーに移動します。更新リストを要求し、バージョン番号を決定します, それがパッケージ全体の更新であるか増分更新であるか. 定量的更新, 必須の更新であるかどうか; 更新リストに従ってダウンロード, ここでは独立したスレッドを使用してダウンロードします
,UI
メインスレッドの進行状況更新表示がスタックしないように
、ダウンロードプロセスはアップロードの再開をサポートしているため、ダウンロードプロセス中のネットワーク切断を回避できますまたはプロセスを強制終了した後、最初からダウンロードする必要があります
;増分パッケージMD5
が正しいかどうかを確認し、正しくない場合はMD5
再度ダウンロードします;
検証が正しい場合は、ディレクトリMD5
に解凍します;フレームワークを起動する前に、プリロード: and ;最後にフレームワークを起動してログイン画面を表示します.persistentDataPath
update
lua
lua
bundle
lua.bundle
lua_update.bundle
lua
さらに、パッケージングAssetBundle
、APP
全体パッケージ、増分パッケージに便利な簡易パッケージ ツールのセットを個別に作成しました.パッケージ全体を
パッケージ化する前に、元のファイルのリストが最初に生成され、パッケージ全体が最後に生成されます。パッケージ化、構成、リソースなど;さらに、他の人が平文ファイルを直接取得できないように、パッケージ化するときに最初にファイルを暗号化しました。APP
lua
MD5
lua
AssetBundle
APP
lua
lua
lua
3. プロジェクトのソースコード
私のホット アップデートDemo
プロジェクトはここにアップロードされています,アドレスCODE CHINA
: https://codechina.csdn.net/linxinfa/UnityHotUpdateFramework mine とは異なり、プロジェクトを開くとエラーが報告される場合があります。Unity
2021.1.7f1c1
私のDemo
いくつかの紹介については、この記事の 6 番目のセクションまで飛ばしてください. 次に、最新の更新プログラムとtolua
フレームワークについて少しスペースを割いて説明します.
2. ホット アップデートが必要な理由は何ですか?
ホットなアップデートがある理由について、簡単にいくつかの言葉を述べます。
ゲームを開発してアプリマーケットに出したところ、ユーザーから重大な問題が報告され、BUG
緊急に修正した後、再パッケージ化してAPP
アプリマーケットの再審査を行う必要があり、心配しながら待っていたところ、ようやく審査を通過したとします。 、その後、プレーヤーはそれをAPP
再度ダウンロードする必要があります インストール. プロセス全体を想像することはできますが、高速で効率的とは言えず、ダウンロードして再度インストールする必要があると、ユーザーが失われる可能性があります. したがって、再インストールせずに修正する方法
が必要です。つまり、APP
BUG
ホットアップデート、私たちは一般的にも呼びます増分更新.
実際、ホット アップデートは修理に使用されるだけでなくBUG
、オンラインでの小さなバージョンの反復にもよく使用されます。実際のゲーム プロジェクトの開発ペースは非常に速く、一般的に次のように分けられます。大きなバージョンの繰り返しと小さなバージョンの反復. 大型版は多くの開発コンテンツを設計し、サイクルは通常 2 週間から 1 か月程度と長いですが、類似ゲームの激しい競争下では、小さなステップで新しいコンテンツを繰り返し、プレーヤーに提供し続ける必要があります。新しいゲームのコンテンツ、定着率の向上、アクティビティの増加。したがって、メジャー バージョン サイクルでは、いくつかの小さなバージョンのイテレーションが設計され、コンテンツはホット アップデートの形でオンライン バージョンに更新されます。ダウンロードしてインストールするAPP
と、APP
複数の目的に役立ちます。
3. Unity はホット アップデートをどのようにサポートしていますか
ホット アップデートにはコードとリソースが含まれ、コードにはC#
コード、lua
コードが含まれ、リソースには構成テーブル、プリセット、音楽効果音、アニメーション、フォント、画像、素材などが含まれます。
1. C# コードのホット アップデート
Unity
デフォルトの開発言語では、C#
作成したコードは最終的にエンジンによってC#
コンパイルおよびロードされます。したがって、コードの一部を独立したファイルにコンパイルしてサーバーにアップロードし、ゲームの開始時にサーバーからファイルをダウンロードし、実行時に再ロードすることで、ホット アップデートの目的を達成できますが、あなたがリロードしたコードがウイルスかどうかは悪魔が知っているため、危険な操作と見なされます. あなたのプロジェクトがアプリ市場に出された場合、この種のホット アップデート操作を使用すると、危険な操作と見なされる可能性が高くなります.アプリ市場による違法な操作として、棚から取り除かれました。dll
Unity
C#
dll
Web
dll
dll
dll
dll
注: ところで、
IL2CPP
メソッドのパッケージ化を使用すると、C#
コードはコードに変換されますC++
。
2. lua コードとリソースのホット アップデート
ゲームのホット アップデートに関して言えば、lua
このlua
言語は実行時に動的に解釈され、実行されていないときは通常のテキスト ファイルであり、リソース ファイルと見なすことができます。したがって、lua
コードの更新とリソースの更新は本質的に同じであり、通常、パッケージ化されてサーバーAssetBundle
に配置されWeb
、クライアントはWeb
サーバーからAssetBundle
ローカルに最新の更新をダウンロードします。
、、、などの多くのフレームワークが市場にlua
出回っています.本質は、仮想マシン (言語で実装された仮想マシン) を環境に埋め込むことです. ゲームが実行されているとき、スクリプトは動的に解析され実行されます.ロジックを実装するために使用され、サーバーを介してスクリプトをダウンロードします(通常、ソース コードは暗号化されてからファイルに入力されるか、ソース コードはバイトコードにコンパイルされてからファイルに入力されます)。 、ホットアップデートの目的を達成するため。tolua
xlua
ulua
slua
Unity
lua
c
lua
lua
Web
lua
lua
AssetBundle
luac
lua
AssetBundle
4. Unity に統合された tolua フレームワーク: LuaFramewrk
1. tolua フレームワークをダウンロードします: LuaFramewrk
tolua
アドレスGitHub
: https://github.com/topameng/tolua
にアクセスできない学生がいる場合は、ミラー ソースからダウンロードすることGitHub
もできます。アドレス: https://codechina.csdn.net/mirrors/topameng/toluaには、 との 2 つのバージョンのフレームワークが用意されています。バージョンをダウンロードしました: https://codechina.csdn.net/mirrors/jarjin/LuaFramework_UGUICode China
LuaFramework_NGUI
LuaFramework_UGUI
UGUI
2. tolua フレームワーク プロジェクトを開きます: LuaFramework_UGUI
ダウンロード後、 に追加します。バージョンで作成されているUnity Hub
ことがわかります。ご想像のとおり、バージョンを使用して開きます。Unity5
Unity2021.1.7f1c1
間違いなく互換性の問題がいくつかあります。, 心配しないでください, 私はあなたのためにそれらを一つずつ解決しました.私はウェブサイトにUnity2021.1.7f1c1
バージョンをLuaFramework_UGUI
アップロードしました.バージョンもCODE CHINA
使用する場合, あなたは私のバージョンを直接使用することができます. アドレス: https://codechina.csdn.ネット/linxinfa/LuaFramework_UGUI_20212021
Unity
ただし、詳細を理解していただくために、私の解決プロセスを書きます。
これらのエラー報告の問題をどのように解決したかを読んでおくことをお勧めします。これは、LuaFramework がどのように機能するかを理解するのに役立ちます。、 男に魚を与えるよりも、魚を教える方が良いです. 魚が欲しいですか、それとも魚が欲しいですか?
确定
ボタンをスマートにクリックし、
3. 登録ファイルの生成: Wrap クラスの生成
ロードして数分待つと、次のボックスがポップアップ表示されます。クリックすると、确定
一般Unity
的に使用されるクラスのクラスC#
が生成され、仮想マシンにWrap
登録されます。これにより、これらのクラスを で使用できるようになります。上のボタンをクリックすると、 menu をクリックすると、誤ってボタンをクリックしても、メニュー内で実行できます.生成が成功すると、ディレクトリ内に多くのクラスが表示されます.自問してみてください: どのクラスを生成するかをどうやって知るのでしょうか? 答えはスクリプトにあります. スクリプトを開くと,次のようにたくさん見ることができます.これに基づいて対応するクラスを生成します. 自分で書いたクラスを使いたい場合は,ここに呼び出しを追加する必要があります.例:lua
lua
c#
确定
Lua / Gen Lua Wrap Files
取消
Wrap
Assets/LuaFramework/ToLua/Source/Generate
Wrap
Wrap
CustomSettings.cs
CustomSettings.cs
_GT(typeof(XXXXX))
Wrap
lua
_GT
_GT(typeof(MyClass)),
注:
GT
ではGenrate Table
、lua
クラスは実際にはtable
4. すべて生成メニュー
上記のクラスを生成したばかりですWrap
が、実際には と も生成する必要がありますLua Delegates
。LuaBinder
メニューに表示されているように、
生成されたWrap
クラスはで仮想マシンLuaBinder
に登録する必要がありlua
、生成されたデリゲートは で仮想マシンに登録するlua
必要があります。もちろん、これらはすべて自動的に生成されるため、メニューを実行するだけで済みます。通常、メニューを直接クリックすると、次の 3 つのことが行われます: 1.に従ってデリゲートを生成し、仮想マシンに登録します; 2.に従ってクラスを生成します; 3.でクラスの登録ロジックを生成します。DelegateFactory
lua
Lua / Generate All
CustomSettings
customDelegateList
lua
DelegateFactory
lua
CustomSettings
customTypeList
Wrap
LuaBinder
Wrap
5. エラー報告の問題を解決する
5.1、GetElementType() が空で、エラーが報告される
Generate All
メニューをクリックした後、次のエラーが報告されました:
コードの検索:ToLuaExport.cs
最初の295
行、GetElementType()
空を返す可能性があります。
空判定を追加します。これはToLuaExport.cs
ツールの問題です。
5.2. UnityEngine_ParticleSystemWrap がエラーを報告する
Generate All
メニューをもう一度クリックし、新しいエラーを報告し、
コードを見つけます:スクリプト、生成されたクラスの異なるパラメーターを持つオーバーロードされた関数の生成に問題があることがわかります。UnityEngine_ParticleSystemWrap.cs
実際Wrap
、ParticleSystem
基本的に使用する必要はありませんコード内のこのメソッド 到着したので、単純かつ無礼にコメントアウトするだけで十分であり、同様に、クラスの同様のエラー報告を解決します。SetParticles
SetParticles
lua
UnityEngine_ParticleSystemWrap
5.3、特定の Wrap を BaseType に移動
ここで問題が発生します。Wrap
これはツールによって生成されるため、Wrap
上記のクラスを変更すると、次回の再生成時に上書きされ、再度エラーが報告されます。解決策は、次のようにディレクトリ
に移動することです.の対応するクラスの呼び出しをコメントアウトすることを忘れないでください,メニューをもう一度クリックすると、クラスが再生成されないことがわかります. .生成されたクラスを自動的に登録します. 世代を指定していないので, では当然登録ロジックは生成されません.関係ありません.にはクラスがいくつかあります. 1つ見つけてどこにあるかを確認してください.参照検索でスクリプトにジャンプすると、その中のクラスが関数に登録されていることがわかります.ここで呼び出しを追加するだけです.大丈夫ですが、名前空間に注意する必要があります. 、およびでラップされ、マルチレイヤーの名前空間はネストできます。次に例を示します。Assets / LuaFramework / ToLua / BaseType
CustomSettings.cs
_GT
Generate All
UnityEngine_ParticleSystemWrap
LuaBinder
Wrap
UnityEngine_ParticleSystemWrap
LuaBinder
BaseType
Wrap
lua
LuaState.cs
BasetType
Wrap
LuaState
OpenBaseLibs
Register
BeginModule
EndModule
BeginModule("System");
BeginModule("Generic");
System_Collections_Generic_ListWrap.Register(this);
System_Collections_Generic_DictionaryWrap.Register(this);
System_Collections_Generic_KeyValuePairWrap.Register(this);
EndModule();//Generic
EndModule();//end System
私たちのものは名前空間の下にParticleSystem
あるため、次のようにと の間にUnityEngine
配置されます。BeginModule("UnityEngine");
EndModule();
5.4、LightWrap および MeshRendererWrap レポート エラー
エラーが報告されていないことを確認し、main
シーンを開いて
実行し、フラッシュし、次のError
ように one を報告しました:
I am a Windows
platform, so I click Build Windows Resource
the menu , そして
次の新しいエラーを報告しました:
one is UnityEngine_LightWrap
a class,もう 1 つはUnityEngine_MeshRendererWrap
クラスです。上記と同様のUnityEngine_ParticleSystemWrap
メソッドを使用して処理します。
メニューを再実行するGenerate All
と、多くのファイルがディレクトリに生成され、リソースが正常にパッケージ化されたことを示します.この時点でBuild Windows Resource
、もう一度実行して、正常に実行できることを確認できます.Assets / StreamingAssets
AssetBundle
五、toluaフレームワークのワークフロー
上記では、を実行するとUI
インターフェイスが表示されることがわかりました. このUI
インターフェイスはlua
コードで作成されました. では、コードをUnity
読み込んで実行するにはどうすればよいでしょうか? lua
順を追って説明しますので、気長に読んでいただければ幸いです。
1. Main.cs: エントリ スクリプト
main
シーンのビューを振り返ると、スクリプトがぶら下がっていHierarchy
ます。明らかに、これはエントリ スクリプトです。GameManager
Main
2. StartUp: ゲーム フレームワークを開始します。
Main.cs
次のようにスクリプトを開きます。その文StartUp
は最も重要な呼び出しであり、メッセージを
送信してクラスの実行をトリガーします。ここに多くのマネージャーが追加されていることがわかります。これらのマネージャーはオブジェクトにハングアップします。もちろん、必要に応じて新しいマネージャーを追加することもできます。不要なマネージャーを削除することもできます。特に、プロジェクトの途中でフレームワークを継承している場合は、インターフェイスなど、独自のプロジェクトに多くのマネージャーが既に存在している可能性があります。マネージャーとリソース管理マネージャー、サウンド マネージャー、ネットワーク マネージャー、スレッド マネージャーなど、START_UP
StartUpCommand
Execute
GameManager
tolua
アーキテクトになりたい場合は、これらのマネージャーを自分で書いてみることをお勧めします。LuaManager
上記のマネージャーの中で、ここで注目したいのは、コアで最も重要なマネージャーですLuaManager
。
3. LuaManager: Lua マネージャー
LuaManager
これはフレームワーク全体のコアでありtolua
、その 3 つのコア メンバーは次のとおりです。
// lua虚拟机
private LuaState lua;
// lua文件加载器
private LuaLoader loader;
// lua生命周期控制
private LuaLooper loop;
彼らが何をしているのかを1つずつ説明しましょう。
3.1、LuaState: lua 仮想マシン
私たちのlua
コードはlua
、実行する前にインタープリターによって解釈される必要があります. インターlua
プリターはc
言語で記述されており、各プラットフォームに対応するライブラリ ファイルがあります. 以前に記事を書きました: 「[高度なゲーム開発] 使用方法を教えてください」 Windows プラットフォームで tolua ランタイムのさまざまなプラットフォーム ライブラリをコンパイルする (Unity | Hot Update | tolua | Cross Compilation)」では、tolua
プラットフォームごとのライブラリ ファイルのコンパイルについて詳しく説明しました。
ライブラリ関数の宣言は にありLuaDLL.cs
、特定のメソッドの呼び出しなど、スケジューリング
LuaState
の多くのペアをカプセル化します。これは、それ自体でスケジュールされます。したがって、スケジューリング関係は、フレームワークが開始されると、スケジューリングは主に次のことを行います。LuaDLL
lua
LuaState
LuaManager
LuaManager -> LuaState -> LuaDLL
LuaState
3.2、LuaLoader: lua ファイルローダー
LuaLoader
LuaFileUtils
ファイルの読み込みと検索の機能を継承し、主に提供するファイルローダですlua
。
コア メンバー変数:
public bool beZip = false;
protected List<string> searchPaths = new List<string>();
protected Dictionary<string, AssetBundle> zipMap = new Dictionary<string, AssetBundle>();
yesの場合は、読み込まれたファイルを で見つけます。そうでない場合は、独自の設計に従ってファイルを読み込む方法を書き換えることができます。たとえば、ファイルを暗号化する場合は、最初にここで読み込む必要があります。復号化を行います。beZip
false
searchPaths
lua文
bundel
lua
ReadFile
lua
lua
3.3、LuaLooper: lua ライフサイクル制御
にはUnity
、MonoBehaviour
ライフサイクルがあります。
公式の Unity ドキュメントの説明を参照できます: https://docs.unity3d.com/Manual/ExecutionOrder.html
tolua
同様のライフサイクル機能を実現するために、いくつかをカプセル化しましたAPI
。
// LuaDLL.cs
[DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
public static extern int tolua_update(IntPtr L, float deltaTime, float unscaledDelta);
[DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
public static extern int tolua_lateupdate(IntPtr L);
[DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
public static extern int tolua_fixedupdate(IntPtr L, float fixedTime);
これらはオリジンAPI
によってスケジュールされ、LuaLooper
注: そうでない場合
LuaLooper
、lua
コルーチンは正常に実行されません。
4. ゲームマネージャー: ゲームマネージャー
このフレームワークは次のものを提供しますGameManager
: フレームワークを使用する代わりに自分で作成できるゲーム マネージャーですが、ここではフレームワークが何をするかGameManager
について説明します。GameManager
4.1. リソースの解放
GameManager
起動時に、まずリソース パス ( ) にファイルがUtil.DataPath
あるかどうかを確認し、ない場合は、ディレクトリ内のファイルをリソース パス ( ) にコピーします。これにより、ディレクトリ内のすべてのファイルとリソース ファイルが記録されます。ファイルをトラバースし、ディレクトリ内のファイルとリソース ファイルをリソース パス ( ) にコピーします。このプロセスは呼び出されます。lua
StreamingAssets
files.txt
Util.DataPath
files.txt
StreamingAssets
lua
md5
files.txt
StreamingAssets
lua
Util.DataPath
リソースを解放する。
4.2. リソースの更新
AppConst.UpdateMode
更新リソースを実行するかどうかによって異なります。
更新が必要な場合は、Web
サーバーのアドレスにアクセスしAppConst.WebUrl
て最新のものをダウンロードしてくださいfiles.txt
。
Then iterate through the latest ones files.txt
, check whether the local files are missing or MD5
not equal, and then go to Web
the server to download lua
code or resources. ダウンロードでは、スレッド マネージャーを使用して、ダウンロード用の独立したスレッドを開始します。
4.3、lua コードの実行
lua
コードとリソースを更新した後にGameManager
呼び出され、OnInitialize
ここでlua
仮想マシンを起動してコードを実行できますlua
。仮想マシン
を起動します。lua
LuaManager.InitStart();
実行lua
コード:
-- 加载Game.lua脚本
LuaManager.DoFile("Logic/Game");
-- 执行lua的Game.OnInitOK方法
Util.CallMethod("Game", "OnInitOK");
シーンに表示されるインターフェイスは、その中で作成され
ますGame.OnInitOK
。
4.4. lua ビジネスコードの構造
lua
ビジネスコードの構造は以下の通りで、Demo
例のインターフェースを例にとると、スクリプト(インターフェース相互作用ロジック、スクリプトと同様)とスクリプト(インターフェースオブジェクトバインディング、スクリプトと同様)に対応するPrompt
プロンプトインターフェースです。レイアウト ファイル)。スクリプトを管理およびスケジュールし、最初に定義して名前を付け、
PromptCtrl.lua
Android
Activity
PromptPanel.lua
UI
Android
layout
CtrlManager.lua
Ctrl
define.lua
Ctrl
Panel
-- define.lua
CtrlNames = {
Prompt = "PromptCtrl",
Message = "MessageCtrl"
}
PanelNames = {
"PromptPanel",
"MessagePanel",
}
次に、すべてがCtrl
に登録されCtrlManager
、
-- CtrlManager.lua
function CtrlManager.Init()
logWarn("CtrlManager.Init----->>>");
ctrlList[CtrlNames.Prompt] = PromptCtrl.New();
ctrlList[CtrlNames.Message] = MessageCtrl.New();
return this;
end
CtrlManager
対応するCtrl
オブジェクトを取得し、Awake()
メソッドを呼び出すことで、
-- CtrlManager.lua
local ctrl = CtrlManager.GetCtrl(CtrlNames.Prompt);
if ctrl ~= nil then
ctrl:Awake();
end
Ctrl
Awake()
メソッドでC#
呼び出されるPanelManager
メソッドでCreatePanel
、
-- PromptCtrl.lua
function PromptCtrl.Awake()
logWarn("PromptCtrl.Awake--->>");
panelMgr:CreatePanel('Prompt', this.OnCreate);
end
C#
インターフェイス プリセットをロードしてスクリプトをハングアップするメソッド。このスクリプトは主にライフ サイクルを管理しPanelManager
、呼び出し中に要素オブジェクトを取得します。CreatePanel
LuaBehaviour
LuaBehaviour
Panel
lua
Panel
Awake
UI
-- PromptPanel.lua
local transform;
local gameObject;
PromptPanel = {
};
local this = PromptPanel;
--启动事件--
function PromptPanel.Awake(obj)
gameObject = obj;
transform = obj.transform;
this.InitPanel();
logWarn("Awake lua--->>"..gameObject.name);
end
--初始化面板--
function PromptPanel.InitPanel()
this.btnOpen = transform:Find("Open").gameObject;
this.gridParent = transform:Find('ScrollView/Grid');
end
--单击事件--
function PromptPanel.OnDestroy()
logWarn("OnDestroy---->>>");
end
After the interface is created, it will be called back Ctrl
.いくつかのイベントとコントロールを要素オブジェクトに追加OnCreate()
しCtrl
ますUI
-- PromptCtrl.lua
--启动事件--
function PromptCtrl.OnCreate(obj)
gameObject = obj;
transform = obj.transform;
panel = transform:GetComponent('UIPanel');
prompt = transform:GetComponent('LuaBehaviour');
logWarn("Start lua--->>"..gameObject.name);
prompt:AddClick(PromptPanel.btnOpen, this.OnClick);
resMgr:LoadPrefab('prompt', {
'PromptItem' }, this.InitPanel);
end
6. ホット アップデート デモの紹介
1. ウェブサーバー
Web
サーバーについては、Xiaopi クライアントを使用してApache
サーバーを直接起動しますWeb
。
実際のプロジェクトでは、Alibaba Cloud や Tencent Cloud などのクラウド サービスをサーバーとして使用しますWeb
。
増分パッケージはWeb
サーバーのルート ディレクトリに配置されます。これは
update_list.json
更新リスト ファイルであり、各増分パッケージのバージョン番号、md5
サイズ、合計が記録されますurl
。次に例を示します。
[
{
"appVersion": "1.0.0.0",
"appUrl": "https://blog.csdn.net/linxinfa",
"updateList":
[
{
"resVersion": "1.0.0.2",
"md5": "206933991b0fd0275695e302b9fa0839",
"size": 916897,
"url": "http://localhost:7890/res_1.0.0.2.zip"
},
{
"resVersion": "1.0.0.1",
"md5": "6d71d1648247546b43197d1ddd832ad6",
"size": 4737,
"url": "http://localhost:7890/script_1.0.0.1.zip"
}
]
}
]
2. コード構造: Scripts ディレクトリ
私のコード構造は次のとおりです。
3. リソース ディレクトリ構造: RawAssets ディレクトリ、GameRes ディレクトリ
アニメーション、フォント、画像などの生肉リソースはRawAssets
ディレクトリに配置されます.これらのリソースはデフォルトで依存されます.デフォルトは調理済み肉リソースです.対照的に,これらは生肉リソースです. ディレクトリに
焼き肉のリソースを配置し、ホットアップデート前に使用するリソースを配置し、ホットアップデート後に他のディレクトリのリソースを読み込みます。GameRes
BaseRes
4. リソース構成: resources.bytes、ResourcesCfg.cs
でリソース パスをresources.bytes
次のように構成します。
[
{
"id":1, "editor_path":"UIPrefabs/LoginPanel.prefab", "desc":"登录界面" },
{
"id":2, "editor_path":"UIPrefabs/PlazaPanel.prefab", "desc":"大厅界面" },
{
"id":3, "editor_path":"UIPrefabs/TipsFly.prefab", "desc":"提示语" }
]
editor_path
これは相対GameRes
パスであり、その第 1 レベルのディレクトリが名前として使用されますAssetBundle
。たとえば、上記の 3 つのリソースの第 1 レベルのディレクトリはすべて であるため、これらはという名前のファイルUIPrefab
にまとめて入力されます。read するスクリプトをカプセル化しました。メソッドを介して構成を取得できます。uiprefab.bundle
AssetBundle
ResourcesCfg
resources.bytes
GetResCfg
// ResourcesCfg.cs
public ResourcesCfgItem GetResCfg(int resId)
例:
var resCfg = ResourcesCfg.instance.GetResCfg(1);
5. リソース マネージャー: ResourceMgr.cs
リソースが構成された後、リソースはリソース マネージャーを介して読み込まれます。2 つのインターフェイスをカプセル化しました。
// ResourceMgr.cs
public T LoadAsset<T>(int resId) where T : UObject
public T LoadAsset<T>(string resPath) where T : UObject
id
リソースを介してリソースをロードできます。
次に例を示します。
var loginPanelObj = ResourceMgr.instance.LoadAsset<GameObject>(1);
相対パスを介してリソースをロードすることもできます。
次に例を示します。
var loginPanelObj = ResourceMgr.instance.LoadAsset<GameObject>("UIPrefabs/LoginPanel.prefab");
ただし、インターフェースを表示したい場合は、PanelMgr
スケジュールと一元管理に使用することをお勧めします。
6. インターフェイス マネージャー: PanelMgr.cs、BasePanel.cs
インターフェイスの管理を容易にするために、インターフェイスBasePanel
のライフサイクルをスケジュールするために使用されるインターフェイス基本クラスをカプセル化しました. これにはメンバーがあります.初期化されると、同じ名前panelName
のスクリプトを検索し、ライフ サイクルに関連するスケジュール機能インターフェースの作成と破棄の起源 ユニファイドコール。絵を描く:panelName
lua
PanelMgr
7. ホット アップデート ロジック: HotUpdater.cs
ホット アップデート ロジックを にカプセル化しHotUpdater
、それが行うことは次のとおりです:
1. リストの更新を要求する;
2. バージョン番号に従って実際にダウンロードする必要があるファイルを計算し、最終的に更新するかどうかを決定する必須の更新またはオプションの更新です;
3. ダウンロードを実行し、Downloader
クラスをスケジュールします ダウンロード タスクを完了します;
4.Update
でダウンロード イベントをリッスンし、イベントに従ってインターフェイス更新デリゲート関数を呼び出し、インターフェイス ステータスの更新を実現します;
5 . ダウンロード完了後に検証を行うMD5
. 検証に失敗した場合は、ダウンロードを再実行する
6.検証に合格したら、ファイルの解凍を実行し、ディレクトリMD5
に解凍する7 解凍が完了したら、ファイルを削除する; 8 すべてのダウンロードが完了するまで次の増分パッケージをダウンロードします; 9 ダウンロードが完了したら、デリゲート関数をコールバックします。persistentDataPath/update
zip
actionAllDownloadDone
8. ダウンローダー: Downloader.cs
Downloader
主なことは、ダウンロード タスクを実行し、それを使用してサーバーHttpWebRequest
を要求することです。Web
var httpReq = HttpWebRequest.Create(url) as HttpWebRequest;
ブレークポイントからの再開可能なアップロードをサポートするには、それが であるHttpWebResponse
かどうかを判断する必要があります。サポートしている場合はブレークポイントからの再開可能なアップロードをサポートしており、そうでない場合は最初から再度ダウンロードする必要があります。StatusCode
HttpStatusCode.PartialContent
var response = (HttpWebResponse)httpReq.GetResponse();
if (response.StatusCode != HttpStatusCode.PartialContent)
{
// 不能断点续传,要重新下载
}
ブレークポイントからアップロードを再開する際の核心は、次のように、ローカル ファイルからSeek
ファイルの末尾、およびHttpWebRequest.AddRange
再開する場所に移動することです。
m_fs = new FileStream(savePath, FileMode.OpenOrCreate, FileAccess.Write);
var lastDownloadSize = fs.Length;
m_fs.Seek(lastDownloadSize, SeekOrigin.Current);
httpReq.AddRange(lastDownloadSize);
ファイルをダウンロードするためのファイルの書き込みには時間がかかるため、独立したスレッドを使用してファイルを書き込み、
// 开启一个独立的写文件线程
if (null == m_thread)
{
m_stopThread = false;
m_thread = new Thread(WriteThread);
m_thread.Start();
}
ファイル書き込みのロジックは、ストリームからデータを読み取りHttpWebResponse
、Stream
それをローカル ファイルに書き込むことです。
var readSize = m_ns.Read(m_buff, 0, m_buff.Length);
if (readSize > 0)
{
m_fs.Write(m_buff, 0, readSize);
curDownloadSize += readSize;
Thread.Sleep(0);
}
else
{
// 完毕
m_stopThread = true;
state = DownloadState.End;
Dispose();
}
9. ファイルの解凍と圧縮
パッケージ化ツールで増分パッケージを圧縮してファイルに圧縮しました.zip
. クライアントがホットアップデートされた場合, ダウンロード後に解凍されます.
私が使用するライブラリを圧縮および解凍するにはIonic.Zip.Unity.dll
、
ファイルを圧縮するには:
// using Ionic.Zip;
using (ZipFile zip = new ZipFile())
{
// 设置压缩密码
// zip.Password = "123456";
zip.AddDirectory(Application.dataPath + "/TestDir", "./TestDir");
zip.AddFile(Application.dataPath + "/Test1.txt", "./");
zip.Save(Application.dataPath + "/result.zip");
}
ファイルを解凍します。
using (ZipFile zip = new ZipFile(Application.dataPath + "/result.zip"))
{
// 设置解压密码
// zip.Password = "123456";
// 直接解压所有文件
// zip.ExtractAll(Application.dataPath + "/UnZip");
foreach (var entity in zip)
{
// 挨个文件解压
entity.Extract(Application.dataPath + "/UnZip");
}
}
10. AES 対称暗号化と復号化
lua
コードがパッケージ化されたらAssetBundle
、まずlua
コードを一時ディレクトリにコピーし、AssetBundle
パッケージを実行する前に暗号化します。
私が使用する暗号化アルゴリズムはAES
、対応するスクリプトはAESEncrypt.cs
、
復号化インターフェースは次のとおりです。
public static byte[] Encrypt(byte[] toEncryptArray)
復号化インターフェース:
public static byte[] Decrypt(byte[] toDecryptArray)
AssetStudio
入力されたlua
ものを逆にすることができAssetBundle
、逆にしたものが文字化けしていることがわかります。これは、暗号化が有効になったことを示しています。
注:
AssetStudio
ダウンロード アドレス: https://codechina.csdn.net/mirrors/perfare/assetstudio
11.パッケージ全体を梱包する
メニューをクリックしBuild / 打包APP
、
印刷するパッケージ全体のバージョン番号を設定し、 をクリックしてSave
から をクリックするとBuild APP
、生成されたものが同じレベルのディレクトリのディレクトリにAPP
配置されます。プラットフォームを例にすると、ファイルは自動的に次のように生成され、パッケージ化の時刻が記録されます。後続の増分パッケージを比較するのに便利です。Assets
Bin
Windows
LuaFrameworkFiles_版本号.json
LuaFramework
md5
MD5
12.ホットアップデートパッケージ
メニューをクリックしBuild / 打热更包
、
増分パッケージのバージョン番号を設定し、読み込むファイルのバージョン番号を設定しLuaFrameworkFiles_xxxx.json
、必要に応じて増分パッケージに入力するリソース ファイルを追加し、最後にホット アップデート パッケージのボタンをクリックします。生成されたホット アップデート パッケージはディレクトリ
に保存されます。次のように、サーバーにコピーして構成するだけです。Bin
Web
update_list.json
[
{
"appVersion": "1.0.0.0",
"appUrl": "https://blog.csdn.net/linxinfa",
"updateList":
[
{
"resVersion": "1.0.0.1",
"md5": "50d550486de1a72bd0caaa560128a9ad",
"size": 908405,
"url": "http://localhost:7890/res_1.0.0.1.zip"
}
]
}
]
md5
そして、あなたsize
はそれを使って見ることができます、それは非常にHash.exe
小さいです.ファイルをウィンドウにドラッグして表示します. ファイルは大文字で生成されていることに注意してください. 設定すると,小文字に変換されます.これは無料です〜)28KB
CODE CHINA
size
md5
md5
md5
ToLower
セブン、終了
では、まずはたくさん書きましょう~
最新情報に戸惑う学生さんの参考になれば幸いです。
私はLin Xinfaです: https: //blog.csdn.net/linxinfa
オリジナルであることは簡単ではありません。再投稿する場合は、ソースを示してください、ありがとうございます〜
私が好きなら、いいね、フォロー、ブックマークできます。技術的な質問がある場合は、メッセージまたはプライベートメッセージを残してください〜