Search Unity

Call a function from a web browser through LAN

Discussion in 'Scripting' started by kaihzu_unity, Mar 7, 2018.

  1. kaihzu_unity

    kaihzu_unity

    Joined:
    Mar 7, 2018
    Posts:
    3
    I have a windows build running on a computer inside a room and want to use another computer on the LAN to call functions with.

    I would like to be able to go to a web browser and type in "http://192.168.x.x/dofunction" where x.x is the unity computer's IP address and then have my computer running the windows build to do its function (which would simply be to reset the game by switching scenes)

    I've looked through the documentation for a few days but I'm not sure I'm looking in the right place for this specific problem.
     
  2. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    To access the unity build directly from a browser like that would require building a web server into your game's build. That's a non-trivial project on its own.

    Far easier would be to set up whatever web server you prefer on that machine, and either have your web server write to a database using something like PHP/MySQL, or write to a file in PHP or your favorite server side web scripting language, and have your game's build talk to the same server or monitor the same local file.
     
  3. kaihzu_unity

    kaihzu_unity

    Joined:
    Mar 7, 2018
    Posts:
    3
    I hate to bother you about it, but could you elaborate more? I've never used php or even written networking code but this is the last hurdle I have before this project can be finalized.
     
  4. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    Well if you used a separate web server to handle your browser requests, you'd write one or more scripts on the web server that handles these requests from your browser. PHP is an often used language for this type of thing because it is freely available, has syntax that at least is not completely alien if you have experience with any C like language like C#, and can be interspersed with html code instead of them having to be different files on the web server.

    For example if you wanted to switch scenes, you might call in your browser "http://192.168.x.x/change_scene.php?newscene=scene2"

    Then in change_scene.php on the web server you get the newscene variable
    Code (csharp):
    1.  
    2. <?php
    3. $newscene = $_GET['newscene'];
    4. ?>
    5.  
    and in that php code you take that and send it to your game. Like I mentioned that could be storing it in a database or writing it to a file on the local disk. If you wrote to a file on the local disk you could just have your game server periodically check that file for any changes. You'd come up with some system of commands to the game server that both the game server and the web server understand, and use that to talk to each other.
     
  5. kaihzu_unity

    kaihzu_unity

    Joined:
    Mar 7, 2018
    Posts:
    3
    Would this be a good starting point? Its web server code for Unity.
     
  6. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    Maybe it could be a good starting point, but there doesn't appear to be any code examples and it looks like it is just a very simplified webserver that hands out static web pages instead of what you want which is a way to send commands to the game. It looks like the developer stopped supporting it a little over a year ago as well.
     
  7. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Another option could be to have a small program you write that sends a msg through a pipe or socket to your unity game.
     
  8. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,537
    If you want a super simple HttpListener, well .net has a HttpListener class built in.

    Remember... Unity just uses mono as it's scripting engine. This means that you have access to the mono framework, which is the open source version of .net. So really, anything you can do in .net, you can do in Unity (with the limitation of the version of mono that unity uses). You should try googling for things in the context of mono/.net (independent of unity) if you want to try and find stuff.

    So... HttpListener:
    https://msdn.microsoft.com/en-us/library/system.net.httplistener(v=vs.110).aspx

    It contains a super simple example of setting one up.

    Here I set one up that listens for http requests of localhost on port 80. I respond based off the LocalPath passed in the url (what comes after the site name):
    Code (csharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. using System.Net;
    7.  
    8. public class SimpleHttpServer : MonoBehaviour
    9. {
    10.  
    11.     private HttpListener _listener;
    12.  
    13.     void Start ()
    14.     {
    15.         if (!HttpListener.IsSupported)
    16.         {
    17.             Debug.LogWarning("HttpListener is not supported.");
    18.             return;
    19.         }
    20.  
    21.         _listener = new HttpListener();
    22.         _listener.Prefixes.Add("http://*:80/");
    23.         _listener.Start();
    24.  
    25.         this.WaitForNextRequest();
    26.     }
    27.  
    28.     private void OnDestroy()
    29.     {
    30.         if(_listener != null)
    31.         {
    32.             _listener.Stop();
    33.             _listener = null;
    34.         }
    35.     }
    36.  
    37.     private void WaitForNextRequest()
    38.     {
    39.         if (_listener == null) return;
    40.  
    41.         System.Threading.ThreadPool.QueueUserWorkItem((o) =>
    42.         {
    43.             var context = _listener.GetContext();
    44.             this.WaitForNextRequest();
    45.  
    46.             switch(context.Request.Url.LocalPath)
    47.             {
    48.                 case "/foo":
    49.                     Debug.Log("CALLED MESSAGE FOO");
    50.                     this.Respond(context.Response, "Successfully called foo");
    51.                     break;
    52.                 case "/bar":
    53.                     Debug.Log("CALLED MESSAGE BAR");
    54.                     this.Respond(context.Response, "Successfully called bar");
    55.                     break;
    56.                 default:
    57.                     Debug.Log("UNKNOWN MESSAGE: " + context.Request.Url.LocalPath);
    58.                     this.Respond(context.Response, "Unknown message: " + context.Request.Url.LocalPath);
    59.                     break;
    60.             }
    61.      
    62.         });
    63.     }
    64.  
    65.     private void Respond(HttpListenerResponse response, string msg)
    66.     {
    67.         //RESPOND TO THE BROWSER:
    68.         string responseString = "<HTML><BODY>" + msg + "</BODY></HTML>";
    69.         byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
    70.         // Get a response stream and write the response to it.
    71.         response.ContentLength64 = buffer.Length;
    72.         using (var output = response.OutputStream)
    73.         {
    74.             output.Write(buffer, 0, buffer.Length);
    75.         }
    76.     }
    77.  
    78. }
    79.  
    Keep in mind, 'GetContext' is a blocking call. And you really only ever want to be monitoring for a request one at a time. This is why every time I get a context I spin up a new thread that waits for the next context, and so on and so forth.

    You'll also need to deal with getting back onto the main thread if you want to access the Unity API. There are several methods of doing this.

    NOTE THOUGH

    This is a super naive/simple implementation of it. It does not validate the requests, and it handles all requests it receives. This means any and all http requests sent to the machine on port 80 will be handled (this can be an issue for multiple reasons).

    You probably should be upgrading this heavily to validate and handle specific headers/mime types/etc. The HttpListenerRequest contains all headers and everything in it so you can do this. Maybe change the prefixes it handles to be more specific so it ain't handling any and all requests.

    [edit]
    NOTE 2

    Your firewall may block remote requests. Make sure you have your firewall on your machine configured correctly.
     
    Last edited: Mar 8, 2018