GoogleMapをUnity上で表示する方法
現在オライリー・ジャパンの書籍"UnityによるARゲーム開発"を参考にしてゲーム開発しています。
問題
上の画面では、Planeを配置してアッタチしたGoogleMapTilesからgoogleマップを表示させようとしているのですがうまくいきません。
(正常に動作すればこのようにPlaneにgoogleマップが表示されます。)
エラーの内容
一つ目はgoogleマップへの画像リクエストのクエリの表示で、
Tile 0x0 requested with
center=37.62815,-122.4265 // リクエストする地図の中心の座標の緯度と経度
&zoom=15 // 地図のズームレベル
&size=640x640 // リクエストされた画像の画素サイズ
&scale=2
&maptype=roadmap // 地図の種類(この場合は道など)
&format=png // 取得する画像の形式
&style=element:geometry|invert_lightness:true|weight:3.1|hue:0x00ffd5
&style=element:labels|visibility:off&sensor=false
二つはエラーになります。
表示する画像にエラーがあった時に表示される文章のようです。
Error loading tile 0x0: exception=HTTP/1.1 403 Forbidden
UnityEngine.MonoBehaviour:print(Object)
packt.FoodyGO.Mapping.<_RefreshMapTile>d__16:MoveNext() (at Assets/FoodyGo/Scripts/Mapping/GoogleMapTile.cs:123)
UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)
"HTTP/1.1 403 Forbidden"はクライアントエラーレスポンスコードで、サーバーがリクエストを理解したものの、認証が拒否されたことを示しているようなので、APIの取得に失敗している可能性があります。
また、他の座標を示しても結果は変わりませんでした。
詳しい方がいらっしゃいましたら、エラーの解決法を教えていただきたいです。
ソースコード
ソースコード(PlaneにアタッチしているGoogleMapTlle.csなど)は以下のリンクから手に入ります。
Chapter2.unitypackage
using UnityEngine;
using UnityEngine.Networking;
using System.Collections;
using packt.FoodyGo.Mapping;
using packt.FoodyGo.Services;
namespace packt.FoodyGO.Mapping
{
[AddComponentMenu("Mapping/GoogleMapTile")]
public class GoogleMapTile : MonoBehaviour
{
public enum MapType
{
RoadMap,
Satellite,
Terrain,
Hybrid
}
//Google Maps API Staticmap URL
private const string GOOGLE_MAPS_URL = "https://maps.googleapis.com/maps/api/staticmap";
[Header("Map Settings")]
[Range(1,20)]
[Tooltip("Zoom Level, 1=global - 20=house")]
public int zoomLevel = 1;
[Tooltip("Type of map, Road, Satellite, Terrain or Hybrid")]
public MapType mapType = MapType.RoadMap;
[Range(64,1024)]
[Tooltip("Size in pixels of the map image")]
public int size = 640;
[Tooltip("Double the pixel resolution of the image returned")]
public bool doubleResolution = true;
public MapLocation worldCenterLocation;
[Header("Tile Settings")]
[Tooltip("Sets the tiles position in tile units")]
public Vector2 TileOffset;
[Tooltip("Calculated tile center")]
public MapLocation tileCenterLocation;
[Tooltip("Calculated tile corners")]
public Vector2 TopLeftCorner;
public Vector2 BottomRightCorner;
[Header("GPS Settings")]
[Tooltip("GPS service used to locate world center")]
public GPSLocationService gpsLocationService;
private double lastGPSUpdate;
// Use this for initialization
void Start ()
{
RefreshMapTile ();
}
// Update is called once per frame
void Update ()
{
// 新しい位置が取得されたかどうかを確認する
if (gpsLocationService != null &&
gpsLocationService.IsServiceStarted &&
lastGPSUpdate < gpsLocationService.Timestamp)
{
lastGPSUpdate = gpsLocationService.Timestamp;
worldCenterLocation.Latitude = gpsLocationService.Latitude;
worldCenterLocation.Longitude = gpsLocationService.Longitude;
print("GoogleMapTile refreshing map texture");
RefreshMapTile();
}
}
public void RefreshMapTile() {
StartCoroutine(_RefreshMapTile());
}
IEnumerator _RefreshMapTile ()
{
// タイル中心の緯度/経度を取得
tileCenterLocation.Latitude = GoogleMapUtils.adjustLatByPixels(worldCenterLocation.Latitude, (int)(size * 1 * TileOffset.y), zoomLevel);
tileCenterLocation.Longitude = GoogleMapUtils.adjustLonByPixels(worldCenterLocation.Longitude, (int)(size * 1 * TileOffset.x), zoomLevel);
var url = GOOGLE_MAPS_URL;
var queryString = "";
// 地図タイルをリクエストするクエリ文字列パラメーターを作成する
queryString += "center=" + WWW.UnEscapeURL (string.Format ("{0},{1}", tileCenterLocation.Latitude, tileCenterLocation.Longitude));
queryString += "&zoom=" + zoomLevel.ToString ();
queryString += "&size=" + WWW.UnEscapeURL (string.Format ("{0}x{0}", size));
queryString += "&scale=" + (doubleResolution ? "2" : "1");
queryString += "&maptype=" + mapType.ToString ().ToLower ();
queryString += "&format=" + "png";
// 地図のスタイルを追加する
queryString += "&style=element:geometry|invert_lightness:true|weight:3.1|hue:0x00ffd5";
queryString += "&style=element:labels|visibility:off";
var usingSensor = false;
#if MOBILE_INPUT
usingSensor = Input.location.isEnabledByUser && Input.location.status == LocationServiceStatus.Running;
#endif
queryString += "&sensor=" + (usingSensor ? "true" : "false");
//set map bounds rect
TopLeftCorner.x = GoogleMapUtils.adjustLonByPixels(tileCenterLocation.Longitude, -size, zoomLevel);
TopLeftCorner.y = GoogleMapUtils.adjustLatByPixels(tileCenterLocation.Latitude, size, zoomLevel);
BottomRightCorner.x = GoogleMapUtils.adjustLonByPixels(tileCenterLocation.Longitude, size, zoomLevel);
BottomRightCorner.y = GoogleMapUtils.adjustLatByPixels(tileCenterLocation.Latitude, -size, zoomLevel);
print(string.Format("Tile {0}x{1} requested with {2}", TileOffset.x, TileOffset.y, queryString));
// 最後に、画像をリクエストする
var req = UnityWebRequestTexture.GetTexture(GOOGLE_MAPS_URL + "?" + queryString); //obsolute
// サービスが応答するまで待つ
yield return req.Send();
// 最初に古いテクスチャーを破棄する
Destroy(GetComponent<Renderer>().material.mainTexture);
// エラーをチェックする
if (req.error != null) {
print (string.Format ("Error loading tile {0}x{1}: exception={2}",
TileOffset.x, TileOffset.y, req.error));
} else {
// レンダリング画像がエラーがなければ戻ってきた画像をタイルテクスチャーとして設定する
GetComponent<Renderer> ().material.mainTexture = ((DownloadHandlerTexture)req.downloadHandler).texture;
print (string.Format ("Tile {0}x{1} textured", TileOffset.x, TileOffset.y));
}
}
}
}
追記
<追記1>
「UnityによるARゲーム開発 」(O’Reillyの書籍 日本語訳バージョン)
上記のサイトを拝見したのですが、課金しないとGoogleMapのAPIは使えないのでしょうか...?