Come gestite le differenze nelle proporzioni con Unity 2D?


67

Ho ricevuto molte risposte a questa domanda, ma sono tutte generiche e generalmente non molto utili. Nessuno dei tutorial parla delle proporzioni e della gestione dei dispositivi mobili e ci sono molti modi per farlo, tutti sembrano avere problemi e difetti.

Mi piacerebbe davvero sapere quali giochi di successo hanno usato per gestire diverse proporzioni su iOS e Android senza fare miliardi di risorse di dimensioni diverse.

Sto parlando rigorosamente mobile, non desktop, in particolare con Unity e non mi interessa l'interfaccia utente, mi interessa solo l'area di gioco.

I problemi che ho in mente sono quando ci sono cose chiave che devono essere in determinati luoghi e non possono cadere dallo schermo. In questi giorni è inaccettabile l'uso di barre nere in alto o in basso.


3
Questa domanda è molto ampia, poiché il modo giusto dipende da quasi tutto. Che cosa hai provato? Perché non ha funzionato?
Anko,

3
Ho provato ogni genere di cose, ho provato a regolare le dimensioni della fotocamera ortogonale, ho provato a collegare tutti gli sprite per elencarli e ridimensionarli in base alla differenza nelle proporzioni, impostando le dimensioni orto su schermo. Altezza / 2/100, molti altri idee. Alcuni funzionano, ma tutti hanno problemi. So che diversi giochi lo gestiscono in modo diverso, ma non c'è assolutamente nessuna discussione su questo argomento da nessuna parte e non è facile come "lasciare che l'unità lo gestisca" come molti sostengono.
Michael,

1
Quindi, perché non hanno funzionato? Come sarebbe una buona soluzione? (A proposito, puoi anche modificare la domanda per chiarire.)
Anko

7
Alcuni hanno distorto le immagini, altri non si sono allineati correttamente. Molti problemi diversi, ma il 65% dei giochi sviluppati con Unity sono in 2D e li hanno fatti funzionare. Voglio solo sapere cosa usano le persone e non dover reinventare la ruota. Nessuno ne parla e non ci sono guide o documenti su come gestirlo. Eppure non puoi andare lontano in un progetto mobile senza avere un sistema in atto per farlo.
Michael,

1
"I problemi che ho in mente sono quando ci sono cose chiave che devono essere in determinati luoghi e non possono cadere dallo schermo. L'uso di barre nere in alto o in basso è inaccettabile in questi giorni." Garanzia di elementi che non cadono fuori dallo schermo, nessuna distorsione, ma nessuna boxe per lettere / colonne (barre nere e simili). Questi requisiti sono inconciliabili. L'ultimo requisito è probabilmente il meno importante, o può essere nascosto riempiendo la tela oltre ciò che deve essere sullo schermo. La maggior parte dei giochi che ho visto con requisiti così severi avrà pilastri / bordi decorati.
Jibb Smart

Risposte:


36

Quello che vuoi è limitare la vista della telecamera su verticale o orizzontale (a seconda delle tue esigenze), calcolando la camera.orthographicSizeproprietà, in modo da poter costruire la tua scena 2D indipendentemente dalle proporzioni e dalla risoluzione:

// Attach this script on your main ortohgraphic camera:

/* The MIT License (MIT)

Copyright (c) 2014, Marcel Căşvan

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. */

using System;
using System.Collections;
using UnityEngine;

[ExecuteInEditMode]
[RequireComponent (typeof (Camera))]
public class ViewportHandler : MonoBehaviour
{
    #region FIELDS
    public Color wireColor = Color.white;
    public float UnitsSize = 1; // size of your scene in unity units
    public Constraint constraint = Constraint.Portrait;
    public static ViewportHandler Instance;
    public new Camera camera;

    private float _width;
    private float _height;
    //*** bottom screen
    private Vector3 _bl;
    private Vector3 _bc;
    private Vector3 _br;
    //*** middle screen
    private Vector3 _ml;
    private Vector3 _mc;
    private Vector3 _mr;
    //*** top screen
    private Vector3 _tl;
    private Vector3 _tc;
    private Vector3 _tr;
    #endregion

