tanaka's Programming Memo

プログラミングについてのメモ。

無料で使えるネットライブラリMirrorのざっくり紹介

f:id:am1tanaka:20200717212431p:plain

この記事は Unity アセット真夏のアドベントカレンダー 2020 Summer! – Unity公式 Asset Portal の15日目の記事です。

Unityには様々なネットワークサービスやライブラリアセットがありますが、今回はMirrorというネットワークライブラリアセットについてざっくりご紹介します!

assetstore.unity.com

※動画6のショットのRigidbodyを無効にする手順を7に移動しました(2020/9/2)

目次

ネットワークライブラリやサービスの種類

ネットワークライブラリやサービスは、ざっくりとサーバー主体のものとクライアント主体のものがあります。

サーバーを主体としたサービス

プレイヤー管理や課金の仕組み、プレイデータの保存、マーケティングのための分析ツールなどのサーバー機能を提供してくれるものです。代表的なものに、PlayFabやニフクラmobileなどがあります。

azure.microsoft.com

mbaas.nifcloud.com

スマホ向けであれば、以下のようなクロスプラットフォーム用のアセットもユーザー管理や課金アイテム、広告などのサービスを提供してくれます。

assetstore.unity.com

assetstore.unity.com

クライアント側の実装を助けてくれるライブラリ

プレイヤーのマッチングやプレイヤー間のデータの同期や遅延対策、ボイスチャットなどといったクライアント側でオンラインゲームを実装するのを助けるものです。代表的なものに、Photon Unity Networking(PUN)やPhoton Bolt、UNetなどがあり、今回のMirrorはこっち側のライブラリです。

www.photonengine.com

www.photonengine.com

mirror-networking.com

Photonはサーバー側もクライアント側も幅広くサービスやライブラリが揃っています。PlayFabは強力なサーバー側のサービスが揃っていて、クライアント側にはPhotonを使うといった組み合わせるができるようです。ニフクラはサービスを提供しているだけではなく、技術的な相談もしやすそうな印象です。

AWSGoogle Cloudももちろんあるのですが、サーバーのホストからリアルタイム利用まで多岐に渡りすぎてまとめきれないので、ここではありますぐらいに留めます。

Mirrorとは

今回紹介するMirrorは、vis2kさんが無料で公開しているオープンソースのネットワークライブラリアセットです。以下、アセットストアの冒頭より。

Mirrorは、低レベルのネットワークライブラリTelepathy上に構築したUnity用の高レベルのネットワークAPIです。 Mirrorは、uMMORPGやCubicaといったMMO規模のネットワーキングのために開発、そしてテストされました。

PUNやPhoton Bolt、UNetと同様、Unityでプレイヤー間の同期をするなど、オンラインゲームのPC間の同期などを助けてくれるライブラリです。以下のような機能を持っています。

  • サーバーとクライアントを1つのプロジェクトで実装するための属性やパラメーター
  • サーバーやクライアントを接続するためのNetworkManagerとNetworkManagerHUD
  • ゲームオブジェクトの位置やアニメを同期させるNetworkTransform, NetworkAnimatorなど
  • パラメーターを自動同期するSyncVarやSyncEventなど
  • ネットワーク間で情報をやりとりするCommandやClientRPC、各種コールバック
  • Room機能
  • などなど

Mirrorの得意分野と不得意分野

個人的に感じている得意不得意は以下の通りです。

  • 得意分野
    • インターネットがない環境でも動かせる
    • 機能がコンパクトで設計が素直なので分かりやすい
    • ゲームサーバーを自前で運用できる
    • 数千接続といった比較的大規模なものが構築可能
    • 更新が続いている
  • 苦手分野
    • サービスをインターネットに手軽に公開できない
    • 行動予測などがない
    • サポートが弱い(他は大手企業ばかりなので)

Mirrorを選択する決め手

MirrorとPhotonの最大の違いは、良くも悪くもプレイヤーのマッチングに公式サーバーが必要ないということだと思います。PhotonはLAN内で接続する場合でも公式サーバーを通す必要があります。そのためインターネットがない環境では接続ができません。ガチガチのセキュリティーが施されている学校内やイベントでの展示などでこれがネックになる恐れがあります。MirrorはNet DiscoveryといったLAN内でのサーバー検索機能を使ったり、サーバーのIPが固定であればIP直打ちで接続できるのでインターネットに接続されていないLAN環境でも動かすことができます。

