This is an old revision of the document!
Realizarea unui game launcher
Gasiti pe MS Teams inregistrat
Un executabil Unity poate fi rulat si cu parametri de linie de comanda. Exista doua tipuri de parametri:
La lansarea aplicațiilor Unity Player, delimitatorul pentru o valoare a argumentului liniei de comandă este un singur spațiu. De exemplu, pentru a seta modul fereastră la fără margini, utilizați -window-mode borderless.
Exemple:
--custom-param 123 -batchMode -executeMethod Build.CommandLineMake +buildLocation Build/Output/WebPlayer +buildTarget WebPlayer
unity.exe --user-token AAA -logFile C:/...
Pentru preluarea acestor parametri, putem folosi clasa Environment care face parte din cadrul .NET.
System.Environment.CommandLine System.Environment.CommandLineArgs
//read from cmdline parameters string[] args = System.Environment.GetCommandLineArgs (); for (int i = 0; i < args.Length; i++) { Debug.Log ("ARG " + i + ": " + args [i]); }
Unity ofera un sistem de interactiune HTTP denumite UnityWebRequest (in versiuni <2019 WWW). Mai multe detalii despre arhitectura si capabilitati gasiti aici: https://docs.unity3d.com/Manual/web-request.html.
Aceste sistem foloseste corutine intrucat cererile HTTP sunt in general asincrone - trebuie sa asteptam un raspuns, care poate dura si cateva secunde, fara a afecta/opri rularea aplicatiei Unity/a jocului.
Mai jos gasiti un exemplu, preluat din pagina de documentatie oficiala https://docs.unity3d.com/2022.3/Documentation/ScriptReference/Networking.UnityWebRequest.Get.html, care prezinta cum se trateaza un request simplu de preluare de informatii (GET).
using UnityEngine; using UnityEngine.Networking; using System.Collections; // UnityWebRequest.Get example // Access a website and use UnityWebRequest.Get to download a page. // Also try to download a non-existing page. Display the error. public class Example : MonoBehaviour { void Start() { // A correct website page. StartCoroutine(GetRequest("https://www.example.com")); // A non-existing page. StartCoroutine(GetRequest("https://error.html")); } IEnumerator GetRequest(string uri) { using (UnityWebRequest webRequest = UnityWebRequest.Get(uri)) { // Request and wait for the desired page. yield return webRequest.SendWebRequest(); string[] pages = uri.Split('/'); int page = pages.Length - 1; switch (webRequest.result) { case UnityWebRequest.Result.ConnectionError: case UnityWebRequest.Result.DataProcessingError: Debug.LogError(pages[page] + ": Error: " + webRequest.error); break; case UnityWebRequest.Result.ProtocolError: Debug.LogError(pages[page] + ": HTTP Error: " + webRequest.error); break; case UnityWebRequest.Result.Success: Debug.Log(pages[page] + ":\nReceived: " + webRequest.downloadHandler.text); break; } } } }
Sistemul permite de asemenea si folosirea de requesturi de tip POST sau PUT si transmiterea de informatii in diferite forme (text, bits, formdata etc). Cateva exemple:
using UnityEngine; using UnityEngine.Networking; using System.Collections; public class MyBehavior : MonoBehaviour { void Start() { StartCoroutine(Upload()); } IEnumerator Upload() { using (UnityWebRequest www = UnityWebRequest.Post("https://www.my-server.com/myapi", "{ \"field1\": 1, \"field2\": 2 }", "application/json")) { yield return www.SendWebRequest(); if (www.result != UnityWebRequest.Result.Success) { Debug.LogError(www.error); } else { Debug.Log("Form upload complete!"); } } } }
PUT request:
byte[] myData = System.Text.Encoding.UTF8.GetBytes("This is some test data"); using (UnityWebRequest www = UnityWebRequest.Put("https://www.my-server.com/upload", myData)) { yield return www.SendWebRequest(); if (www.result != UnityWebRequest.Result.Success) { Debug.Log(www.error); } else { Debug.Log("Upload complete!"); } }
POST request cu FormData:
IEnumerator postRequest(string url) { WWWForm form = new WWWForm(); form.AddField("myField", "myData"); form.AddField("Game Name", "Mario Kart"); UnityWebRequest uwr = UnityWebRequest.Post(url, form); yield return uwr.SendWebRequest(); if (uwr.isNetworkError) { Debug.Log("Error While Sending: " + uwr.error); } else { Debug.Log("Received: " + uwr.downloadHandler.text); } }
POST request cu Json:
IEnumerator postRequest(string url, string json) { var uwr = new UnityWebRequest(url, "POST"); byte[] jsonToSend = new System.Text.UTF8Encoding().GetBytes(json); uwr.uploadHandler = (UploadHandler)new UploadHandlerRaw(jsonToSend); uwr.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer(); uwr.SetRequestHeader("Content-Type", "application/json"); //Send the request then wait here until it returns yield return uwr.SendWebRequest(); if (uwr.isNetworkError) { Debug.Log("Error While Sending: " + uwr.error); } else { Debug.Log("Received: " + uwr.downloadHandler.text); } }
POST request cu Multipart FormData/Multipart (fisier):
IEnumerator postRequest(string url) { List<IMultipartFormSection> formData = new List<IMultipartFormSection>(); formData.Add(new MultipartFormDataSection("field1=foo&field2=bar")); formData.Add(new MultipartFormFileSection("my file data", "myfile.txt")); UnityWebRequest uwr = UnityWebRequest.Post(url, formData); yield return uwr.SendWebRequest(); if (uwr.isNetworkError) { Debug.Log("Error While Sending: " + uwr.error); } else { Debug.Log("Received: " + uwr.downloadHandler.text); } }
DELETE request:
IEnumerator deleteRequest(string url) { UnityWebRequest uwr = UnityWebRequest.Delete(url); yield return uwr.SendWebRequest(); if (uwr.isNetworkError) { Debug.Log("Error While Sending: " + uwr.error); } else { Debug.Log("Deleted"); } }
Mai multe detalii gasiti aici: https://docs.unity3d.com/ScriptReference/Networking.UnityWebRequest.html.
In .NET Framework > 4.5 (ar trebui sa fie default in versiune 2022) putem folosi si direct sistemul de client HTTP din C# https://docs.unity3d.com/2022.3/Documentation/Manual/dotnetProfileSupport.html.
In acest capitol vom prezenta cum puteti crea un game launcher simplu folosind C# si WPF (Windows Presentation Foundation). Cea din urma este o biblioteca ce permite realizarea formularelor / interfetelor grafice intr-o aplicatie Windows printr-o metoda facila (drag-and-drop).
Asigurati-va ca aveti modulul .NET desktop development instalat (verificati din Visual Studio Installer).
Creati un nou proiect “WPF Application”.
Mai jos aveti o imagine ce prezinta panourile de interes din IDE.
Pentru a va obisnui cu lucrul in acest environment, prezentam un exemplu simplu de adaugare componenta UI si legare a unui eveniment
Debug.WriteLine(“Button clicked”);
(sau orice similar), rulati, apasati butonul si vedeti daca va apare in consola mesajul
Un aspect important este numirea acestor elememente de UI. Astfel le veti putea referentia in cod (de ex. veti avea nevoie sa referentiati un text box pentru a extrage proprietatea Text
). Aveti mai jos un exemplu de utilizare.
Pentru partea de backend ne vom folosi de Back4App, ce este o platoforma de tip backend-as-a-service (BaaS), construita pe Parse, ce ofera stocare cloud, servicii de autentificare, baze de date, etc.
In mod special pentru acest laborator ne vom folosi de apeluri catre endpoint-uri via un REST API (request-uri HTTP).
In esenta, datele din formularul nostru le vom trimite prin API call-uri catre un proiect creat in Back4App (ce contine o baza de date cu userii nostrii) pe care-i vom autentifica. Rezultatul, in caz de succes, va fi returnarea unui session token, pe care-l veti putea folosi pentru alte request-uri.
Quickstart:
displayName
. Considerati ca acesta este numele user-ului vostru in joc, diferit de cel de logare (username
)username
, password
si displayName
Pentru a reliza autentificarea sunt necesari o serie de pasi in cod (cei prezentati in continuare sunt specifici pentru C#, dar ideea generala este aceeasi indiferent de limbaj):
Mai jos aveti un exemplu de metoda de login in C# pentru Back4App.
private async Task<string> LoginUser(string username,string password) { // Initialize the HTTP client & set the required headers. var client = new HttpClient(); client.DefaultRequestHeaders.Add("X-Parse-Application-Id", "YOUR_APP_ID"); client.DefaultRequestHeaders.Add("X-Parse-REST-API-Key", "YOUR_REST_API_KEY"); // Create the request message content. var content = new StringContent($"{{\"username\":\"{username}\",\"password\":\"{password}\"}}", System.Text.Encoding.UTF8, "application/json"); // Send POST request to back4app's login endpoint. var response = await client.PostAsync("https://parseapi.back4app.com/login", content); if (response.IsSuccessStatusCode) { // Get response. string responseBody = await response.Content.ReadAsStringAsync(); // Create JSON. var json = JsonObject.Parse(responseBody); // Return the `sessionToken` (get it from the JSON). return json["sessionToken"].ToString(); } else { Debug.WriteLine($"Login failed : {response.StatusCode}, {response.ReasonPhrase}"); return null; } }
YOUR_APP_ID
si YOUR_REST_API_KEY
. Le gasiti in dashboard-ul proiectului Back4App → App Settings → Security & Keys.