    #region PROPERTIES
    public float Width {
        get {
            return _width;
        }
    }
    public float Height {
        get {
            return _height;
        }
    }

    // helper points:
    public Vector3 BottomLeft {
        get {
            return _bl;
        }
    }
    public Vector3 BottomCenter {
        get {
            return _bc;
        }
    }
    public Vector3 BottomRight {
        get {
            return _br;
        }
    }
    public Vector3 MiddleLeft {
        get {
            return _ml;
        }
    }
    public Vector3 MiddleCenter {
        get {
            return _mc;
        }
    }
    public Vector3 MiddleRight {
        get {
            return _mr;
        }
    }
    public Vector3 TopLeft {
        get {
            return _tl;
        }
    }
    public Vector3 TopCenter {
        get {
            return _tc;
        }
    }
    public Vector3 TopRight {
        get {
            return _tr;
        }
    }
    #endregion

    #region METHODS
    private void Awake()
    {
        camera = GetComponent<Camera>();
        Instance = this;
        ComputeResolution();
    }

    private void ComputeResolution()
    {
        float leftX, rightX, topY, bottomY;

        if(constraint == Constraint.Landscape){
            camera.orthographicSize = 1f / camera.aspect * UnitsSize / 2f;    
        }else{
            camera.orthographicSize = UnitsSize / 2f;
        }

        _height = 2f * camera.orthographicSize;
        _width = _height * camera.aspect;

        float cameraX, cameraY;
        cameraX = camera.transform.position.x;
        cameraY = camera.transform.position.y;

        leftX = cameraX - _width / 2;
        rightX = cameraX + _width / 2;
        topY = cameraY + _height / 2;
        bottomY = cameraY - _height / 2;

        //*** bottom
        _bl = new Vector3(leftX, bottomY, 0);
        _bc = new Vector3(cameraX, bottomY, 0);
        _br = new Vector3(rightX, bottomY, 0);
        //*** middle
        _ml = new Vector3(leftX, cameraY, 0);
        _mc = new Vector3(cameraX, cameraY, 0);
        _mr = new Vector3(rightX, cameraY, 0);
        //*** top
        _tl = new Vector3(leftX, topY, 0);
        _tc = new Vector3(cameraX, topY , 0);
        _tr = new Vector3(rightX, topY, 0);           
    }

    private void Update()
    {
        #if UNITY_EDITOR
        ComputeResolution();
        #endif
    }

    void OnDrawGizmos() {
        Gizmos.color = wireColor;

        Matrix4x4 temp = Gizmos.matrix;
        Gizmos.matrix = Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one);
        if (camera.orthographic) {
            float spread = camera.farClipPlane - camera.nearClipPlane;
            float center = (camera.farClipPlane + camera.nearClipPlane)*0.5f;
            Gizmos.DrawWireCube(new Vector3(0,0,center), new Vector3(camera.orthographicSize*2*camera.aspect, camera.orthographicSize*2, spread));
        } else {
            Gizmos.DrawFrustum(Vector3.zero, camera.fieldOfView, camera.farClipPlane, camera.nearClipPlane, camera.aspect);
        }
        Gizmos.matrix = temp;
    }
    #endregion

    public enum Constraint { Landscape, Portrait }
}

Se hai bisogno di maggiori informazioni su questo, chiedi e ti risponderò. ;) Saluti e saluti.

AGGIORNAMENTO: utilizzare lo script di ancoraggio oggetti di Eliot Lash insieme a questo per posizionare gli oggetti in posizioni chiave sullo schermo, se necessario (rispetto agli angoli / bordi dello schermo). In tal caso, rinominare "CameraFit" in "ViewportHandler".

Anteprima simulando varie schermate delle proporzioni: inserisci qui la descrizione dell'immagine


4
@Eliot Aggiunta licenza MIT sopra. Buona fortuna con i tuoi progetti!
androidu

7
Fantastico, grazie! Un buon turno merita un altro, quindi ecco un componente open source che ho appena scritto per il semplice ancoraggio di GameObjects ai punti di supporto definiti dal tuo script: gist.github.com/fadookie/256947788c364400abe1
Eliot

