Select to view content in your preferred language

How do you activate a ARCGIS layer with a button?

2947
18
09-26-2023 09:52 AM
AidanAumell
Emerging Contributor

I am having trouble activating an ArcGIS layer with a button game object. 

 

I want the user to click on a button to activate an ArcGIS layer and make it visible. However, I cannot drag the ARCGIS layer on to the button component function. I have tried producing some code for the interaction, but no lucky yet. Does anyone know how to do this? Thanks  

0 Kudos
18 Replies
and1
by Esri Contributor
Esri Contributor

Here is the code to add layers to your map. This line of code is also illustrated in the API sample (SampleAPIMapCreator.cs).

 

map.Layers.Add(LAYER_NAME);

 

For the buttons, I'm sure there are other ways to do it but the easiest way on top of my head is to use UnityEvent.AddListener to extend the onClick click events in Unity.

For examples, first you set up the button as public:

 

public button addButton;

 

Then you would just use the onClick events as below:

 

addButton.onClick.AddListener(delegate {map.Layers.Add(LAYER_NAME);});

 

 This should add the layer to your map.

AidanAumell
Emerging Contributor

Still kinda having a hard time getting that script to work.

0 Kudos
and1
by Esri Contributor
Esri Contributor

So the API sample (SampleAPIMapCreator.cs) shows you examples of adding/removing layers.

All you have to do is to move that "add layer" command inside of the button onClick events as shown below: 

 

addButton.onClick.AddListener(delegate {map.Layers.Add(LAYER_NAME);});

 

This onClick events above should be in the CreateArcGISMap() method from the SampleAPIMapCreator.cs example script.

Result:

AidanAumell
Emerging Contributor

Thank for you your response and help. Unfortunately, I still cannot get the code working, spent many hours working on it with no success. I am getting errors. The name "map" does not exist in the namespace. Also, when I try to rename my map layer in the code it is not recognized here is my script which I am attaching to button game object once it works. Any way you could create a short screen recording of the process?  Thanks! 

 

using Esri.ArcGISMapsSDK.Components;
using Esri.ArcGISMapsSDK.Samples.Components;
using Esri.ArcGISMapsSDK.Utils.GeoCoord;
using Esri.GameEngine.Extent;
using Esri.GameEngine.Geometry;
using Esri.Unity;
using UnityEngine.UI;
using UnityEngine;

public class buttonid : MonoBehaviour
{
public Button addButton; // 

public void CreateArcGISMap()
{
addButton.onClick.AddListener(delegate {maps.Layers.Add(LAYER_NAME); });
}

void Update()
{
}
}

0 Kudos
and1
by Esri Contributor
Esri Contributor

Below is the entire script that I am using, it was slightly modified from the API sample (SampleAPIMapCreator.cs) script.

The API sample scene is located in here for your reference:

and1_0-1696010913017.png


The SampleAPIMapCreator.cs script is located here:

and1_1-1696010971951.png

 

So you would set up an empty GameObject and call it "ExampleScript" , and also create a UI button like what is shown below:

and1_2-1696011077388.png

Select the "ExampleScript" GameObject, click "Add Component" to add the "ExampleScript.cs" to it,  and then enter your API key, and attach that UI button you just created.

and1_3-1696011113517.png

Now select the UI button in the Hierarchy window, and navigate to the Inspector window and find On Click (), attach the script to it and select the "DiableButtonOnClick" method.

and1_4-1696011251512.png

Now you should be good to go.

Noticed that line 150 is where I added that onclick listener that I mentioned from previous posts. Hope this helps and let me know if you still have trouble.

 

// Copyright 2023 Esri.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
// You may obtain a copy of the License at: http://www.apache.org/licenses/LICENSE-2.0
//

// ArcGISMapsSDK

using Esri.ArcGISMapsSDK.Components;
using Esri.ArcGISMapsSDK.Samples.Components;
using Esri.ArcGISMapsSDK.Utils.GeoCoord;
using Esri.GameEngine.Extent;
using Esri.GameEngine.Geometry;
using Esri.Unity;
using UnityEngine.UI;

// Unity

using Unity.Mathematics;
#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;

// System

using System;

