夜風のMixedReality

xRと出会って変わった人生と出会った技術を書き残すためのGeekなHoloRangerの居場所

MapsSDKで任意のタイミングでマップピンを立てる

本日はMapsSDK for Unity応用枠です。

MapsSDK for Unityでは[MapPin]と呼ばれる機能があり、地図上の任意の座標にオブジェクトを配置することができます。

これはMapsSDKの[MapPinExamles]というサンプルで提供されています。

redhologerbera.hatenablog.com

MapPinの仕組みとしては[MapPin]を描画するための[MapPinLayer]コンポーネントと、SCVデータから座標を読み込み配置する[MapPinProvider]コンポーネントで実現しています。

f:id:Holomoto-Sumire:20211014203643p:plain

今回は[MapPinProvider]コンポーネントを改造して任意のタイミングでピンをさせるようにします。

〇任意のタイミングでピンを立てる

[MapPinProvider]コンポーネントではAwake関数でシーン実行時にピン立が実行されます。

  void Awake()
    {
         ...
    }

①Awake関数をパブリックな変数にします。

 public void PinAwake()
    {
     ...
    }

今回はPinAwakeと関数を作りました。

この作業によって自動的に実行されなくなり、外部のクラスから呼び出す必要があります。

次にピンを立てるcsvを任意で変更できるように変数を改造します。

②変数をPublicにします。

public class MapPinProvider : MonoBehaviour
{
    [SerializeField]
    private MapPinLayer _mapPinLayer = null;
    public MapPin _mapPinPrefab = null;


    public TextAsset _mapPinLocationsCsv = null;

...

以上で[MapPinProvider]コンポーネントの改造が終わりました。次に任意のタイミングで呼び出せるように外部クラスを作ります。

今回は前回作成した山手線ツアーと合わせてツアー開始時に山手線の各駅にピンがたつようにします。

redhologerbera.hatenablog.com

③[YamanoteTour]クラスにパブリックな変数として[MapPinProvider]、[MapLayer]を作成します。

    public  MapPinProvider _mapPinProvider;
    public MapLayer _mapLayer;

④山手線ツアーの発火とピンを立てるのを同期させるためTourStart関数に以下の処理を加えます。

  public void TourStart()
    {
        _isActive = true;
        _mapPinProvider._mapPinLocationsCsv = _tourCSV;//追加
        StartCoroutine(PinCreate());//追加
        StartCoroutine(RunTour());
    }

⑤次にピンを生成するコルーチンを作成します。

   private IEnumerator PinCreate()
    {
        yield return new WaitForSeconds(11.0f);
        _mapPinProvider.PinAwake();
    }

ここでは山手線ツアーが始まり十分マップを読み込んだと判断される11秒待ってPinAwakeを呼び出しています。

以上で任意のタイミングでピンを立てることができるようになりました。

f:id:Holomoto-Sumire:20211014211959g:plain

最後に任意のタイミングでピンを削除します。

⑥TourEnd関数に以下の処理を加えます。

    public void TourEnd()
    {
        _isActive = false;
        _mapLayer.enabled = false;//追加
    }

[MapLayer]をディアクティブにすることでマップピンを削除します。

以上で任意のタイミングでマップピンを立て、削除できるようにしました。

スクリプト

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Microsoft.Maps.Unity;
using Microsoft.Geospatial;
using Unity.VisualScripting;

public class YamanoteTour : MonoBehaviour
{
    public  MapPinProvider _mapPinProvider;
    public MapLayer _mapLayer;