1
MarcelCăşvan Bellissimo script! Ho aggiunto un enum per selezionare se si desidera definire le dimensioni dell'unità per il ritratto per il paesaggio (altezza / larghezza). Ho dovuto solo aggiungere un paio di righe alla sceneggiatura, e le uso GetComponent<Camera>().orthographicSize = UnitSize / 2f;per le unità potrait / definizione dell'altezza
am_

2
@ MarcelCăşvan grandi cose! Grazie. Vedo che le variabili deviceWidth e deviceHeight di ComputeFunction () non sono utilizzate. Forse considera di eliminarli.
user2313267

1
CameraAnchor sta lanciando l'errore: "CameraFit non è definito in questo contesto" - Nel caso in cui qualcun altro trovi questa risposta in seguito, sembra che "CameraFit" abbia appena rinominato "ViewportHandler" poiché originariamente pubblicato. Se hai appena rinominato la classe da ViewportHandler a CameraFit.
Lenny,

5

In genere non sono necessarie diverse dimensioni di risorse: trame e sprite importati con mappe mip generate automaticamente appariranno piacevoli se renderizzati a qualsiasi dimensione inferiore o uguale alla dimensione in pixel originale dell'immagine.

Il layout della scena è la sfida. Un buon approccio è il seguente (e FYI utilizzo una videocamera 3D guardando contenuto 2D posizionato su z = 0):

  1. Decidi arbitrariamente una dimensione di visualizzazione "logica" minima in pixel o riquadri. Questo non deve corrispondere a nessuna risoluzione del mondo reale, ma dovrebbe riflettere le proporzioni più strette / più brevi che si desidera supportare. Ad esempio, per un gioco paesaggistico non sceglierei 480x320 perché è un formato più ampio rispetto all'iPad. Quindi potrei scegliere 1024x768 - o anche 480x360, che mi dà un sistema di coordinate originale per iPhone con cui lavorare e le stesse proporzioni di ogni iPad (incluso iPad Air 2, ecc.). Si noti inoltre che è possibile lavorare altrettanto facilmente in coordinate di riquadro anziché in pixel, ad esempio 15x11,25.
  2. Programma la tua logica di gioco in modo che tutto ciò che è importante sia (o possa essere) posizionato entro le dimensioni minime del tuo display, ma preparati a riempire di spazio aggiuntivo sui lati con contenuti aggiuntivi, anche se è solo un riempimento decorativo.
  3. Determina quanto devi ridimensionare il contenuto in modo che la larghezza o l'altezza corrispondano al valore minimo e l'altro asse sia maggiore o uguale al minimo necessario. Per fare questa "scala per adattarla", dividi la dimensione dei pixel dello schermo per la dimensione minima del display e prendi il più piccolo dei valori di scala risultanti come scala generale della vista.
  4. Usa la scala di visualizzazione per calcolare la dimensione di visualizzazione effettiva (effettiva) ai fini della logica di gioco.
  5. In realtà ridimensiona il contenuto spostando la videocamera lungo l'asse Z.

In forma di codice:

  // Adjust the camera to show world position 'centeredAt' - (0,0,0) or other - with
  // the display being at least 480 units wide and 360 units high.

  Vector3 minimumDisplaySize = new Vector3( 480, 360, 0 );

  float pixelsWide = camera.pixelWidth;
  float pixelsHigh = camera.pixelHeight;

  // Calculate the per-axis scaling factor necessary to fill the view with
  // the desired minimum size (in arbitrary units).
  float scaleX = pixelsWide / minimumDisplaySize.x;
  float scaleY = pixelsHigh / minimumDisplaySize.y;

  // Select the smaller of the two scale factors to use.
  // The corresponding axis will have the exact size specified and the other 
  // will be *at least* the required size and probably larger.
  float scale = (scaleX < scaleY) ? scaleX : scaleY;

  Vector3 displaySize = new Vector3( pixelsWide/scale, pixelsHigh/scale, 0 );

  // Use some magic code to get the required distance 'z' from the camera to the content to display
  // at the correct size.
  float z = displaySize.y /
            (2 * Mathf.Tan((float)camera.fieldOfView / 2 * Mathf.Deg2Rad));

  // Set the camera back 'z' from the content.  This assumes that the camera
  // is already oriented towards the content.
  camera.transform.position = centeredAt + new Vector3(0,0,-z);

  // The display is showing the region between coordinates 
  // "centeredAt - displaySize/2" and "centeredAt + displaySize/2".

  // After running this code with minimumDisplaySize 480x360, displaySize will
  // have the following values on different devices (and content will be full-screen
  // on all of them):
  //    iPad Air 2 - 480x360
  //    iPhone 1 - 540x360
  //    iPhone 5 - 639x360
  //    Nexus 6 - 640x360

  // As another example, after running this code with minimumDisplaySize 15x11
  // (tile dimensions for a tile-based game), displaySize will end up with the following 
  // actual tile dimensions on different devices (every device will have a display
  // 11 tiles high and 15+ tiles wide):
  //    iPad Air 2 - 14.667x11
  //    iPhone 1 - 16.5x11
  //    iPhone 5 - 19.525x11
  //    Nexus 6 - 19.556x11