自分の場合は、学園祭や学校の体験入学用のプロジェクトにMirrorを採用しました。

インターネットごしに接続する予定があるのであれば、素直にPhoton系のサービスでよいと思います。20名程度の試用レベルの接続であれば無料でマッチングやリレーサービスを利用することができます。非リアルタイムであったりWebGLで使うならPUN2、リアルタイムオンラインゲームに特化するならPhoton Boltがオススメです。

学習コストと教材

学習コスト

学習コストは前提知識次第ですが、UNetを使ったことがあればほぼそのままなので1~2日で使えるのではないかと思います。

オンラインゲーム作りのノウハウがない場合は、オンラインゲームを動かすための考え方を理解するところからなので1ヶ月以上はかかりそうです。

オンラインゲーム作りのノウハウがあれば、Mirrorの使い方自体は1週間もあれば使えるようになると思います。

教材

Mirrorの教材です。以下の順で目を通していくとよいのではないかと思います。

ネットワークは、どこで何が動いているのかの仕組みを理解していないと、マニュアルを読んだり説明を聞くだけでは理解するのが難しいです。まずはサンプルや動画を見て動きを確認したり、実際に自分でも実装をしてみながら、マニュアルを併せて読んでいくのがよいと思います。

インターネットにサービスを公開するには(調査中)

Mirrorから使えるList Serverというマッチングのサービスが月額20ドルで用意されています。

mirror-networking.com

List Serverがマッチングのためのアクセスポイントになり、自宅サーバーやホスティングサービスなどに立てているゲームサーバーのIPアドレスとポートを接続相手に伝えてプレイヤー同士を接続するようです。ゲームサーバーで指定する指定のポートは、インターネットからアクセスできるように設定しておく必要があります。NATパンチスルーがないので、一般のプレイヤーが気軽にホストになる、というような運用は難しそうです。

List Serverを利用するには、Mirrorのアセットに含まれているサンプルコードを自分のプロジェクトに組み込むよう紹介されていて、PhotonやUNetのように最初から接続できる機能が含まれている訳ではないようです。

サーバー環境を丸ごと自前で構築できるので、サーバーコストはList Serverと原価のみ、ということが可能ではあります。また、ディアブロのようにサーバー側の知識を持ったプレイヤーが野良サーバーを立ち上げて自由に遊んでもらうようなこともできます。手軽ではありませんが、オープンソースなので自由度は圧倒的です。

英語ですが、以下の公式ドキュメントにサーバーの立て方やAWSでのセットアップ例が紹介されています。

mirror-networking.com

以下、UNet版のゲームサーバーの立ち上げチュートリアルです。Mirrorも対応しているようです。これも英語ですが...

noobtuts.com

Mirrorの組み込み手順の紹介動画

簡単なサンプルプロジェクトを作って、Mirrorでオンライン化するチュートリアル動画など用意してみました。

サンプルプロジェクトは以下からダウンロードできます。

github.com

1. サンプルプロジェクトの準備

youtu.be

2. Mirrorのインポート

youtu.be

3. プレイヤーをオンラインに登場

NetworkIdentityやNetworkManagerなどのMirrorの根幹コンポーネントの紹介。

youtu.be

4. プレイヤーの操作をネットに対応

NetworkBehaviourでローカルプレイヤーを制御する。

youtu.be

5. プレイヤーごとに色を変えるカスタマイズ

カスタムプレイヤーオブジェクトの実装例。

youtu.be

6. ショットをネットに対応

変数を同期するSyncVarやサーバーのメソッドを呼び出すCommandの利用。

youtu.be

※Rigidbodyを無効にする処理を7に移動しました(2020/9/2)

7. ショットの色を設定

youtu.be

※Rigidbodyを無効にする処理を最後に追加しました(2020/9/2)

8. 持ち弾数の管理

youtu.be

9. ミスの処理の概要

サーバーとクライアントの役割のざっくり説明。

youtu.be

10. プレイヤーと弾を消す

youtu.be

11. 爆発をネットに対応

youtu.be

12. ネットからの離脱、GUIの表示調整

カスタムのNetworkManagerによる接続管理。

youtu.be

まとめ

