LoginSignup
13

More than 5 years have passed since last update.

Unityアプリケーションが自身で自身を更新する方法

Posted at

実現したいこと

  • PC上のUnityアプリケーションがサーバーと更新チェックを行い、更新が必要であればサーバーからInstallerをダウンロードして自ら再インストールする
  • 今回はローカルサーバーを立てて、すべてローカル環境で行います

環境

ホスト

  • Unity5.5(バージョン依存はないと思うので、それ以外のバージョンでも動くと思います)
  • Windows10 Pro(会社支給マシン)

ゲスト

  • ElementaryOS Loki0.4(なかみはUbuntu16.04LTS
    • 今回はVirtualBoxでいれました
    • なぜかGuestAdditionalがインストールできなかったのでドラッグ&ドロップができず、共有フォルダ経由でやり取りするのがかなり面倒なので、素直にUbuntuを使ったほうがいいかもです…
  • サーバーサイドは今回はnode.js使いましたが、RubyでもPHPでもなんでも大丈夫です

手順

Unityアプリケーションをつくる

シーン

  • とりあえず起動時に更新チェックするようにしたいので、1つだけシーンを作ります
  • CanvasにPanelをいれて、その中に更新ボタンと終了ボタンをつくります
  • Unity 5.5.2f1 Personal (64bit) - Opening.unity - UpdateCheck - PC, Mac & Linux Standalone _DX11_ 2017-06-14 16.30.01.png

スクリプト

  • 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化します

  • またこのInnoSetupCompilerを使うのは自己責任でお願いします

  • コンパイル後に出力されるファイルは setup.exe とします

    • また設定ファイルである.issファイルsetup.exe をBuildsの中に入れてしまうとコンパイル時に一緒に含まれてしまうので別の場所に保存するようにしたほうがいいと思います

VirtualBoxにゲストOSをいれる

環境設定

  • VirtualBoxの公式サイトからWindowsHost版をダウンロードしてインストールします。
  • ISOイメージをElementaryの公式サイトからダウンロードしてインストールします
    • 寄付額のフォームがありますがカスタムを押して0と入力すれば無料でダウンロードできます

仮想マシンの作成

  • VirtualBoxを起動して、「新規」を押して仮想マシンの作成を行います
  • 仮想マシンの作成 2017-06-14 15.21.26.png
  • Elementaryは中身はUbuntuなのでバージョンはUbuntuで大丈夫です
  • メモリサイズやハードディスク、ハードディスクのファイルタイプはだいたいデフォルトのままで大丈夫です

OSインストール

  • Oracle VM VirtualBox マネージャー 2017-06-14 17.16.01.png
  • 上記が終わって仮想マシンができたら、起動します
  • 起動時に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/checkhttp://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を押してみましょう!

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13