2

Se vieni ad usare le barre, in realtà è abbastanza semplice da implementare (sto pubblicando questo anche se l'OP ha dichiarato che la sua opinione è inaccettabile perché ha il vantaggio di non essere così male sui dispositivi mobili ed è una soluzione semplice che non richiede alcun codice)

Camera.orthographicSizeè una variabile all'interno della videocamera orto (utilizzata dalla maggior parte dei giochi 2D) che si adatta alla quantità misurata di unità di gioco verticalmente sullo schermo ( divisa per 2 ) ( sorgente ). Quindi, scegli un rapporto che si adatta alla stragrande maggioranza dei dispositivi (ho scelto 16: 9 poiché la maggior parte degli schermi che ho cercato sono 16: 9, 16:10, 3: 2) e aggiungi una maschera che si sovrappone a un rapporto.

Esempio :

Nel mio gioco (non elencato qui in quanto non si tratta di un annuncio, se lo si desidera nei commenti è possibile) si utilizza la modalità ritratto. Per fare un bel semplice 16: 9 ho realizzato la mia fotocamera Ortho alla dimensione 16. Ciò significa che la fotocamera adatta 32 unità di gioco di altezza (y: da 16 a -16 nel mio caso) alla verticale dello schermo del dispositivo.

Ho quindi inserito maschere nere con un gioco tra -9 e +9. Voilà, lo schermo del gioco sembra esattamente lo stesso su tutti i dispositivi e un po 'più magro su dispositivi un po' più ampi. Non ho avuto alcun feedback negativo sulle maschere. Per fare il panorama basta capovolgere quei valori e poi si dovrebbe rendere la fotocamera di dimensioni 9. Cambiare i valori in modo che corrispondano a qualsiasi cosa tu abbia deciso è la scala dell'unità di gioco.

L'unico posto in cui abbiamo osservato che la barra nera si presenta in modo significativo è sull'iPad a 3: 2. Anche allora, non ho avuto lamentele.


1

Lo sto facendo in un gioco a cui sto attualmente lavorando. Ho un'immagine di sfondo di 1140x720. I bit più importanti (quelli che non dovrebbero mai essere ritagliati) sono contenuti nell'area centrale 960x640. Eseguo questo codice sulla funzione di avvio della mia fotocamera:

    float aspect = (float)Screen.width / (float)Screen.height;

    if (aspect < 1.5f)
        Camera.main.orthographicSize = 3.6f;
    else
        Camera.main.orthographicSize = 3.2f;

    float vertRatio = Screen.height / 320.0f;
    fontSize = (int)(12 * vertRatio);

Definisco anche dimensioni diverse dalla dimensione del carattere per i pulsanti e simili. Funziona bene su tutte le proporzioni che ho testato. È passato un po 'di tempo da quando l'ho impostato, quindi potrei perdere un passo. Fammi sapere se non funziona come previsto e vedrò se ho lasciato qualcosa fuori.


1

La risposta e il codice di @ Marcel sono fantastici e mi hanno aiutato a capire cosa stava succedendo. È la risposta definitiva. Ho pensato che qualcuno potesse anche trovare utile quello che ho finito per fare per il mio caso specifico: dato che volevo qualcosa di veramente molto semplice, uno sprite per essere sempre sullo schermo, ho trovato queste poche righe:

public class CameraFit : MonoBehaviour {

    public SpriteRenderer spriteToFitTo;

    void Start () { // change to Update to test by resizing the Unity editor window
        var bounds = spriteToFitTo.bounds.extents;
        var height = bounds.x / camera.aspect;
        if (height < bounds.y)
            height = bounds.y;
        camera.orthographicSize = height;
    }
}

Ho aggiunto questo alla videocamera e trascinato il mio sprite (è il mio sfondo) sull'unica proprietà dello script. Se non vuoi alcuna barra nera (orizzontale o verticale) puoi mettere uno sfondo più grande dietro questo ...


0

Esistono alcuni modi per affrontare questo problema e non esiste una soluzione perfetta (almeno non ne ho ancora trovata una) e il tipo di soluzione che scegli dipenderà in gran parte dal tipo di gioco che stai sviluppando.

Indipendentemente da ciò che fai, dovresti iniziare scegliendo la risoluzione più bassa possibile che desideri supportare e sviluppare i tuoi sprite a quella risoluzione. Quindi, se sei interessato a sviluppare per iOS, secondo http://www.iosres.com/ la risoluzione del dispositivo iOS più bassa è 480x320.

Da lì, puoi iniziare a ridimensionare gli sprite per soddisfare le risoluzioni più elevate. L'avvertenza a questo è che alla fine inizierai a notare che gli sprite iniziano a sfocare più in alto della scala, nel qual caso puoi passare a un altro set di sprite costruito per le risoluzioni più elevate.

In alternativa, puoi ignorare completamente il ridimensionamento e decidere di visualizzare più dello schermo di gioco per risoluzioni più elevate (credo che sia così che fa Terraria, ad esempio). Tuttavia, per molti giochi, questo non è appropriato; giochi competitivi per esempio.

In questi giorni è inaccettabile l'uso di barre nere in alto o in basso.

È? Molti giochi che vogliono forzare le proporzioni 4: 3 lo fanno. Dato che stai usando Unity, puoi usare lo script AspectRatioEnforcer per aiutarti in questo.


Mi rivolgo ai dispositivi mobili, quindi non posso modificare le proporzioni o la risoluzione. L'uso di risorse a bassa risoluzione non è una soluzione accettabile. Alcuni giochi (in particolare 3D) non sono un problema, basta mostrare più o meno. Ma giochi come Kingdom Rush, tower defence e altri giochi come Alex, vuoi vedere la stessa cosa indipendentemente dal dispositivo. Se le cose non vengono visualizzate nelle posizioni giuste, il gioco non funzionerà correttamente.
Michael,


0

Esistono diversi modi per gestire questo problema, dipende dal tuo gioco e da ciò che funzionerà meglio. Ad esempio, nel nostro gioco Tyrant Unleashed abbiamo semplicemente creato mappe ampie con dettagli non importanti sui lati, in modo da poter tagliare i lati su dispositivi più stretti. Tuttavia, altri giochi potrebbero essere migliori con un approccio in cui si spostano effettivamente i pulsanti o qualcosa per adattarsi meglio allo schermo.

(Anche parte del nostro approccio consiste nel mantenere un'altezza costante su tutti i dispositivi, variando solo la larghezza. Questo certamente ci semplifica la vita, ma ancora una volta questo può o meno essere utile per il tuo gioco specifico. Non importa in il nostro stile artistico se le immagini vengono ridimensionate un po 'su schermi diversi, mentre questo potrebbe essere importante per qualcosa come la pixel art. Fondamentalmente, questo è l'approccio "lascia che sia Unity a gestirlo")


Hai fatto qualche progetto in cui quella non era un'opzione? Quasi tutti i giochi di stile di difesa della torre che ho visto e molti altri stili puoi vedere l'intera vista di gioco sul dispositivo senza scorrere, e questo è coerente tra i dispositivi. Su IOS puoi creare risorse e scambiarle, ma questo diventa impossibile (e in realtà solo una grande PITA comunque) su Android.
Michael,

No non l'ho fatto. tra l'altro ho appena aggiunto qualche dettaglio in più sulle dimensioni dello schermo
jhocking

0

Sto usando il seguente script che aggiunge un targetAspectparametro alla telecamera e lo adatta orthographicSizerispetto al rapporto dello schermo (maggiori dettagli in questo post del blog ):

using UnityEngine;
using System.Collections;

public class AspectRatioScript : MonoBehaviour {

    public float targetAspect;

    void Start () 
    {
        float windowAspect = (float)Screen.width / (float)Screen.height;
        float scaleHeight = windowAspect / targetAspect;
        Camera camera = GetComponent<Camera>();

        if (scaleHeight < 1.0f)
        {  
            camera.orthographicSize = camera.orthographicSize / scaleHeight;
        }
    }
}

0

Il mio metodo è per lo più simile alle soluzioni fornite da altri :) Cercherò di spiegare in dettaglio l'approccio che prendo per rendere il gioco indipendente dalle dimensioni dello schermo.

Orientamento schermo

A seconda dell'orientamento dello schermo (Orizzontale o Verticale), è necessario considerare se la fotocamera verrà ridimensionata con un'altezza fissa o larghezza fissa. Principalmente scelgo la larghezza fissa per i giochi orientati al paesaggio e l'altezza fissa per i giochi orientati al ritratto.

Ridimensionamento della fotocamera

Come discusso, questo può essere un'altezza fissa o una larghezza fissa.

Altezza fissa : l'area verticale del gioco si adatterà sempre all'altezza dello schermo. E man mano che le proporzioni dello schermo cambiano, verrà aggiunto ulteriore spazio a sinistra e a destra dello schermo. Per implementare questo non è necessario codificare nulla, è il comportamento predefinito di Camera Camera.

Larghezza fissa : l'area orizzontale del gioco si adatta sempre alla larghezza dello schermo. E lo spazio aggiuntivo verrà aggiunto in alto e in basso man mano che le proporzioni dello schermo cambiano. Per implementare questo è necessario scrivere un piccolo pezzo di codice. Successivamente, assicurarsi di rimuovere la funzione di aggiornamento del modulo di codice e di metterlo in stato di attivazione.

using UnityEngine;

[ExecuteInEditMode]
public class ScaleWidthCamera : MonoBehaviour {

    public int targetWidth = 640;
    public float pixelsToUnits = 100;

    void Update() {

        int height = Mathf.RoundToInt(targetWidth / (float)Screen.width * Screen.height);

        camera.orthographicSize = height / pixelsToUnits / 2;
    }
}

Nell'editor è possibile modificare targetWidth per definire l'area dello spazio mondiale che si desidera visualizzare. Questo codice è spiegato nel seguente video insieme a molte altre pratiche per i giochi 2D :)