// This sample code demonstrates the essential API calls to set up an ArcGISMap
// It covers generation and initialization for the necessary ArcGISMapsSDK game objects and components

// Render-In-Editor Mode
// The ExecuteAlways attribute allows a script to run both in editor and during play mode
// You can disable the run-in-editor mode functions by commenting out this attribute and reloading the scene
// NOTE: Hot reloading changes to an editor script doesn't always work. You'll need to restart the scene if you want your code changes to take effect
// You could write an editor script to reload the scene for you, but that's beyond the scope of this sample script
// See the Unity Hot Reloading documentation to learn more about hot reloading: https://docs.unity3d.com/Manual/script-Serialization.html

[ExecuteAlways]


public class ExampleScript : MonoBehaviour
{
	private ArcGISMapComponent mapComponent;
	private ArcGISCameraComponent cameraComponent;
	public string APIKey = "";
	public Button addBtn;
	private ArcGISPoint geographicCoordinates = new ArcGISPoint(-74.054921, 40.691242, 3000, ArcGISSpatialReference.WGS84());

	// This sample event is used in conjunction with a Sample3DAttributes component
	// It passes a layer to a listener to process its attributes
	// The Sample3DAttributes component is not required, so you are free to remove this event and its invocations in both scripts
	// See ArcGISMapsSDK/Samples/Scripts/3DAttributesSample/Sample3DAttributesComponent.cs for more info
	public delegate void SetLayerAttributesEventHandler(Esri.GameEngine.Layers.ArcGIS3DObjectSceneLayer layer);
	public event SetLayerAttributesEventHandler OnSetLayerAttributes;

	private void Start()
	{
		CreateArcGISMapComponent();
		CreateArcGISCamera();
		CreateArcGISMap();
	}

	// The ArcGISMap component is responsible for setting the origin of the map
	// All geographically located objects need to be a parent of this object

	private void CreateArcGISMapComponent()
	{
		mapComponent = FindObjectOfType<ArcGISMapComponent>();

		if (!mapComponent)
		{
			var mapComponentGameObject = new GameObject("ArcGISMap");

			mapComponent = mapComponentGameObject.AddComponent<ArcGISMapComponent>();
		}

		mapComponent.OriginPosition = geographicCoordinates;
		mapComponent.MapType = Esri.GameEngine.Map.ArcGISMapType.Local;

		// To change the Map Type in editor, you can change the Map Type property of the Map component
		// When you change the Map Type, this event will trigger a call to rebuild the map
		// We only want to subscribe to this event once after the necessary game objects are added to the scene
		mapComponent.MapTypeChanged += new ArcGISMapComponent.MapTypeChangedEventHandler(CreateArcGISMap);
	}

	// ArcGIS Camera and Location components are added to a Camera game object to enable map rendering, player movement and tile loading

	private void CreateArcGISCamera()
	{
		cameraComponent = Camera.main.gameObject.GetComponent<ArcGISCameraComponent>();

		if (!cameraComponent)
		{
			var cameraGameObject = Camera.main.gameObject;

			// The Camera game object needs to be a child of the Map View game object in order for it to be correctly placed in the world
			cameraGameObject.transform.SetParent(mapComponent.transform, false);

			// We need to add an ArcGISCamera component
			cameraComponent = cameraGameObject.AddComponent<ArcGISCameraComponent>();

			// The Camera Controller component provides player movement to the Camera game object
			cameraGameObject.AddComponent<ArcGISCameraControllerComponent>();

			// The Rebase component adjusts the world origin to accound for 32 bit floating point precision issues as the camera moves around the scene
			cameraGameObject.AddComponent<ArcGISRebaseComponent>();
		}

		var cameraLocationComponent = cameraComponent.GetComponent<ArcGISLocationComponent>();

		if (!cameraLocationComponent)
		{
			// We need to add an ArcGISLocation component...
			cameraLocationComponent = cameraComponent.gameObject.AddComponent<ArcGISLocationComponent>();

			// ...and update its position and rotation in geographic coordinates
			cameraLocationComponent.Position = geographicCoordinates;
			cameraLocationComponent.Rotation = new ArcGISRotation(65, 68, 0);
		}
	}