    //Defalt Location 37.7,137.9,4.8
    [SerializeField] private TextAsset _tourCSV;
    private static readonly List<MapScene> MapScenes =
        new List<MapScene>
        {
            // TokyoStation -> Yurakucho
            new MapSceneOfLocationAndZoomLevel(new LatLon(35.681382, 139.76608399999998), 16.8f),
            // Yurakucho->shinbashi
            new MapSceneOfLocationAndZoomLevel(new LatLon(35.675069, 139.763328), 17.3f),
            // Shinbashi
            new MapSceneOfLocationAndZoomLevel(new LatLon(35.665498 , 139.75964), 16.0f),
            // Hamamatucho
            new MapSceneOfLocationAndZoomLevel(new LatLon(35.655646, 139.756749), 17.0f),
            // Tamachi
            new MapSceneOfLocationAndZoomLevel(new LatLon(35.645736 , 139.74757499999998), 17.0f),
            // TakanawaGateway
            // Shinagawa
            new MapSceneOfLocationAndZoomLevel(new LatLon(35.630152, 139.74044000000004), 16.15f),
            // Osaki
            new MapSceneOfLocationAndZoomLevel(new LatLon(35.6197,  139.72855300000003), 17.0f),
            // Gotanda
            new MapSceneOfLocationAndZoomLevel(new LatLon(35.626446, 139.72344399999997), 17.5f),
            // Meguro
            new MapSceneOfLocationAndZoomLevel(new LatLon(35.633998 , 139.715828), 17.5f),
            // Ebisu
            new MapSceneOfLocationAndZoomLevel(new LatLon(  35.64669, 139.710106), 17.5f),
            // Shibuya
            new MapSceneOfLocationAndZoomLevel(new LatLon(35.658517, 139.70133399999997), 15f),
            // Harajuku
            new MapSceneOfLocationAndZoomLevel(new LatLon(35.670168 ,139.70268699999997),17f),
            // Yoyogi
            new MapSceneOfLocationAndZoomLevel(new LatLon(35.683061,139.702042),17f),
            // Shinjuku
            new MapSceneOfLocationAndZoomLevel(new LatLon(35.690921,139.70025799999996),17f),
            // ShinOkubo
            new MapSceneOfLocationAndZoomLevel(new LatLon(35.701306,139.70004399999993),17f),
            // Takadanobaba
            new MapSceneOfLocationAndZoomLevel(new LatLon(35.712285,    139.70378200000005),17f),
            // Mejiro
            new MapSceneOfLocationAndZoomLevel(new LatLon(35.721204 ,139.706587),17f),
            // Ikebukuro
            new MapSceneOfLocationAndZoomLevel(new LatLon(35.728926 ,139.71038),17f),
            // Otuka
            new MapSceneOfLocationAndZoomLevel(new LatLon(35.731401 ,139.72866199999999),17f),
            // Sugamo
            new MapSceneOfLocationAndZoomLevel(new LatLon(35.733492,139.73934499999996),17f),
            // Komagome
            new MapSceneOfLocationAndZoomLevel(new LatLon(35.736489,139.74687500000005),17f),
            // Tabata
            new MapSceneOfLocationAndZoomLevel(new LatLon(35.738062 ,139.76085999999998),17f),
            // Nishi Nippori
            new MapSceneOfLocationAndZoomLevel(new LatLon(35.732135,139.76678700000002),17f),
            // Nippori
            new MapSceneOfLocationAndZoomLevel(new LatLon(35.727772 ,139.770987),17f),
            // Uguisudani
            new MapSceneOfLocationAndZoomLevel(new LatLon(35.720495 ,139.77883700000007),17f),
            // Ueno
            new MapSceneOfLocationAndZoomLevel(new LatLon(35.713768,139.77725399999997),17f),
            // Okachimachi
            new MapSceneOfLocationAndZoomLevel(new LatLon(35.707438 ,139.774632),17f),
            // Akihabara
            new MapSceneOfLocationAndZoomLevel(new LatLon(35.698683 ,139.77421900000002),17f),
            // Kanda
            new MapSceneOfLocationAndZoomLevel(new LatLon(35.69169  ,139.77088300000003),17f)
        };
 
    [SerializeField]
    private MapRenderer _map = null;

    private bool _isActive;
    private void Awake()
    {
        Debug.Assert(_map != null);
    }

    public void TourStart()
    {
        _isActive = true;
        _mapPinProvider._mapPinLocationsCsv = _tourCSV;
        StartCoroutine(PinCreate());
        StartCoroutine(RunTour());
    }

    public void TourEnd()
    {
        _isActive = false;
        _mapLayer.enabled = false;
    }

    private IEnumerator PinCreate()
    {
        yield return new WaitForSeconds(11.0f);
        _mapPinProvider.PinAwake();
    }
    private IEnumerator RunTour()
    {
        yield return new WaitForSeconds(5.0f);

        while (_isActive) // loop the tour as long as we are running.
        {
            foreach (var scene in MapScenes)
            {
                yield return _map.SetMapScene(scene);

                yield return new WaitForSeconds(3.0f);
                Debug.Log(_isActive);
                if (!_isActive)
                {
                    break;
                }
            }
        }
    }
}