Unite 2014 - Best practice 2D in unità

Proporzioni

Le seguenti proporzioni, elencate dal più ampio al più stretto, coprono quasi tutte le dimensioni dello schermo sia per Android che per iOS

  • 5: 4
  • 4: 3
  • 3: 2
  • 16:10
  • 16: 9

Di solito imposto tutte queste proporzioni nell'ordine indicato sotto la finestra di gioco, poiché è utile durante il test per schermi di dimensioni diverse :)

Area spendibile

Questa è l'area che viene aggiunta allo schermo ai lati o in alto / in basso a seconda del ridimensionamento della fotocamera che hai scelto.

Per un'altezza fissa, tutti gli elementi del gioco dovrebbero preferibilmente adattarsi nel rapporto 16: 9 che è il più stretto. E lo sfondo dovrebbe estendersi fino a coprire il rapporto 5: 4. Il che assicura che il tuo gioco non abbia mai strisce nere ai lati.

Per larghezza fissa è quasi lo stesso, ma qui gli elementi dovrebbero adattarsi nel rapporto 5: 4 e il BG dovrebbe estendersi fino a 16: 9.

misura

A volte non possiamo usare l'approccio dell'area sacrificabile in quanto dobbiamo utilizzare l'intero schermo disponibile per il gioco.

