Apr
29
Written by:
Michael Washington
4/29/2012 6:23 PM
Visual Studio LightSwitch in Visual Studio 11 allows you to communicate directly with the LightSwitch business layer (business rules, custom code, security), though OData. This allows you to use LightSwitch as the orchestrating control for any enterprise application or deployment.
In this example, we will demonstrate, using Visual Studio LightSwitch, an application to monitor and send messages to a Unity 3D online game.
Previously, we covered using LightSwitch to support a Android mobile application in: Communicating With LightSwitch Using Android App Inventor. We have also covered implementing user and role based security using LightSwitch and OData in: A Full CRUD LightSwitch JQuery Mobile Application and A Full CRUD DataJs and KnockoutJs LightSwitch Example Using Only An .Html Page.
A Visual Studio LightSwitch Game Controller
This article coverers a proof of concept we recently created for a video game project. We plan to have several players playing online at one time and we need to monitor the game from each players perspective. In addition, we need to be able to transmit messages to individual players and to all players.
It is possible to implement this additional functionality using Unity 3D, but Unity 3D is really is not designed for forms over data operations for such things as user account management, tracking and facilitating in-game purchases, forum and chat logs, player notes, and tracking complaints. We desire to use LightSwitch as the control center and database for everything involved with maintaining an online Unity 3D game.
Using the methods described in this article, one could also control each of the players in the game, but currently we do not have that requirement. Also, we will not cover security in this example (to keep the code simple), however, LightSwitch allows you to implement any security methods you require.
A Walk Thru Of The Functionality
For the end-user playing the game, all they see are messages transmitted to the game, that appear in a box inside the game.
The LightSwitch application allows an administrator to have the Unity 3D game send a screen shot by clicking the Get Screen Shot button.
The screen shot is displayed in the LightSwitch application.
A message can be sent to the Unity 3D game by clicking the Send Message button…
…and entering a message and clicking Save Message.
The message appears in the game.
The Unity 3D Game
Unity 3D is a game development tool that allows you to create professional games.
It allows you to publish your games on multiple platforms.
best of all you can download it for free. You only have to pay if you want to publish your game to anything other than the web based player (or you want the professional features).
Unity 3D has some of the best documentation and tutorials you will find anywhere. For the example Unity 3D project, we will use the game covered in the 2D Gameplay Tutorial.
The only thing we change in the original project, is the addition of a script, ContactLightSwitch (written in C#. Unity 3D allows you to write your scripts in C#, JavaScript, and Boo), that we drop on the Main Camera object to attach to it.
The ContactLightSwitch script starts off with a few public variables and a private variable that will hold the last message:
using UnityEngine;
using System.Collections;
public class ContactLightSwitch : MonoBehaviour
{
public string ScreenShotURL = "http://localhost/LsUnity3DController/UploadImage.aspx";
public string GetCommandURL = "http://localhost/LsUnity3DController/GetCommand.aspx";
private string LastMessage = "";
The public variables show up in the property panel for the script, and allow the game designer to set them explicitly in the Unity 3D inspector panel, or programmatically from another script.
The first method to fire is the Start method, and in that method we use invokeRepeating to call the Loop method every 2 seconds:
void Start()
{
// Call the Loop method every 2 seconds
InvokeRepeating("Loop", 2f, 2f);
}
The Loop method sets up a Coroutine to call LightSwitch and get the latest command (either to send a screen shot or to display a message):
void Loop()
{
// Contact the LightSwitch application
WWW www = new WWW(GetCommandURL);
// Call WaitForRequest method
StartCoroutine(WaitForRequest(www));
}
IEnumerator WaitForRequest(WWW www)
{
// Return control for now but return
// back to this method when the web call
// is complete
yield return www;
// check for errors
if (www.error == null)
{
if(www.text == "SendPicture")
{
// Call the UploadPNG method
StartCoroutine(UploadPNG());
}
else
{
if(www.text != "")
{
// This is just a message so display it
print(www.text);
LastMessage = www.text;
}
}
}
else
{
// Show any errors
print(www.error);
LastMessage = www.error;
}
}
The OnGUI method is used to display the contents of the LastMessage:
void OnGUI()
{
GUI.Box(new Rect (300,20,300,30), LastMessage);
}
If a screen shot needs to be sent to LightSwitch, the following method is used (this code is taken from the Unity 3D site):
IEnumerator UploadPNG()
{
// We should only read the screen after all rendering is complete
yield return new WaitForEndOfFrame();
// Create a texture the size of the screen, RGB24 format
var width = Screen.width;
var height = Screen.height;
var tex = new Texture2D( width, height, TextureFormat.RGB24, false );
// Read screen contents into the texture
tex.ReadPixels( new Rect(0, 0, width, height), 0, 0 );
tex.Apply();
// Encode texture into PNG
var bytes = tex.EncodeToPNG();
Destroy( tex );
// Create a Web Form
var form = new WWWForm();
form.AddField("frameCount", Time.frameCount.ToString());
form.AddBinaryData("fileUpload", bytes, "screenShot.png", "image/png");
// Upload to a cgi script
var www = new WWW(ScreenShotURL, form);
yield return www;
}
The LightSwitch Application
The LightSwitch application uses a single entity (table) called Unity3DCommand. This is the table that commands for the Unity 3D game are entered into, and read from, by the Unity 3D game.
Next, we switch to File View.
We add an OData Service Reference. See: Calling LightSwitch 2011 OData Using Server Side Code for a step-by-step walk-thru on the process.
We add a page to receive the screen shot image from the Unity 3D game using the following code:
(note: The following code allows any file to be uploaded. This is not safe to do in production. You should alter the method to only allow certain file types such as .jpg or .png)
protected void Page_Load(object sender, EventArgs e)
{
HttpFileCollection uploadFiles = Request.Files;
// Build HTML listing the files received.
string summary = "<p>Files Uploaded:</p><ol>";
// Loop over the uploaded files and save to disk.
int i;
for (i = 0; i < uploadFiles.Count; i++)
{
HttpPostedFile postedFile = uploadFiles[i];
// Access the uploaded file's content in-memory:
System.IO.Stream inStream = postedFile.InputStream;
byte[] fileData = new byte[postedFile.ContentLength];
inStream.Read(fileData, 0, postedFile.ContentLength);
// Save the posted file
postedFile.SaveAs(Server.MapPath("~") + "\\" + postedFile.FileName);
// Also, get the file size and filename (as specified in
// the HTML form) for each file:
summary += "<li>" + postedFile.FileName + ": "
+ postedFile.ContentLength.ToString() + " bytes</li>";
}
summary += "</ol>";
// If there are any form variables, get them here:
summary += "<p>Form Variables:</p><ol>";
//Load Form variables into NameValueCollection variable.
NameValueCollection coll = Request.Form;
// Get names of all forms into a string array.
String[] arr1 = coll.AllKeys;
for (i = 0; i < arr1.Length; i++)
{
summary += "<li>" + arr1[i] + "</li>";
}
summary += "</ol>";
divContent.InnerHtml = summary;
}
We use the following code for the page that provides the commands for the Unity 3D game. This page is calling the OData service reference we created:
protected void Page_Load(object sender, EventArgs e)
{
string strResponse = "";
// Create DataContext
ODataServiceReference.ApplicationData objApplicationData =
new ODataServiceReference.ApplicationData(
new Uri(string.Format(@"{0}applicationdata.svc/", BaseSiteUrl)));
// Query OData source
var objUnity3DCommand = (from Unity3DCommands in objApplicationData.Unity3DCommands
where Unity3DCommands.Processed == false
orderby Unity3DCommands.CreatedDate
select Unity3DCommands).FirstOrDefault();
if (objUnity3DCommand != null)
{
// Get the command
strResponse = objUnity3DCommand.Command;
// Update Processed
objUnity3DCommand.Processed = true;
objApplicationData.UpdateObject(objUnity3DCommand);
// Save changes
objApplicationData.SaveChanges(System.Data.Services.Client.SaveChangesOptions.Batch);
}
// Return command as the response
Response.Write(strResponse);
Response.End();
}
(note: see: Calling LightSwitch 2011 OData Using Server Side Code for an explanation of the process to add .aspx pages to the project file)
The main screen allows us to see the screen shot from the Unity 3D game and to issue commands.
When the user requests a screen shot, the following code inserts a record into the Unity3DCommand entity and saves it:
partial void SendPicture_Execute()
{
Unity3DCommand objUnity3DCommand = Unity3DCommands.AddNew();
objUnity3DCommand.Command = "SendPicture";
this.Save();
}
The Unity 3D game reads the command, and sends the screen shot, and the following code is used to display it in a LightSwitch Static Image control:
private void SetImage()
{
// Make a new Bitmap
BitmapImage myImage = new BitmapImage();
// Get the "screenShot.png" sent by Unity3D
string strWebPageURL = String.Format(@"{0}{1}",
GetBaseURL(),
"screenShot.png");
// Create a random string to add to the image to prevent it from being cached
string strRandomText = String.Format(@"?param={0}",
DateTime.Now.Ticks.ToString());
// Set the Image
myImage.UriSource = new Uri(strWebPageURL + strRandomText, UriKind.RelativeOrAbsolute);
UnityImageControl.Source = myImage;
}
For a text message, the following code is used to open a modal window:
partial void SendMessage_Execute()
{
this.OpenModalWindow("EnterMessage");
}
The following code is used to save the message and close the modal window:
partial void SaveMessage_Execute()
{
Unity3DCommand objUnity3DCommand = Unity3DCommands.AddNew();
objUnity3DCommand.Command = this.Message;
this.Save();
this.CloseModalWindow("EnterMessage");
this.Message = "";
}
LightSwitch Without Borders
This solution is actually ‘low tech’. It uses simple communication over normal HTTP protocols. This avoids most network and firewall complications and issues. This is intended to demonstrate that LightSwitch is not just for simple forms over data applications, it can easily integrate into complex applications and deployments.
A few things to note about the example code:
- The account the web server is running under needs create and write permission to save the screenshot.png file that is sent by the Unity 3D game.
- If you publish the Unity 3D game to the web player, you will need to run the app in the same domain as the LightSwitch application or create a cross domain policy file and place it in the root directory of the LightSwitch application.
- The Unity 3D game will go to sleep and not process any commands if it does not have the focus. To properly test this application you need to use two different computers or switch to the Unity 3D game and click on the play area to get it to respond to the commands from LightSwitch.
Also See
Shape Your LightSwitch OData Using WCF RIA Services
A Full CRUD DataJs and KnockoutJs LightSwitch Example Using Only An .Html Page
A Full CRUD LightSwitch JQuery Mobile Application
Calling LightSwitch 2011 OData Using Server Side Code
Communicating With LightSwitch Using Android App Inventor
Using The OData Explorer with LightSwitch OData
Learn How To Make OData Calls In LightSwitch 2011
Accessing Your Visual Studio 2011 LightSwitch Application Using OData
A LightSwitch Netflix OData Mash-up
Download Code
The LightSwitch and Unity 3D source code is available at:
http://lightswitchhelpwebsite.com/Downloads.aspx
5 comment(s) so far...
Thanks so much
By Arshiyan on
5/1/2012 9:05 AM
|
Hi~ I'm Taesoon and Korean Develoments Android & Unity3D
I'm download sample project(LsUnity3DController) and I'm want to debugging this sample project(LsUnity3DController) in My VisualSutudio2012.
But.... At dragging and load LsUnity3DController.sin file, and in to processing the version coverting.... an error occured ;;
error log is ↓
Message Error LsUnity3DController\LsUnity3DController.lsproj: The application which this project type is based on was not found. Please try this link for further information: http://go.microsoft.com/fwlink/?prd=12395&pver=11&sbp=ProjectTypeDeprecated&plcid=0x409&clcid=0x409&ar=MSDN&sar=ProjectCompatibility&o1=ECD6D718-D1CF-4119-97F3-97C25A0DFBF9
Why this error occured;;
Please hemp me... I'm very tired;;; from this problem;;;
p.s : sorry, I'm very be a poor at English.;;;;
By TaeSoon on
7/4/2013 4:18 AM
|
how do change ODataServiceReferenceURL?
I'm try to add the AddReference and my localhostInput in server...
but... ODataServiceReference is already exist... in LsUnity3DController Project;;;
By JAVAHell on
7/4/2013 3:45 AM
|
@TaeSoon - I just downloaded the code and it did the upgrade and it worked fine for me.
By Michael Washington on
7/4/2013 4:26 AM
|
@JAVAHell - Delete the reference and recreate it.
By Michael Washington on
7/4/2013 4:27 AM
|