Archivi categoria: Unity 3D

Unity 3d: il famoso framework multipiattaforma per la creazione di giochi in modo semplice.

Unity 3D: Singleton Design Pattern

Affrontiamo l’implementazione di un design pattern fondamentale della letteratura informatica: il Singleton.

L’implementazione sarà effettuata in Unity 3D, utilizzando il linguaggio C#.

Cos’è un singleton

Brevemente, il singleton  garantisce che una classe venga istanziata una e una sola volta in tutta l’esecuzione di un programma, accessibile da ogni punto del programma.

Implementazione

Per l’implementazione in C# si sfruttano i qualificatori static e public di una classe.

public class MySingleton : MonoBehaviour {
    // private fields
    private static MySingleton instance = null; // attenzione, i minuscola iniziale
 
    public bool MyBoolValue = true;
    //--------------------------------------------------
    // constructor field: Instance
    //--------------------------------------------------
    // Creates an instance of GamScreen if one does not exists
    //--------------------------------------------------
    // con la I maiuscola, indica il method
    public static MySingleton Instance {
        get {
            if (instance == null) {
                instance = new GameObject("MySingleton").AddComponent<MySingleton>();
            }
            return instance;
        }
    }
 
 
    //--------------------------------------------------
    // Unity method: OnApplicationQuit()
    //--------------------------------------------------
    // Called when you quit the application or stop the editor player
    //--------------------------------------------------
    public void OnApplicationQuit() {
        DestroyInstance();
    }
 
    //--------------------------------------------------
    // DestroyInstance()
    //--------------------------------------------------
    public void DestroyInstance() {
        Debug.Log("Screen Border Instance destroyed");
        instance = null;
    }
    //--------------------------------------------------
    // Initialize()
    //--------------------------------------------------
    public void Initialize() {
        Debug.Log("MySingleton initialized");
    }

    public void DoStuff() {
      Debug.Log("MySingleton stuff");
    }
    
}

Quindi per instanziare la prima volta il singleton sarà sufficente scrivere:

MySingleton.Instance.DoStuff();

e dopo quella riga di codice la classe sarà instanziata e accessibile da qualsiasi parte del programma.

Unity3d: Salvataggio delle impostazioni in modo persistente con PlayerPrefs

In questo rapido tutorial vediamo come rendere persistenti le impostazioni di gioco in Unity 3d.
Per “rendere persistenti” si intende che le impostazioni verranno mantenute anche se si chiude e si riapre l’applicazione.

Allo scopo, il framework Unity ci fornisce la classe PlayerPrefs (namespace UnityEngine).
Un’importante limitazione da segnalare per questo sistema di memorizzazione persistente è che abbiamo a disposizione solo 1 megabyte.

Il sistema funziona tramite la logica della memorizzazione di chiave-valore.