Ad esempio, considera un gioco ritratto con altezza fissa, catturando le monete che cadono dal cielo. In questo dobbiamo dare al giocatore la possibilità di muoversi orizzontalmente sulla larghezza dello schermo disponibile.

Quindi abbiamo bisogno dei limiti della fotocamera in termini di coordinate mondiali per sapere dove esattamente la sinistra, la destra, la parte superiore o inferiore delle clip della fotocamera nella posizione mondiale.
Possiamo anche usare questi limiti per ancorare gli elementi del gioco o l'interfaccia utente a un lato desiderato della telecamera.

Usando Camera.ViewportToWorldPoint possiamo ottenere i limiti. Lo spazio di visualizzazione è normalizzato e relativo alla telecamera. L'angolo in basso a sinistra della telecamera è (0,0); l'angolo in alto a destra è (1,1). La posizione z è espressa in unità mondiali dalla fotocamera. Per 2D / ortografica la z non ha importanza.

Vector3 leftBottom = camera.ViewportToWorldPoint(new Vector3(0, 0, camera.nearClipPlane));
Vector3 rightTop = camera.ViewportToWorldPoint(new Vector3(1, 1, camera.nearClipPlane));

float left = leftBottom.x;
float bottom = leftBottom.y;
float right = rightTop.x;
float top = rightTop.y;

