Location-based gaming is one area of innovation that has gone largely underutilized by the game development community. Let's suppose that we want to start a whole line of games that utilize the actual players location information to change some of the state in our game. For our purposes we will utilize the players location to determine the weather in their area, as well as the time of day so that we can have the player's game world match the world outside.
Let's walk through the steps that would be necessary for this application's functionality:
As this is something that we only need to do when our application first starts, we can perform all of our operations in the Start()
method of our script. All we need to do is:
iPhoneSettings.StartLocationServiceUpdates()
method and Unity will start its interaction with the platform's CoreLocation services.//Use this for initialization void Start () { iPhoneSettings.StartLocationServiceUpdates(); }
To expose a variable to the Unity editor we need to define it in such a way that it is public in our script. This will allow Unity to expose this variable to the rest of the IDE and we will be able to change the value for this variable without having to edit the script again.
using UnityEngine; using System.Collections; public class LocationBasedGaming : MonoBehaviour { public int retries = 20; // Use this for initialization void Start () { iPhoneSettings.StartLocationServiceUpdates(); } // Update is called once per frame void Update () { } }
This will be represented inside of the Unity Editor in the Inspector when you examine the Game Object that this script is attached to. In our example, if you take a look at the Camera object that we've attached this script to you will see the variable and whatever value it currently has. If you change this value, you will be overriding the default value that the script is providing:
Unity provides an overridden method WaitForSeconds
, which takes an amount of time to wait. In order for us to invoke this method, we must:
void
. Thus, we cannot simply expose this in our Start()
function. However, this is easily remedied by providing a secondary function which can handle this.IEnumerator EnterWaitState( float time ) { yield return new WaitForSeconds( time ); }
Start()
function, wait for a certain amount of time and then check to see if the location services are available.// Use this for initialization void Start () { iPhoneSettings.StartLocationServiceUpdates(); while( iPhoneSettings.locationServiceStatus == LocationServiceStatus.Initializing && retries > 0 ) { EnterWaitState( 2.0f ); retries --; } }
This code will check the status of the device, wait for 2 seconds and then check again. Each time it will reduce the number of retries remaining. When this reaches zero we can safely assume that either the user has chosen to not allow location services or there is something wrong which is preventing the location services from working (like Airplane Mode).
Start()
method from one that returns void
to one that returns IEnumerator
.IEnumerator Start () { iPhoneSettings.StartLocationServiceUpdates(); while( iPhoneSettings.locationServiceStatus == LocationServiceStatus.Initializing && retries > 0 ) { yield return new WaitForSeconds ( 2.0f ); retries --; } }
Either mechanism is acceptable depending on what you intend to do and the style of development you're accustomed to. Both are included here for completeness.
Now that we know that the device is giving us location data, we can simply look in the iPhoneInput.lastLocation
variable and extract the longitude and latitude. From these we can then integrate with a web service, which can tell us what the weather is where the device is located.
if (iPhoneSettings.locationServiceStatus == LocationServiceStatus.Failed) { Debug.Log("Unable to activate the location services. Device reports failure"); } else { // success path for location services - get information // from Google float latitude = iPhoneInput.lastLocation.latitude; float longitude = iPhoneInput.lastLocation.longitude; }
Now that we know the latitude and longitude for the device, we can get the weather at this location so that we can use it in our game. To accomplish this we will use Google's Weather API and parse the XML we receive.
public class GoogleWeather : MonoBehaviour { String city; String conditions; String tempC; String tempF; String humidity; String wind; // Use this for initialization void Start () { } // Update is called once per frame void Update () { } void forLocation( float lat, float lon ) { String postLat = "" + lat * 1000000; String postLon = "" + lon * 1000000; XmlDocument responseXML = new XmlDocument(); responseXML.Load("http://www.google.com/ig/api?weather=,,," + postLat + "," + postLon ); city = responseXML.SelectSingleNode("/xml_api_reply/weather/forecast_information/city").Attributes["data"].InnerText; conditions = responseXML.SelectSingleNode("/xml_api_reply/weather/current_conditions/condition").Attributes["data"].InnerText; tempC = responseXML.SelectSingleNode("/xml_api_reply/weather/current_conditions/temp_c").Attributes["data"].InnerText; tempF = responseXML.SelectSingleNode("/xml_api_reply/weather/current_conditions/temp_f").Attributes["data"].InnerText; humidity = responseXML.SelectSingleNode("/xml_api_reply/weather/current_conditions/humidity").Attributes["data"].InnerText; wind = responseXML.SelectSingleNode("/xml_api_reply/weather/current_conditions/wind_condition").Attributes["data"].InnerText; } }
The code first starts by defining variables that will store the results of our weather query: city, conditions, tempC, tempF, humidity, and wind.
The forLocation()
method takes latitude and longitude and converts them into the format that Google expects (the API doesn't support the decimal version of lat/lon – just an integer representation).
Next the API requests the XmlDocument from the Google servers by compositing the URL that will be passed to Google and telling the C# to load this data. Once it has returned we simply select the current_conditions
for our location and we now have the weather for where our player is currently playing the game.
We activated the location services on our device and polled the device to determine where our device was located. We entered a wait loop to give the location services a chance to start and provide the user an opportunity to interact with the OS and give our application permission to use the gathered data. But, for our inability to launch this application remotely we just performed the same job as FindMyiPhone
. Next we interfaced with a web service, which provided us the location that this lat/lon represents. With this information we accessed another web service that told us what the weather was in this location. By exposing this data to our environment script in the game we have created a game that uses real location data to function.
One of the great things about modern smart phones is that they enable the device to be operated from a horizontal or vertical orientation. Due to this, it has become expected behavior that games are able to work in whatever orientation the device is in. Fortunately, there are ways to detect the screen orientation and have Unity update our content as a result of the change in device orientation.
18.224.31.41