実現したいこと
- PC上のUnityアプリケーションがサーバーと更新チェックを行い、更新が必要であればサーバーからInstallerをダウンロードして自ら再インストールする
- 今回はローカルサーバーを立てて、すべてローカル環境で行います
環境
ホスト
- Unity5.5(バージョン依存はないと思うので、それ以外のバージョンでも動くと思います)
- Windows10 Pro(会社支給マシン)
ゲスト
- ElementaryOS Loki0.4(なかみはUbuntu16.04LTS)
- 今回はVirtualBoxでいれました
- なぜかGuestAdditionalがインストールできなかったのでドラッグ&ドロップができず、共有フォルダ経由でやり取りするのがかなり面倒なので、素直にUbuntuを使ったほうがいいかもです…
- サーバーサイドは今回はnode.js使いましたが、RubyでもPHPでもなんでも大丈夫です
手順
Unityアプリケーションをつくる
シーン
スクリプト
- UpdateMenuController.cs をつくります
- StreamやProcessの処理は安全に処理できてないと思うのでコピペで使わないほうがいい気がします
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using System.Diagnostics;
public class UpdateMenuController : MonoBehaviour {
private string downloadURL;
class Response {
public string url = "";
}
IEnumerator Start() {
WWW www = new WWW("http://192.168.1.100:8888/check");
yield return www;
Response res = JsonUtility.FromJson<Response>(www.text);
if (res.url != "") {
downloadURL = res.url;
}
}
public void OnClickUpdateButton() {
StartCoroutine("UpdateApplication");
}
IEnumerator UpdateApplication() {
WWW www = new WWW(downloadURL);
yield return www;
string path = Application.temporaryCachePath;
string filePath = path + "/setup.exe";
FileStream stream = new FileStream(filePath, FileMode.Create, FileAccess.ReadWrite);
BinaryWriter writer = new BinaryWriter(stream);
writer.Write(www.bytes);
writer.Flush();
writer.Close();
Process process = new Process();
process.StartInfo.FileName = filePath;
process.Start();
}
public void OnClickQuitButton() {
Application.Quit();
}
}
- あとは(どこでも大丈夫ですが)UpdateMenuに上記スクリプトをアタッチして、それぞれのボタンコンポーネントのonClick()にそれぞれの処理をバインドしてあげると動くはずです
- ここではIPを指定していますが、仮想マシンを立ててから
ifconfig
などで調べて適宜変更して下さい
注意点
- 実際に運用する際は最初のStartでのWWWのURLにアプリケーションのバージョン情報や使用しているデバイス情報などのパラメーターを付与して、サーバー側でそれに応じたInstallerのURLを返してあげるのがいいと思います
- ここでは必ずurlが返ってくる想定仕様にしていますが、更新が不要であれば、なにも起きないようにする分岐が必要になります
Installerにコンパイルする
-
まずUnityアプリケーションのビルド先はBuildsなどのフォルダを作ってそこにエクスポートするのがコンパイルするときに楽なので作って、そこに出力しておきましょう
-
Unityアプリケーションをビルドしたら、EXEファイルとXXX_Dataフォルダが生成されると思いますので、それをまるっとInstallerにコンパイルします
-
こちらのブログを参考に、InnoSetupCompilerをつかってInstaller化します
- http://martin-klappacher.com/tutorial-windows-installer-for-your-unity-game/
- ほかにいいツールや方法などがあればご教授いただけると幸いです
-
またこのInnoSetupCompilerを使うのは自己責任でお願いします
-
コンパイル後に出力されるファイルは
setup.exe
とします- また設定ファイルである
.issファイル
やsetup.exe
をBuildsの中に入れてしまうとコンパイル時に一緒に含まれてしまうので別の場所に保存するようにしたほうがいいと思います
- また設定ファイルである
VirtualBoxにゲストOSをいれる
環境設定
- VirtualBoxの公式サイトからWindowsHost版をダウンロードしてインストールします。
- ISOイメージをElementaryの公式サイトからダウンロードしてインストールします
- 寄付額のフォームがありますがカスタムを押して0と入力すれば無料でダウンロードできます
仮想マシンの作成
- VirtualBoxを起動して、「新規」を押して仮想マシンの作成を行います
- Elementaryは中身はUbuntuなのでバージョンはUbuntuで大丈夫です
- メモリサイズやハードディスク、ハードディスクのファイルタイプはだいたいデフォルトのままで大丈夫です
OSインストール
OS初期設定
- インストール完了後に再起動して、デスクトップ画面が表示されたらまずターミナルを開いて更新をかけます
$ sudo apt-get update
$ sudo apt-get upgrade
- あとは好みでEditerを入れたりしてください
- 自分は以下をインストールしました
- Atom(エディター)
- Chrome(ブラウザ)
- mozc(Google日本語入力のLinux版)
- linuxbrew(homebrewのlinux版)
- Macとインストールパスが違うので注意
- それぞれのインストール方法などは各公式サイトをご確認下さい
- 自分は以下をインストールしました
ネットワーク設定
- ホストからアクセスできるように設定します
- 仮想マシンを一度Shutdownしてから仮想マシン>設定>ネットワーク>アダプター2にホストオンリーアダプターを追加する
- 仮想マシン>設定>ネットワーク>アダプター1(NAT)>ポートフォワーディング>高度>ホストとゲストのポート8888をあけておく
- 上記設定が終わったら
ifconfig
でゲストOSのIPアドレスを調べます- ここでは
192.168.1.100
であると仮定します
- ここでは
node.jsでサーバーをつくる
node.jsのインストール
- linuxbrewでndenvをインストールしました
- ndenvはフォルダ単位でnodeのバージョンを指定できるので重宝してます
- ndenvのinstallを使うにはnode-buildが必要なのでそちらもインストールしておきます
$ brew install ndenv
$ echo 'export PATH="$HOME/.ndenv/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(ndenv init -)"' >> ~/.bash_profile
$ exec $SHELL -l
$ git clone https://github.com/riywo/node-build.git $(ndenv root)/plugins/node-build
$ ndenv install v6.11.0
$ cd ~/workspace/project
~/workspace/project$ ndenv local v6.11.0
~/workspace/project$ node -v
v6.11.0
※設定がうまくいかないときは公式サイトをご確認下さい
サーバーをつくる
~/workspace/project$ npm init -y
- 上記を実行するとpackage.jsonが自動生成されます
- パッケージの依存解決とかしてくれるんですが今回は標準ライブラリだけなので特にすることはないです
- 次に index.js を作ります
var http = require('http');
var fs = require('fs');
var path = require('path');
var server = http.createServer();
server.on('request',function(req, res){
if(req.url === "/check"){
res.writeHead(200, {'Content-Type':'application/json; charset=utf-8'});
res.write('{ "url":"http://192.168.1.100:8888/download" }');
res.end();
}else if(req.url === "/download"){
var filePath = path.join(__dirname, 'assets/setup.exe');
var stat = fs.statSync(filePath);
res.writeHead(200, {
'Content-Type':'application/octet-steam',
'Content-Length':stat.size,
'Content-Disposition':'attachment; filename=setup.exe'
});
var readStream = fs.createReadStream(filePath);
readStream.pipe(res);
}
});
server.listen(8888,'192.168.1.100');
console.log('Server running at http://192.168.1.100:8888');
- 特にnpm installする必要もなく標準ライブラリだけで動きます
- ここでは
http://192.168.1.100:8888/check
とhttp://192.168.1.100:8888/download
というリクエストを想定しています -
assetsフォルダ
に先程コンパイルしたInstaller(setup.exe)を配置します。ファイル構成は以下のようになるはずです
~/workspace/project$ tree
.
├── assets
│ └── setup.exe
├── index.js
└── package.json
サーバーの起動
~/workspace/project$ node index.js
Server running at http://192.168.1.100:8888
- 起動したら一旦ゲストOSのブラウザで
http://192.168.1.100:8888
にアクセスしてみましょう - 上記が問題なければ今度はホストからアクセスして試してみましょう!
アプリから更新
- サーバーが動いており、ホストからの疎通も確認できたらさっそく、ホストでUnityアプリケーションを起動してUpdateButtonを押してみましょう!