UI

Per l'interfaccia utente possiamo applicare gli stessi concetti che abbiamo usato per gli elementi di gioco. Dopo l'introduzione dell'interfaccia utente di Unity5 e la disponibilità di plugin come NGUI questo non sarà un grosso problema :)


0

Ho creato l'Unity Asset 'Resolution Magic 2D' per risolvere proprio questo problema (annuncio: puoi ottenerlo da Unity Asset Store o vedere maggiori dettagli su grogansoft.com).

Il modo in cui ho affrontato il problema è stato il seguente ...

Definisci un'area dello schermo che deve essere sempre visibile indipendentemente dalle proporzioni / risoluzione e usa una semplice trasformazione rettangolare per "stencil" questa regione. Questa è la forma dello schermo ideale. Usando un semplice algoritmo, ingrandisco la fotocamera fino a quando la regione bloccata dal rettangolo non è più grande possibile pur restando visibile al 100% alla fotocamera.

Quindi l'area di gioco principale occupa sempre più schermo possibile. E fintanto che c'è un contenuto 'extra' sufficiente (ad es. Lo sfondo) al di fuori dell'area del rettangolo precedentemente definita, i giocatori il cui schermo non ha le stesse proporzioni del rettangolo 'ideale' vedranno il contenuto extra in cui altrimenti le barre nere partire.

La mia risorsa include anche alcune logiche per il posizionamento dell'interfaccia utente, ma ciò è per lo più obsoleto a causa del nuovo sistema di interfaccia utente di Unity.

La mia risorsa fornisce questo out of the box con una configurazione minima e funziona davvero bene su tutte le piattaforme.

Se usi questa tecnica (o la mia risorsa), assicurati di progettare il tuo gioco in modo da avere uno spazio "opzionale" tutto intorno per ospitare schermi più larghi o più alti del tuo ideale (per evitare le barre nere).

Non realizzo personalmente giochi 3D, quindi non so se funzionerebbe in 3D (o se è addirittura necessario).

È davvero difficile da spiegare senza immagini, quindi per favore visita il mio sito Web ( Resolution Magic 2D )


0

La soluzione migliore per me è usare il teorema delle linee che si intersecano in modo che non vi sia né un taglio ai lati né una distorsione della vista del gioco. Ciò significa che è necessario fare un passo indietro o avanti a seconda delle diverse proporzioni.


-3

Ho creato un'estensione AssetStore che consente un cambio di aspetto più semplice chiamato AspectSwitcher . Fornisce un sistema che consente di specificare facilmente proprietà diverse per aspetti diversi. Esistono generalmente due metodi che la maggior parte delle persone usa per cambiare aspetto. Uno è fornire oggetti di gioco diversi per ogni aspetto. L'altro è quello di creare un codice personalizzato che modifica le proprietà di un singolo oggetto di gioco in base all'aspetto corrente. Ciò generalmente richiede molta codifica personalizzata. La mia estensione tenta di alleviare molto di quel dolore.


2
Questa risposta sarebbe migliore e sembrerebbe meno spammy, se elaborassi le tecniche reali che potresti usare per rispondere alla domanda del PO.
Josh
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.