In questa parte del tutorial vediamo come aggiungere uno sfondo al nostro gioco e come ottenere uno scrolling infinito.
Per prima cosa aggiungiamo un Quad alla scena (GameObject > Create Other > Quad
), lo chiamiamo Background e lo posizioniamo su (0, 0, 0)
.
Nella cartella "Materials" creiamo un nuovo materiale che chiamiamo "BackgroundMaterial" e impostiamo come texture di questo materiale il file "Background.png" che troviamo in "Textures\Environment".
Impostiamo lo shader a Mobile/Background, questo shader visualizza esattamente i colori originali dell'immagine e ci permette di non utilizzare alcuna luce sulla scena (possiamo anche farne a meno in un gioco 2D).
Impostiamo il fattore di scala dell'oggetto Background in modo che abbia la stessa aspect ratio dell'immagine (51.2, 12.8, 1)
e impostiamo la Z del vettore posizione a 1 perché appaia dietro al giocatore. Il risultato sarà qualcosa del genere:
Il loop dello sfondo
Ora dobbiamo fare in modo che lo sfondo sembri infinito grazie all'artificio di un loop. Potremmo duplicare il GameObject Background molte volte e allineare tutte le copie una affinanco all'altra, ma forse sarà meglio creare un prefab e utilizzare uno script per disegnarne di più senza utilizzare troppe risorse.
Creiamo una sottocartella "Prefabs" nella cartella "Assets" e poi un nuovo script, che chiamiamo EnvironmentHandler
, nella cartella "Scripts". Associamo poi lo script alla Main Camera, trascinandocelo sopra.
Ora trasciniamo il GameObject Background
dalla finestra Hierarchy alla cartella Prefabs, per ottenere un prefab dello sfondo. Fatto questo possiamo cancellare l'oggetto Background dalla scena.
Apriamo lo script EnvironmentHandler
e scriviamo il codice che segue:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class EnvironmentHandler : MonoBehaviour {
public GameObject BackgroundPrefab;
public GameObject Player;
List<GameObject> spawnedBackgrounds = new List<GameObject>();
int spawnIndex = 2;
// Use this for initialization
void Start () {
for (int i = 0; i < spawnIndex; i++)
{
spawnedBackgrounds.Add(
(GameObject)Instantiate(BackgroundPrefab,
new Vector3(i * 51.2f - 25.6f, 0, 0.01f),
Quaternion.identity)
);
}
}
void Update()
{
bool addNewBackground = false;
foreach (GameObject bgObject in spawnedBackgrounds)
{
if (bgObject != null)
{
if (bgObject.activeInHierarchy)
{
float distanceFromPlayer =
Player.transform.position.x – bgObject.transform.position.x;
if (distanceFromPlayer > 51.2f)
{
Destroy(bgObject);
bgObject.SetActive(false);
addNewBackground = true;
}
}
}
}
if (addNewBackground)
{
spawnedBackgrounds.Add(
(GameObject)Instantiate(BackgroundPrefab,
new Vector3(spawnIndex * 51.2f - 25.6f, 0, 0.01f),
Quaternion.identity));
spawnIndex++;
}
}
}
Ecco un altro pezzo di codice da poter certamente ottimizzare ma di cui è utile capire la logica. Quello che vogliamo fare è creare due istanze dello sfondo sulla scena. Quando avremo oltrepassato una delle istanze la cancelleremo e ne genereremo una nuova avanti a noi.
All'inizio istanziamo due GameObjects che saranno posizionati ad una distanza di -25.5f
dall'origine della scena (dove è anche posizionato il giocatore all'inizio). Questo numero altro non è che la larghezza dello sfondo diviso due. Questo ci garantisce di non avere metà dello schermo vuoto al primo avvio del gioco.
Subito dopo controlliamo la distanza degli sfondi a sinistra del giocatore: se sono arrivati oltre 51.2 (che è la lunghezza dell'intero GameObject) li cancelliamo e richiediamo che ne vengano aggiunti altri a destra (spawnIndex
è utilizzata per ricordarci dove siamo nel "mondo", ovvero quanti sfondi abbiamo generato).
Poiché abbiamo due variabili public per ottenere i riferimenti al giocatore e al prefab dello sfondo, clicchiamo sulla Main Camera (dove è presente EnvironementHandler) e trasciniamo il prefab Background sulla proprietà Background Prefab
e il nostro GameObject Player sulla proprietà Player
.
Ora possiamo effettuare un test e verificare che ci possiamo muovere su e giù e che lo sfondo ci sia.
Rimanere "dentro" l'ambiente
Come noterete subito, ora ci si può muovere anche fuori dagli spazi previsti dal gioco, il ché rende visibile lo sfondo blu della nostra scena. Per evitare questo sgradevole effetto aggiungiamo qualcosa allo script che abbiamo collegato alla camera. Quindi torniamo al nostro script cliccando sulla Main Camera e poi con un doppio click sullo script del componente SmoothFollow2D
.
Poi modifichiamo lo script in questo modo:
#pragma strict
var target : Transform;
var smoothTime = 0.3;
private var thisTransform : Transform;
private var velocity : Vector2;
function Start()
{
thisTransform = transform;
}
function Update()
{
thisTransform.position.x = Mathf.SmoothDamp( thisTransform.position.x,
target.position.x, velocity.x, smoothTime);
thisTransform.position.y = -0.5;
}
In questo modo blocchiamo il movimento della telecamera sull'asse Y. Ora lanciando di nuovo il gioco vedremo la telecamere piazzata a -0.5 sull'asse Y.
Far camminare il giocatore sul marciapiede
Vedremo ora come fare in modo che il giocatore non cammini fuori dal marciapiede. Lo facciamo in modo simile a quanto fatto per la telecamera, ma stavolta agendo sullo script PlayerHandler. Qui daremo dei limiti minimi e massimi per gli spostamenti sull'asse Y.
Possiamo vericare che il giocatore non dovrebbe oltrepassare il range che va da -2.0
e 5.5
. Questi numeri si possono ottenere praticamente lanciando il gioco e muovendo il giocatore, poi cliccando su Player nella finestra hierarchy verificare l'altezza.
using UnityEngine;
using System.Collections;
public class PlayerHandler : MonoBehaviour {
float speed = 4.0f;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
Vector3 movePlayerVector = Vector3.right;
if (Input.GetMouseButton(0))
{
Vector3 touchWorldPoint = Camera.main.ScreenToWorldPoint(
new Vector3(Input.mousePosition.x,
Input.mousePosition.y,
10.0f));
if (touchWorldPoint.y > this.transform.position.y)
{
movePlayerVector.y = 1.0f;
}
else movePlayerVector.y = -1.0f;
}
this.transform.position += movePlayerVector * Time.deltaTime * speed;
if (transform.position.y > -2.0)
{
transform.position = new Vector3(transform.position.x,
-2.0f,
transform.position.z);
}
if (transform.position.y < -5.5)
{
transform.position = new Vector3(transform.position.x,
-5.5f,
transform.position.z);
}
}
}
Ora il nostro robot si muoverà su e giù ma rispettando i vincoli.
L'ultima cosa da fare è allungare un po' il campo visivo del giocatore in avanti, così che possa vedere prima cosa sta per accadere sulla scena.
È piuttosto semplice. Aggiungiamo un nuovo GameObject vuoto nella scena e lo trasciniamo nel nostro GameObject "Player". Lo chiamiamo "CameraTarget" e lo posizioniamo a (6, 0, 0)
.
Quindi non ci resta che dare in pasto questo nuovo target allo script SmoothFollow2d della Main Camera: clicchiamo sulla Main Camera e trasciniamo CameraTarget dalla Hierarchy alla proprietà target
dello script.
Ora lanciamo il gioco ancora e vediamo come aumenta il campo visivo del nostro robottino.