ESEMPIO (C#)

Salviamo il punteggio del gioco:
PlayerPrefs.SetInt(“Score”1000); // salvataggio di 1000 nella chiave “Score”

Successivamente, per andare a rileggere il valore salvato:
int score = PlayerPrefs.GetInt(“Score”);

Unity 3D – Come sparare con un fucile, visualizzando i fori del proiettile

In questo articolo vedremo come aggiungere una texture che simulerà un foro su una superfice di un oggetto che è stato “colpito da un proiettile”.

( Pulsante sinistro mouse = SPARA   Frecce= spostati )

Procuriamoci una scena di base in cui ci sono i nostri oggetti da colpire.
Nel mio caso ho creato a partire da una scena vuota un piano (plane)  che fa da pavimento ( aggiungendo una texture per l’erba ) e quattro cubi (cube), a cui ho aggiunto una texture di legno.
Ho importato dagli asset standard il First Person Controller.
Ho impilato i cubi.
Ottenendo la scena nell’immagine:
tut_bulletholes_01

A questo punto per simulare uno sparo di un fucile aggiungiamo uno script all’oggetto First Person Controller, utilizzando un RayCast per identificare l’oggetto colpito.

void Update () {
        // If the Button “Fire1” is pressed down it will return true and so we enter the if condition
        if(Input.GetButton("Fire1") && Time.time > nextFire)
        {
      // è stato premuto il bottone "Fire1", che per default è associato al bottone sinistro del mouse.
  
            nextFire = Time.time + fireRate; // piccolo filtro di tempo per evitare che ad ogni frame venga sparato un raggio

            // Vector2 è usato per avere le coordinate del puntatore sullo schermo al momento della pressione del muose sinistro.
            // Il centro dello schermo è calcolato dividendo per due le dimensioni dello schermo
            Vector2 screenCenterPoint = new Vector2(Screen.width/2, Screen.height/2);
            
            // Camera.main è la camera di default della scena ( deve avere il Tag MainCamera )
            ray = Camera.main.ScreenPointToRay(Input.mousePosition);

            if(Physics.Raycast(ray, out hit, Camera.main.farClipPlane)) // spara il raggio dalla camera
            {
                // E' stata rilevata la collisione del raggio con un oggetto dotato di Collider
                // qui possiamo gestire la collisione
                Debug.DrawLine (transform.position, hit.point, Color.red);
                Debug.Log("hit the object:" + hit.transform.name);
            }
        }
    }

Premendo play vedremo il raggio ROSSO uscire dalla camera e colpire un cubo.

Ora, procuriamoci una texture che faccia da “foro”:
bullethole

Io l’ho creata velocemente con un programma di grafica qualsiasi.
Aggiungiamo un quad alla scena e trasciniamoci sopra la texture del foro di proiettile.tut_bulletholes_02tut_bulletholes_03

Costruiamo un prefab con questo quad, chiamandolo ad esmpio: BulletHole.

Quindi aggiungiamo allo script che gestisce il raycast una variabile public per assegnargli il prefab appena creato.

public GameObject bulletHolePrefab; // bullet hole prefab to instantiate

e aggiungiamo il codice di gestione:

if(Physics.Raycast(ray, out hit, Camera.main.farClipPlane)) { // spara il raggio dalla camera

  // E' stata rilevata la collisione del raggio con un oggetto dotato di Collider
  // qui possiamo gestire la collisione
  Debug.DrawLine (transform.position, hit.point, Color.red);
  Debug.Log("hit the object:" + hit.transform.name);
  
  Vector3 bulletHolePosition = hit.point + hit.normal * 0.01f;  // posizione di collisione del raycast sull'oggetto colpito
  // notare la normale all'oggetto è l'offset di 0.01f per non avere intersecazioni di textures.

  // ci serve una variabile per salvarci la rotazione del prefab
  // La rotazione sarà data dall'unione del vettore forward e la normale al punto di impartto
  Quaternion bulletHoleRotation = Quaternion.FromToRotation(-Vector3.forward, hit.normal);

  // instanziamo il prefab
  GameObject hole = (GameObject)GameObject.Instantiate(bulletHolePrefab, bulletHolePosition, bulletHoleRotation);
  hole.transform.parent = hit.transform; // assegniamo anche il parent del foro per fare in modo che l'oggetto colpito, 
                                         // se si sposta, ha sempre il foro posizionato correttamente.

  // chicca: se ho un rigdbody sull'aggotto applico una forza per simulare l'impatto del proiettile
  if ( hit.rigidbody != null ) {
    hit.rigidbody.AddForceAtPosition (150 * ray.direction, hit.point);

    // riproduzione dell'audio attaccato all'aggetto.
    if ( audio != null ) {
      audio.Play();
    }

  }

}

Scarica da qui il progetto demo Unity3D

OLYMPUS DIGITAL CAMERA

Unity 3D – Come riprodurre un audio quando due oggetti si scontrano

 

E’ possibile generare un effetto sonoro quando due oggetti collidono fra loro in modo semplice.

esempio live

in questo esempio viene riprodotto un rumore quando la palla si scontra con un altro oggetto ( pavimento )

La classe MonoBehaviour, classe padre di ogni oggetto nella scena di unity3d, offre un intertessante metodo ( method ):

OnCollisionEnter(Collision)

OnCollisionEnter è chiamato dal framework quando l’oggetto ( con un collider/rigidbody ) ha cominciato a toccare un altro oggetto dotato di collider/rigidbody.

Il parametro passato Collision contiene informazioni utili sull’altro oggetto, il punto di collisione e altre utili informazioni come ad esempio la velocità di impatto.

Quello che interessa a noi è appunto la velocità di impatto, che la sfrutteremo nel seguente modo:

void OnCollisionEnter(Collision collision) {    
    if ( (collision.relativeVelocity.magnitude > 2) && (audio != null) )
       audio.Play();
}

Quindi se la velocità di impatto supererà il valore 2 verrà riprodotto l’audio attached all’oggetto.
Quindi è necessario che l’oggetto abbia uno script Audio associato.

Osservazioni:

  • Entrambi gli oggetti devono avere un component rigidbody/collider.
  • Se l’audio riprodotto vi sembra basso controllate le proprietà del file audio, molto probabilmente lo volete con proprietà 2D.
  • Regolate sempre il valore di confronto con il collision.relativeVelocity.magnitude ( nell’esempio è > 2 ) per evitare suoni non voluti.