	// This function creates the actual ArcGISMap object that will use your data to create a map
	// This is the only function from this script that will get called again when the map type changes

	public void CreateArcGISMap()
	{
		if (APIKey == "")
		{
			Debug.LogError("An API Key must be set on the SampleAPIMapCreator for content to load");
		}

		// Create the Map Document
		// You need to create a new ArcGISMap whenever you change the map type
		var map = new Esri.GameEngine.Map.ArcGISMap(mapComponent.MapType);

		// Set the Basemap
		map.Basemap = new Esri.GameEngine.Map.ArcGISBasemap(Esri.GameEngine.Map.ArcGISBasemapStyle.ArcGISImagery, APIKey);

		// Create the Elevation
		map.Elevation = new Esri.GameEngine.Map.ArcGISMapElevation(new Esri.GameEngine.Elevation.ArcGISImageElevationSource("https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer", "Terrain 3D", ""));

		// Create ArcGIS layers
		var layer_1 = new Esri.GameEngine.Layers.ArcGISImageLayer("https://tiles.arcgis.com/tiles/nGt4QxSblgDfeJn9/arcgis/rest/services/UrbanObservatory_NYC_TransitFrequency/MapServer", "MyLayer_1", 1.0f, true, "");

		// Remove a layer
		//map.Layers.Remove(map.Layers.IndexOf(buildingLayer));

		// Add a layer with a button listener
		addBtn.onClick.AddListener(delegate { map.Layers.Add(layer_1); });

		// You can update an ArcGISLayer's name, opacity, and visibility without needing to rebuild the map
		// Update properties
		layer_1.Opacity = 0.9f;

		// If the map type is local, we will create a circle extent and attach it to the map's clipping area
		if (map.MapType == Esri.GameEngine.Map.ArcGISMapType.Local)
		{
			// Set this to true to enable an extent on the map component
			mapComponent.EnableExtent = true;

			var extentCenter = new Esri.GameEngine.Geometry.ArcGISPoint(-74.054921, 40.691242, 3000, ArcGISSpatialReference.WGS84());
			var extent = new ArcGISExtentCircle(extentCenter, 10000);

			try
			{
				map.ClippingArea = extent;
			}
			catch (Exception e)
			{
				Debug.Log(e.Message);
			}
		}

		// We have completed setup and are ready to assign the ArcGISMap object to the View
		mapComponent.View.Map = map;

#if UNITY_EDITOR
		// The editor camera is moved to the position of the Camera game object when the map type is changed in editor
		if (!Application.isPlaying && SceneView.lastActiveSceneView != null)
		{
			SceneView.lastActiveSceneView.pivot = cameraComponent.transform.position;
			SceneView.lastActiveSceneView.rotation = cameraComponent.transform.rotation;
		}
#endif
	}

	// Disable the button after it's being clicked
	public void DisableButtonOnClick()
	{
		addBtn.interactable = false;
	}
}

 

 

0 Kudos
AidanAumell
Emerging Contributor

Did not work. The first error message I get is shown below. I then delete line 138 of code and it crashes everything. Unfortunately, when I put that code in it causes a stack overflow and crashes Unity. I followed all those steps, and did not succeed. Do I need to be in the sample API scene? I copy and pasted that entire code you had and created a script. 

 

Assets\ExampleScript.cs(138,55): error CS0234: The type or namespace name 'ArcGISBasemapStyle' does not exist in the namespace 'Esri.GameEngine.Map' (are you missing an assembly reference?)

0 Kudos
AidanAumell
Emerging Contributor

Also where would I write down the layer name I want to load in the script or in Unity on inspector panel ?

0 Kudos
and1
by Esri Contributor
Esri Contributor

This is how you define your custom layer. In this case, it's a service URL.

var layer_1 = new Esri.GameEngine.Layers.ArcGISImageLayer("https://tiles.arcgis.com/tiles/nGt4QxSblgDfeJn9/arcgis/rest/services/UrbanObservatory_NYC_TransitFrequency/MapServer", "MyLayer_1", 1.0f, true, "");

 

AidanAumell
Emerging Contributor

How would you define a custom layer from a tile package in that code? 

0 Kudos