Mirrorは、プレイヤー間の接続ゲームの状態やキャラクター、オブジェクトの同期といったオンラインゲームを開発する上で役立つ機能を提供してくれる軽量なオープンソースのネットワークライブラリです。

インターネット接続のないLAN環境で動かすことができ、自分でサーバーを立ち上げる知識があれば自由にゲームサーバーを構築できます。がっちりと企業がついてサポートしてくれる他のネットワークサービスとは趣が異なり、良くも悪くも自前であらゆることができる自由度の高いライブラリです。

展示であったり、利用用途が限定されている場合は自由度の高さが魅力です。また、本格的にがっちりとサーバーまで勉強したり開発したりする時に、オープンソースなのでよい題材になるのではないかと思います。

おまけ

Mirrorの作者さんがDOTSNETという新しいネットワークライブラリアセットを公開しました。$100の有料アセットなのですが、MirrorをECSで高機能化したものだそうです。Unity2020.1以降向けで、ECSの基礎知識が必要な上に$100という攻め込みまくったアセットですが、うまく動作すれば処理速度や消費電力など恩恵は大きそうです。

使ったことがないのでオススメできるだけの知識はありませんが情報共有までに。

参考URL

Mirrorでプレイヤーごとに違うプレハブからプレイヤーオブジェクトを生成する

f:id:am1tanaka:20200717212431p:plain

Mirrorは、UNetをベースに設計された高評価のMMOスケールにも対応できるというネットワークAPIライブラリです。

mirror-networking.com

MirrorでデフォルトのNetworkManagerを使った場合、Player Prefab欄に設定されているプレハブをプレイヤー用のゲームオブジェクトとして自動的に生成します。NetworkManagerを継承すればプレイヤーごとに違うプレハブからプレイヤーを生成することができるという自分用のメモです。

目次

実行環境

  • Unity2019.3.15f1
  • Mirror16.1.1

ざっくり手順

プレイヤー用のプレハブを用意する

違いが分かるようにメッシュを変えたり動きを変えたプレイヤー用のプレハブをいくつか用意します。NetworkIdentityをアタッチしてあれば一先ず動きます。

プレイヤー定義用のScriptableObjectを作成

クライアントからどのプレハブを使うかを送る手段が考えつかなかったので、ちょっと乱暴ですがScriptableObjectにプレイヤー用のプレハブを配列で持たせて、そのインデックスで生成するオブジェクトを指定するようにします(ResourcesやAssetBundleを使えば、プレハブ名などでいけると思います)。

PlayerPrefabList.cs

配列の参照用のenumと、GameObjectの配列を持つScriptableObjectを宣言しています。PlayerTypeの内容は、用意するプレイヤー用プレハブに応じて書き換えてください。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum PlayerType
{
    Green,
    Red
}

[CreateAssetMenu(menuName ="AM1Mirror/PlayerPrefabList")]
public class PlayerPrefabList : ScriptableObject
{
    public GameObject [] playerPrefs = null;
}

これができたら、ProjectウィンドウのCreateから AM1Mirror > PlayerPrefabList を選んでスクリプタブルオブジェクトを作成します。作成したら、enumの定義順に応じてプレイヤー用のプレハブをInspectorウィンドウから設定しておきます。

NetworkManagerのサブクラスを作成する

公式ガイドの以下をもとに、今回の要であるカスタムのNetworkManagerを作ります。

mirror-networking.com

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Mirror;

public class NetworkManagerCP : NetworkManager
{
    PlayerType spawnPlayerType;

    [Tooltip("プレイヤープレハブリスト"), SerializeField]
    PlayerPrefabList playerPrefabList = null;

    public void SetPlayerType(PlayerType pt)
    {
        spawnPlayerType = pt;
    }

    /// <summary>
    /// サーバー開始時、プレイヤーキャラクターのメッセージを登録
    /// </summary>
    public override void OnStartServer()
    {
        base.OnStartServer();

        NetworkServer.RegisterHandler<CreateCharacterMessage>(OnCreateCharacter);
    }

    /// <summary>
    /// クライアント側で接続した時に、選択してあるプレイヤーのプレハブをメッセージで送信
    /// </summary>
    /// <param name="conn"></param>
    public override void OnClientConnect(NetworkConnection conn)
    {
        base.OnClientConnect(conn);

        CreateCharacterMessage ccm = new CreateCharacterMessage
        {
            playerType = spawnPlayerType
        };

        conn.Send(ccm);
    }

