Come creare un videogioco? Quali tool e linguaggi utilizzare? Come impostare un nuovo progetto?
Ecco una panoramica e utilizzo dei motori più conosciuti per la creazione di videogiochi

Post in evidenza

Vendere il tuo videogioco, quali piattaforme usare?

Supponiamo abbiate sviluppato di giorno (ma soprattutto di notte) negli ultimi 12 mesi un gioco che vi sta particolarmente a cuore (vuoi per...

Visualizzazioni totali

Unity - condividere uno screenshot di gioco su Android


Molti giochi su piattaforme mobile (Android o iOS) presentano una caratteristica molto interessante dal punto di vista "social": la possibilità non solo di condividere un link del gioco inviandolo ad esempio tramite app di instant messaging, ma anche di "scattare" (per cosi dire) una foto del gameplay ed inviarla come allegato via email o utilizzando le solite app social (twitter, facebook, hangout, ecc...).

In questo post vedremo come implementare questa funzionalità con Unity e Android.

Rispetto ad una versione dedicata a piattaforme desktop, in questo caso dovremo necessariamente utilizzare codice nativo Java che implementerà la chiamata all'intent che avrà come "azione" la condivisione di un messaggio tramite un'app.
Per semplicità possiamo creare un nuovo metodo che si occuperà della creazione di uno screenshot e della sua condivisione: al termine della sua esecuzione il dispositivo chiederà all'utente quale app utilizzare per effettuare tale condivisione. In questa selezione potremo liberamente scegliere l'applicativo da usare, a partire ovviamente dalle app installate (ovviamente non verrà proposta una "condivisione" con Facebook se tale app non è installata fisicamente sul device....)


I passi sono:
  • Salvare lo rappresentazione attuale dello schermo in un oggetto di tipo Texture2D 
  • Salvare la texture su file (utilizzando il filesystem nativo di Android)
  • Creare un nuovo oggetto di tipo Intent con action valorizzata a ACTION_SEND 
  • Esecuzione di questo intent dalla Activity principale del progetto

L'unica accortezza è quella di utilizzare una funzione di tipo IEnumerator, dato che dovremo attendere il disegno completo del frame attuale per evitare distorsioni nell'immagine salvata. Tutto questo si riduce ad utilizzare la keyword IEnumerator per la nostra funzione.

La nostra funzione (in c#) è la seguente:

public IEnumerator ShareScreenshot() {
 
   // wait for graphics to render
   yield return new WaitForEndOfFrame();
 
   // prepare texture with Screen and save it
   Texture2D texture = new Texture2D(Screen.width, Screen.height,TextureFormat.RGB24,true);
   texture.ReadPixels(new Rect(0f, 0f, Screen.width, Screen.height),0,0);
   texture.Apply();
 
   // save to persistentDataPath File
   byte[] data = texture.EncodeToPNG();        
   string destination = Path.Combine(Application.persistentDataPath, 
           System.DateTime.Now.ToString("yyyy-MM-dd-HHmmss") + ".png");        
   File.WriteAllBytes(destination, data);
 
   if(!Application.isEditor)
   {
    #if UNITY_ANDROID
    string body = "Body of message to be shared";
    string subject = "Subject of message";

    AndroidJavaClass intentClass = new AndroidJavaClass("android.content.Intent");
    AndroidJavaObject intentObject = new AndroidJavaObject("android.content.Intent");
    intentObject.Call<AndroidJavaObject>("setAction", intentClass.GetStatic<string>("ACTION_SEND"));
    AndroidJavaClass uriClass = new AndroidJavaClass("android.net.Uri");
    AndroidJavaObject uriObject = uriClass.CallStatic<AndroidJavaObject>("parse","file://" + destination);
    intentObject.Call<AndroidJavaObject>("putExtra", intentClass.GetStatic<string>("EXTRA_STREAM"), uriObject);
    intentObject.Call<AndroidJavaObject>("putExtra", intentClass.GetStatic<string>("EXTRA_TEXT"), body );
    intentObject.Call<AndroidJavaObject>("putExtra", intentClass.GetStatic<string>("EXTRA_SUBJECT"), subject);
    intentObject.Call<AndroidJavaObject>("setType", "image/jpeg");
    AndroidJavaClass unity = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
    AndroidJavaObject currentActivity = unity.GetStatic<AndroidJavaObject>("currentActivity");
  
    // run intent from the current Activity
    currentActivity.Call("startActivity", intentObject);
    #endif
   }
}
NOTA: Per poter "scrivere" file sul FileSystem di Android è necessario abilitare tale permesso (normalmente sul file manifest). Nel caso di Unity basta impostare a TRUE il campo "writeaccess" nella finestra "Edit" -> "Project" -> "Player" -> "Android Settings"



Un esempio completo

Vediamo un semplice esempio ma completo che mostra il funzionamento del metodo appena descritto.
Creeremo una nuova scena vuota con Unity e un "empty object" (cioè un oggetto vuoto) al quale applicheremo uno script che si occuperà del disegno dell'interfaccia utente e delle funzionalità minime per poter condividere uno screenshot.

Ricapitolando:
  1. Create una scena nuova in Unity
  2. Create un "Emply Object"
  3. Agganciate all'oggetto il seguente script C#

using UnityEngine;
using System.Collections;
using System.IO;

/**
 *  Share a Screenshot on Android (on Unity 5.3.4)
 * 
 *  Last update 2016-05-04
 * 
 */
public class Screenshot : MonoBehaviour {

    void OnGUI () {
        GUI.Box (new Rect (0,Screen.height - 100,220,70), "Action Menu");
        if(GUI.Button(new Rect(20,Screen.height-60,180,20), "Share Screenshot")) {
            StartCoroutine(ShareScreenshot());
        }
    }

    public IEnumerator ShareScreenshot() {
        
        // wait for graphics to render
        yield return new WaitForEndOfFrame();
        
        // prepare texture with Screen and save it
        Texture2D texture = new Texture2D(Screen.width, Screen.height,TextureFormat.RGB24,true);
        texture.ReadPixels(new Rect(0f, 0f, Screen.width, Screen.height),0,0);
        texture.Apply();
        
        // save to persistentDataPath File
        byte[] data = texture.EncodeToPNG();        
        string destination = Path.Combine(Application.persistentDataPath, 
                                          System.DateTime.Now.ToString("yyyy-MM-dd-HHmmss") + ".png");        
        File.WriteAllBytes(destination, data);
        
        if(!Application.isEditor)
        {
            #if UNITY_ANDROID
            string body = "Body of message to be shared";
            string subject = "Subject of message";

            AndroidJavaClass intentClass = new AndroidJavaClass("android.content.Intent");
            AndroidJavaObject intentObject = new AndroidJavaObject("android.content.Intent");
            intentObject.Call<AndroidJavaObject>("setAction", intentClass.GetStatic<string>("ACTION_SEND"));
            AndroidJavaClass uriClass = new AndroidJavaClass("android.net.Uri");
            AndroidJavaObject uriObject = uriClass.CallStatic<AndroidJavaObject>("parse","file://" + destination);
            intentObject.Call<AndroidJavaObject>("putExtra", intentClass.GetStatic<string>("EXTRA_STREAM"), uriObject);
            intentObject.Call<AndroidJavaObject>("putExtra", intentClass.GetStatic<string>("EXTRA_TEXT"), body );
            intentObject.Call<AndroidJavaObject>("putExtra", intentClass.GetStatic<string>("EXTRA_SUBJECT"), subject);
            intentObject.Call<AndroidJavaObject>("setType", "image/jpeg");
            AndroidJavaClass unity = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
            AndroidJavaObject currentActivity = unity.GetStatic<AndroidJavaObject>("currentActivity");
            
            // run intent from the current Activity
            currentActivity.Call("startActivity", intentObject);
            #endif
        }
    }
}

0 commenti:

Posta un commento