Time for action – Changing state according to player location

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:

  1. Start the location services on our device,
  2. Poll the device location information,
  3. Get the weather for this location,

Start the location services on our device

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:

  1. Call the iPhoneSettings.StartLocationServiceUpdates() method and Unity will start its interaction with the platform's CoreLocation services.
    //Use this for initialization
    void Start () {
      iPhoneSettings.StartLocationServiceUpdates();
    }
  2. Now that the location services have started, we need to wait for them to be available. Location services do not activate immediately and if the GPS is being utilized, the internal systems will have to acquire satellites to triangulate the device's location. If we try to acquire information from the device before this has completed, the resulting behavior is not defined.
  3. In order to wait for the location services to start we need to enter a loop where we will check for the status of the location services and then enter a short wait state before checking again. We can do this by specifying an amount of time to wait that we configure in the Unity editor.

Expose variable to Unity editor

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.

  1. In our example we want to expose the maximum amount of time we will wait before we assume that we won't get location services working.
    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:

    Expose variable to Unity editor

    Unity provides an overridden method WaitForSeconds, which takes an amount of time to wait. In order for us to invoke this method, we must:

  2. Perform a yield operation to tell Mono that our code needs to pause while this function runs. Normally one would simply add this as a single line of code, however, C# requires that the method which performs this yield has a different return type other than 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 );
    }
  3. Now we can invoke this method from inside our 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).

  4. A second method that could be accomplished is to change the signature of the 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.

Poll the device location information

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;

}

Get the weather for this location

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.

What just happened?

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.

Screen manipulation

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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.224.31.41