    /// <summary>
    /// メッセージがクライアントからサーバーに到着したら、届いたプレハブでプレイヤー生成
    /// </summary>
    /// <param name="conn"></param>
    /// <param name="messages"></param>
    void OnCreateCharacter(NetworkConnection conn, CreateCharacterMessage messages)
    {
        Transform tr = GetStartPosition();
        GameObject go = Instantiate(playerPrefabList.playerPrefs[(int)messages.playerType], tr.position, tr.rotation);
        NetworkServer.AddPlayerForConnection(conn, go);
    }

}

通信を開始する

通信を開始するためのクラスSimpleNetManを作成します。これはNetworkManagerCPに統合できるのですが、設定がNetworkManagerの設定に埋もれるのが見辛いので分けました。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Mirror;

public class CreateCharacterMessage : MessageBase
{
    public PlayerType playerType;
}

public class SimpleNetMan : MonoBehaviour
{
    public enum ConnectType
    {
        Host,
        Client
    }

    [Tooltip("プレイヤーの種類"), SerializeField]
    PlayerType playerType = PlayerType.Green;
    [Tooltip("接続の種類"), SerializeField]
    ConnectType connectType = ConnectType.Host;
    [Tooltip("ホストのIPアドレス"), SerializeField]
    string ipAddress = "localhost";

    NetworkManagerCP networkManager = null;

    private void Awake()
    {
        networkManager = GetComponent<NetworkManagerCP>();
        networkManager.SetPlayerType(playerType);
        StartCoroutine(Online());
    }

    IEnumerator Online()
    {
        yield return null;  // 1フレーム待つ

        if (connectType == ConnectType.Host)
        {
            networkManager.StartHost();
        }
        else
        {
            networkManager.networkAddress = ipAddress;
            networkManager.StartClient();
        }
    }
}

IEnumeratorでやってるのは、なんとなく1フレーム待った方が初期化が終ってそうでいいかな、という雰囲気でやったことです。Awake()内でやってもいいかも。

仕上げ

作成したSimpleNetManNetworkManagerCPNetworkManagerのような名前のゲームオブジェクトに一緒にアタッチします。

SimpleNetManでは、生成したいプレイヤータイプを設定して、ホストかクライアントか選択して、ホストのIPアドレスを設定します。これらのパラメーターを設定するメニューを用意すれば実行時に変更できます。

NetworkManagerCPでは、下の方にあるPlayer Prefab List欄に、最初に作成したScriptableObjectをアタッチして、ScriptableObjectに設定したプレイヤー用のプレハブをRegistered Spawnable Prefabs欄に全て追加します。これをしないとプレイヤーオブジェクトがネットワーク上に生成できず、エラーになります。

まとめ

ざっくりですがこんな感じでできました。ScriptableObjectを利用するなど何らかの方法で、クライアントからホストへ生成したいプレイヤープレハブをNetworkMessageで送信して、それをもとにStartHost()やStartClient()が実行されたら、NetworkMessageを受け取って記録して、クライアントの生成の段階で指定されたプレハブからプレイヤーオブジェクトをInstantiateして、ネットワークに追加します。

この記事では、スクリプトが分かれていたり、Inspectorウィンドウでプレイヤーや接続の種類を設定する不自然な状態になっていますが、これは体験入学用に全員がUnityエディターで作業をすることを前提としているからです。通常の利用であれば、プレイヤーを選択するルームなどを作って、そこで選ばれたものをメッセージで送ってゲーム開始、という感じになると思います。

とりあえず、こんな流れで、こんな感じのコードで異なるプレハブからプレイヤーを生成できるという記事でした。

おまけ:Mirrorのイベントの発生順

重要なドキュメントですが、なんか下の方にあった...

mirror-networking.com

これを見ると、まずはStart()が呼ばれて、OnStartServer()OnStartHost()より後に呼ばれています。ということで、NetworkManagerのStartHost()やStartClient()で通信を開始します。

参考URL

Laravelのバージョン指定でプロジェクトを作る

Laravelの最新版を入れると7が入るけど、今は6.xを使いたいというとき、とりあえず以下でバージョン指定できる。

composer create-project --prefer-dist laravel/laravel blog "6.*"

参考URL

macのLaravelを5.xから最新版にアップデートする

PHPなどに問題がなければ、以下でいけました。

  • laravelをインストールした.composerフォルダーを開く
  • 以下を実行
composer global require laravel/installer
composer update

これでうまくいかない場合は、以下も参照。

brewあたりから更新

かなり苦戦したので、ざっくりやったこと。

brew update
brew upgrade
rm /usr/local/etc/php/7.1/conf.d/*
brew untap homebrew/php
atom ~/.composer/composer.json

Atomが開いたら、phpunitを以下に修正。

        "phpunit/phpunit": "~7.0",

以上で上書き保存してから、以下実行。

composer global update

以下で、利用できるphpを調べる。

brew search php

7.2を使うなら、

brew install php@7.2

これをリンクします。

brew link php72 --force

以下を実行して、パスを設定します。

echo 'export PATH="/usr/local/opt/php@7.2/bin:$PATH"' >> ~/.bash_profile
echo 'export PATH="/usr/local/opt/php@7.2/sbin:$PATH"' >> ~/.bash_profile

ターミナルを再起動します。

valetのを再インストールします。

valet stop
valet uninstall
composer global require laravel/valet
valet install
valet restart

以上で、動きました。どのあたりが決めてかはわからず、余計な物もあるかもしれませんが、ひとまずコマンドのメモということで。

参考URL

ラズパイ4の電源不安定

これまで問題なく動いていたラズパイ4が急に起動しなくなりました。TVにつなげるとリカバリーモードまでは行けるのですが、その先で画面が表示されずターミナルによる接続もできません。起動の際に雷マークが表示されたため、電圧不足であることが分かりました。雷マークについては以下のようなものです。

raspi.maruzonet.com

どうやらUSBケーブルによる電圧降下があって、推奨されている5V 3Aきっちりの電源だと電圧が足りなくなってしまうようです。参考↓

jsdkk.com

今調べると、ラズパイ4用の電源は殆どが5.1Vなのですね。アマゾンで5.1V 3Aのラズパイ4用とあったケーブルを購入して無事に解決しました。私が購入したものは品切れで紹介できないのですが、スイッチサイエンスさんの以下のやつとかは確実そうです。

www.switch-science.com

まとめ

比較的初期に千石電子さんでセットで購入したものに付属していた電源を使っていて、これまで問題なく使えていました。あれこれインストールしたからか、あるいは電源周りの汚れやらガタつきやらで状況が変わったからか、急に動かなくなったのが今回のきっかけでした。もし、同じように急に起動しなくなって、雷マークが表示されているようでしたら、電源を調べてみてください。

電源不足以外ですと、メモリカードの故障、TVモニターに映らなくなる、などが、ラズパイの突然起動しない問題の原因として挙げられていました。「ラズパイ 起動しない」などで検索して、自分の症状にあったものを見つけてみてください。

参考URL

BurstのBurstCompileがVisualStudioでエラー

Burstを触ってみようと思って以下のQuick Startを試してみました。

docs.unity3d.com

Unityでは動くものの、Visual Studio[BurstCompile(CompileSynchronously = true)]がエラーになる。

以下に「Visual StudioをUnity Game Packageから入れなおしたら直った」とありました。

https://forum.unity.com/threads/visual-studio-unity-mathematics-unity-burst-not-found.711215/

ということで、以下のことをごちゃごちゃやってたら直しました。

  • Visual Studio Installerを起動
  • Visual Studio Community 2019変更をクリック
  • Unityによるゲーム開発のチェックを外して、変更ボタンをクリックして、一旦Unityの拡張を解除
  • Unity Hubのインストールから、Unity2019.3.2モジュールの追加をクリックして、Microsoft Visual Studio Community 2019にチェックを入れて実行をクリック
  • インストールが完了したら、Visual Studio Installerに戻って、Unityによるゲーム開発にチェックを入れて、変更をクリック
  • Visual Studio Installerのトップに戻って、Visual Studio Community 2019詳細 > 修復をクリック
  • 修復が完了したら、指示に従ってPCを再起動

以上で直りました。どの段階で直ったか分からないので、やったこと全部書きました。

参考URL

eTrex30xの日本語化&OSMのインストール

長年愛用してきたeTrex20の電源スイッチが物理的に壊れまして、もう十分天寿を全うしたであろうという判断で無理には修理せず、eTrex30xを購入しました。新機種のeTrex22Xや32xが出たばかりですが、なにせ強烈に安かったもので。

英語版が2万円きってる!20より安いぐらいじゃん。コンパスを使ってみたいというのもありゲットしました。英語版なので、お約束の日本語化ですが、日本版のOSM地図は、ファームウェアのダウングレードではできなくなっていました!!

ということで、こちらのサイトにお世話になりました。あらかじめ目を通して内容が分かるか確認してください。バイナリエディターを使うので、よく分からない場合は素直に日本語対応版の購入を!!

diary.cyclekikou.net

メニューの日本語化はこちらのサイトにお世話になりました。

tom-brs.hatenablog.com

目次

はじめに

いざという時に備え、必ず元のファイルを全てPCにコピーしておくなどして、バックアップを取りましょう。ここから先は自己責任です。保証が欲しい場合は正規のルートで日本語版をご購入ください!!

バックアップ

eTrex30xの中身を全てバックアップしておきます(最初、手順を間違えて台湾版になって日本語化に失敗したので、すぐにバックアップが役に立ちました。バックアップ大切)。

  • eTrexに電池を入れて、電源は入れずにPCにUSBケーブルで接続します
  • しばらくすると接続されて、フォルダーを開けるようになります
  • Garmin eTrex 30xと表示されるドライブの中身を全て選択して、PCにコピーしておきます

ファームウェアを最新にする

ファームウェアを最新にしておきます。

メニュー画面が表示されたら完了です。

日本語化

続けて、nuvi200_TWN_v460の方です。

  • nuvi200_TWN_v460.exe の名前を nuvi200_TWN_v460.zipに変えます
    • exeファイルを実行して無理やり先に進めると台湾版になるので、zip展開するように!!
  • nuvi200_TWN_v460などのフォルダーを作成して、その中にnuvi200_TWN_v460.zipを展開します
  • 展開したフォルダーのnuvi200_TWN\Garmin\ExtDataを開いて、006-D1053-64.binの名前を006-D0952-06.binに変更します
  • 006-D0952-06.binを、eTrex\Garmin\ExtDataフォルダーに上書きコピーします

以上できたらeTrexをPCから外して電源を入れます。

言語選択でJapaneseを選択すれば、メニューが日本語に変わります。

日本語地図を入れる

日本語用の地図を入れます。

  • eTrexの電源を切ってから、PCにUSBで接続します
  • Downloads – OpenStreetMap for GARMIN を開きます
  • 等高線なしか、等高線ありの2種類あります。入れたい方の日本語のUTF8のをダウンロードします
  • ダウンロードしたZIPファイルを展開します
  • 展開したら、中のimgファイルを複製して、gmapsupp.orgなどの名前にしておきます
  • gmapsupp.imgバイナリエディターStiringで開きます
  • 検索・移動メニューから、置換を選択します
  • 以下で置換します
    • 検索データ E9 FD 13 00 04 80
    • データ種別 16進データ
    • 置換データ A4 03 13 00 04 80
    • データ種別 16進データ
    • 置換範囲 データ全体
    • 以上設定したら、一括置換をクリックします
  • かなりの箇所の置換が行われます。完了したら、上書き保存します
  • 作成したgmapsupp.imgファイルと、gmapsupp.orgファイルの2ファイルを、eTrex\Garminフォルダーにコピーします

コピーにはかなり時間がかかります。コピーが完了したら、eTrexをPCから外して、起動して地図を読み込みます。この段階では、地名はちゃんと表示されません。最後にファイルを元のに置き換えます。

  • eTrexの電源をオフ
  • eTrexをPCにUSB接続します
  • eTrex\Garminフォルダー内のgmapsupp.imgを削除します(拡張子を間違えないように!!)
  • gmapsupp.orgの名前を、gmapsupp.imgに変更します

以上で完了です。eTrexをPCから外して、電源を入れて確認してください。

まとめ

ファームウェアのダウングレードが駄目になっているのを知らず、全部やり直しました^^; 自己救済が難しい場合は、素直に日本語版を購入した方がよさそうです。この方法もいつ塞がれるか分かりませんし、この辺が並行輸入盤の値段が下がった理由かも知れませんね。

Open Street Mapの更新はなかなか早い感じなので有難いです。

参考URL