Como você lida com as diferenças de proporção com o Unity 2D?

67

Eu recebi muitas respostas para essa pergunta, mas todas são genéricas e geralmente não são muito úteis. Nenhum dos tutoriais fala sobre relação de aspecto e como lidar com dispositivos móveis, e há um zilhão de maneiras de fazer isso, todas parecem ter problemas e falhas.

Eu realmente adoraria saber quais jogos de sucesso usaram para lidar com diferentes proporções no iOS e Android sem gerar um zilhão de ativos de tamanhos diferentes.

Estou falando estritamente de dispositivos móveis, não de desktop, especificamente com o Unity e não me importo com a interface do usuário, apenas com a tela de jogabilidade.

Os problemas que tenho em mente é quando há coisas importantes que precisam estar em determinados lugares e que não podem cair da tela. O uso de barras pretas na parte superior ou inferior é inaceitável atualmente.

Michael
fonte
3
Esta questão é muito ampla, pois o caminho certo depende de quase tudo. O que você tentou? Por que não funcionou?
Anko
3
Tentei todo o tipo de coisas, tentei ajustar o tamanho da câmera orto, tentei anexar todos os sprites para listar e dimensioná-los por diferença de proporção, definindo o tamanho orto para a tela. Altura / 2/100, muitas outras idéias. Alguns funcionam, mas todos eles têm problemas. Eu sei que jogos diferentes lidam com isso de maneira diferente, mas não há absolutamente nenhuma discussão sobre esse tópico em nenhum lugar e não é tão fácil quanto "apenas deixar a unidade lidar com isso", como muitos afirmam.
Michael
11
Então, por que eles não funcionaram? Como seria uma boa solução? (By the way, você pode editar a questão de esclarecer também.)
Anko
7
Alguns distorceram as imagens, outros não se alinharam corretamente. Muitos problemas diferentes, mas 65% dos jogos desenvolvidos com o Unity são 2D, e eles o fizeram funcionar. Eu só quero saber o que as pessoas estão usando e não ter que reinventar a roda. Ninguém fala sobre isso e não há guias ou documentos sobre como lidar com isso. No entanto, você não pode ir muito longe em um projeto móvel sem ter um sistema para fazê-lo.
Michael
11
"Os problemas que tenho em mente é quando há coisas importantes que precisam estar em determinados lugares e não podem cair da tela. Usar barras pretas na parte superior ou inferior é inaceitável nos dias de hoje". Garantia de elementos que não caem da tela, distorção zero, mas sem letras / colunas (barras pretas e similares). Esses requisitos são inconciliáveis. O último requisito é provavelmente o menos importante ou pode ser oculto preenchendo a tela além do que deve estar na tela. A maioria dos jogos que eu já vi com requisitos tão rigorosos terá decorações decorativas.
perfil completo de Jibb Smart

Respostas:

36

O que você deseja é restringir a viewport da câmera em retrato ou paisagem (dependendo de suas necessidades), através da camera.orthographicSizepropriedade de computação , para que você possa construir sua cena em 2d independentemente da proporção e resolução:

// 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 você precisar de mais informações sobre isso, pergunte e eu responderei. ;) Saudações e aplausos.

ATUALIZAÇÃO: Use o script de ancoragem de objetos de Eliot Lash junto com este para colocar objetos em posições-chave na tela, se necessário (em relação aos cantos / bordas da tela). Se você fizer isso, renomeie "CameraFit" para "ViewportHandler".

Visualização simulando várias telas de proporção: insira a descrição da imagem aqui

androidu
fonte
4
@ Eliot Adicionada licença MIT acima. Boa sorte com seus projetos!
androidu
7
Fantástico, obrigado! Uma mão lava a outra, então aqui está um componente de código aberto que eu escrevi para simples fixação de GameObjects aos pontos auxiliares definidas pelo seu script: gist.github.com/fadookie/256947788c364400abe1
Eliot
11
MarcelCăşvan Script muito bom! Adicionei uma enumeração para selecionar se você deseja definir o tamanho da unidade para potrait para paisagem (altura / largura). Apenas teve que adicionar um par de linhas para o script, e eu uso GetComponent<Camera>().orthographicSize = UnitSize / 2f;para potrait / definição de unidades de altura
AM_
2
@ MarcelCăşvan grandes coisas! Obrigado. Vejo que as variáveis ​​deviceWidth e deviceHeight de ComputeFunction () não são utilizadas. Talvez considere excluí-los.
usar o seguinte comando
11
O CameraAnchor está lançando o erro: "CameraFit não está definido neste contexto" - Caso alguém encontre essa resposta posteriormente, parece que "CameraFit" acabou de renomear "ViewportHandler", pois foi originalmente publicado. Se você acabou de renomear a classe de ViewportHandler de volta para CameraFit.
Lenny
5

Normalmente, você não precisa de tamanhos diferentes de recursos - texturas e sprites importados com mapas mip gerados automaticamente ficarão agradáveis ​​quando renderizados em qualquer tamanho menor ou igual ao tamanho de pixel original da imagem.

O layout da cena é o desafio. Uma boa abordagem é a seguinte (e, para sua informação, eu uso uma câmera 3D olhando para o conteúdo 2D posicionado em z = 0):

  1. Decida arbitrariamente sobre um tamanho de exibição "lógico" mínimo em pixels ou blocos. Isso não precisa corresponder a nenhuma resolução do mundo real, mas deve refletir a proporção mais estreita / mais curta que você deseja oferecer suporte. Por exemplo, para um jogo paisagístico, eu não escolheria 480x320, porque essa é uma proporção maior que o iPad. Portanto, posso escolher 1024x768 - ou mesmo 480x360, o que me fornece um sistema de coordenadas original do tamanho do iPhone para trabalhar e a mesma proporção de todos os iPads (incluindo o iPad Air 2, etc.). Observe também que você pode trabalhar com facilidade nas coordenadas de bloco em vez de coordenadas de pixel - 15x11,25 por exemplo.
  2. Programe sua lógica do jogo para que tudo o mais importante seja (ou possa ser) posicionado dentro do tamanho mínimo de exibição, mas esteja preparado para preencher espaço extra nas laterais com conteúdo adicional, mesmo que seja apenas um preenchimento decorativo.
  3. Determine quanto você precisa dimensionar seu conteúdo para que a largura ou a altura correspondam ao valor mínimo e o outro eixo seja maior ou igual ao mínimo necessário. Para fazer isso "dimensionar para caber", divida o tamanho do pixel da tela pelo tamanho mínimo de exibição e considere o menor dos valores de escala resultantes como sua escala geral de visualização.
  4. Use a escala de exibição para calcular o tamanho efetivo (real) da exibição para fins de lógica do jogo.
  5. Na verdade, redimensione seu conteúdo movendo a câmera ao longo do eixo Z.

Em forma de código:

  // 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
AbePralle
fonte
2

Se você usar as barras, é realmente muito simples de implementar (eu estou postando isso, embora o OP tenha declarado a opinião inaceitável porque tem o benefício de não ser tão ruim no celular e é uma solução simples que não requer nenhum código)

Camera.orthographicSizeé uma variável na câmera orto (usada pela maioria dos jogos 2D) que se ajusta à quantidade medida de unidades de jogo verticalmente na tela ( dividida por 2 ) ( fonte ). Portanto, escolha uma proporção que se encaixe na grande maioria dos dispositivos (eu escolhi 16: 9, pois a maioria das telas que pesquisei são 16: 9, 16:10, 3: 2) e adicione uma máscara que se sobreponha a essa proporção.

Exemplo :

No meu jogo (não listado aqui, pois este não é um anúncio, pode perguntar nos comentários, se desejar), usamos o modo retrato. Para fazer um bom 16: 9 simples, criei minha câmera Ortho no tamanho 16. Isso significa que a câmera adaptará 32 unidades de altura de jogo (de 16 a 16 no meu caso) na vertical da tela do dispositivo.

Coloquei máscaras pretas com um jogo entre -9 e +9. Bem, a tela do jogo parece exatamente igual em todos os dispositivos e um pouco mais fina em dispositivos um pouco mais largos. Não tive absolutamente nenhum feedback negativo sobre as máscaras. Para fazer a paisagem, basta inverter esses valores e, então, você criaria a câmera com o tamanho 9. Altere os valores para corresponderem ao que você decidiu que é a escala da sua unidade de jogo.

O único lugar em que observamos a barra preta aparecer significativamente é no iPad, às 3: 2. Mesmo assim, não tive queixas.

McAden
fonte
1

Estou fazendo isso em um jogo no qual estou trabalhando atualmente. Eu tenho uma imagem de plano de fundo que é 1140x720. Os bits mais importantes (os que nunca devem ser cortados) estão contidos na área central de 960x640. Eu executo esse código na função start da minha câmera:

    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);

Também defino outros tamanhos, além do tamanho da fonte, para botões e afins. Funciona bem em todas as proporções que testei. Já faz um tempo desde que eu o configurei, então posso estar perdendo um passo. Deixe-me saber se não funcionar como esperado e vou ver se deixei alguma coisa de fora.

John
fonte
1

A resposta e o código de @ Marcel são ótimos e me ajudaram a entender o que estava acontecendo. É a resposta definitiva. Apenas pensei que alguém também poderia achar útil o que acabei fazendo no meu caso específico: como eu queria que algo realmente realmente simples, um sprite estivesse sempre na tela, eu vim com estas poucas linhas:

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;
    }
}

Adicionei isso à câmera e arrastei meu sprite (é meu plano de fundo) para a única propriedade do script. Se você não deseja barras pretas (horizontais ou verticais), pode colocar um fundo maior por trás dessa ...

maltalef
fonte
0

Existem algumas maneiras de resolver esse problema, e não há uma solução perfeita (pelo menos ainda não encontrei uma) e o tipo de solução que você utiliza depende muito do tipo de jogo que você está usando. em desenvolvimento.

Independentemente de você o que faz, você deve começar escolhendo a menor resolução possível que deseja apoiar e criar seus sprites para essa resolução. Portanto, se você estiver interessado em desenvolver para iOS, de acordo com http://www.iosres.com/, a resolução mais baixa do dispositivo iOS é 480x320.

A partir daí, você pode começar a expandir os sprites para atender às resoluções mais altas. A ressalva é que você acabará percebendo que os sprites começam a ficar mais borrados na escala, nesse caso, você pode mudar para outro conjunto de sprites criados para resoluções mais altas.

Ou você pode ignorar o dimensionamento completamente e apenas decidir exibir mais da tela do jogo para obter resoluções mais altas (acredito que é assim que Terraria faz isso, por exemplo). No entanto, para muitos jogos, isso não é apropriado; jogos competitivos, por exemplo.

O uso de barras pretas na parte superior ou inferior é inaceitável atualmente.

É isso? Muitos jogos que desejam forçar as proporções 4: 3 fazem isso. Como você está usando o Unity, você pode usar o script AspectRatioEnforcer para ajudar nisso.

Tanoeiro
fonte
Como estou segmentando para dispositivos móveis, não posso alterar a proporção ou a resolução. Usar ativos de baixa resolução não é uma solução aceitável. Alguns jogos (especialmente 3D) não são um problema, você apenas mostra mais ou menos. Mas jogos como Kingdom Rush, tower defense e outros jogos como Alex, você deseja ver a mesma coisa, independentemente do dispositivo. Se as coisas não aparecerem nos locais certos, o jogo não funcionará corretamente.
Michael
0

Existem várias maneiras de lidar com esse problema, isso depende do seu jogo e do que funcionará melhor. Por exemplo, em nosso jogo Tyrant Unleashed , simplesmente fizemos mapas amplos com detalhes sem importância nas laterais, para que não há problema em cortar as laterais em dispositivos mais estreitos. No entanto, outros jogos podem ser melhores com uma abordagem em que você realmente muda os botões ou algo para se ajustar melhor à tela.

(também parte de nossa abordagem também é manter uma altura consistente em todos os dispositivos, variando apenas a largura. Isso certamente facilita a vida para nós, mas, novamente, isso pode ou não ser bom para o seu jogo específico. Não importa em nosso estilo artístico, se as imagens forem dimensionadas um pouco em telas diferentes, embora isso possa interessar algo como pixel art (basicamente, essa é a abordagem "deixe a Unity lidar com isso")

jhocking
fonte
Você já fez algum projeto em que isso não era uma opção? Quase todos os jogos de estilo de defesa de torre que eu já vi e muitos outros estilos podem ser vistos no dispositivo sem rolagem, e isso é consistente entre os dispositivos. No IOS, você pode criar ativos e trocá-los, mas isso se torna impossível (e realmente apenas uma grande PITA) no Android.
Michael
Não, eu não tenho. btw eu só adicionou mais alguns detalhes sobre o tamanho da tela
jhocking
0

Estou usando o script a seguir, que adiciona um targetAspectparâmetro à câmera e o adapta orthographicSizeem relação à proporção da tela (mais detalhes nesta postagem do 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;
        }
    }
}
sdabet
fonte
0

Meu método é mais parecido com as soluções fornecidas por outros :) Vou tentar explicar em detalhes a abordagem adotada para tornar o jogo independente do tamanho da tela.

Orientação da tela

Dependendo da orientação da tela (paisagem ou retrato), é necessário considerar se a câmera será dimensionada com uma altura ou largura fixa. Escolho principalmente a largura fixa para jogos orientados para paisagem e altura fixa para jogos orientados para retrato.

Escala da câmera

Conforme discutido, isso pode ser altura ou largura fixas.

Altura fixa : a área vertical do jogo sempre se ajustará à altura da tela. E conforme a proporção da tela muda, haverá espaço extra adicionado à esquerda e direita da tela. Para implementar isso, você não precisa codificar nada, é o comportamento padrão da câmera da unidade.

Largura fixa : a área horizontal do jogo sempre se ajusta à largura da tela. E um espaço extra será adicionado à parte superior e inferior conforme a proporção da tela muda. Para implementar isso, você precisa escrever um pequeno pedaço de código. Posteriormente, remova a função de atualização do formulário de código e coloque-a em funcionamento.

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;
    }
}

No editor, você pode alterar a targetWidth para definir a área do espaço mundial que você deseja exibir. Este código é explicado no vídeo a seguir, juntamente com muitas outras práticas para jogos 2D :)

Unite 2014 - Melhores práticas 2D no Unity

Proporção da tela

As proporções a seguir, listadas da maior para a mais estreita, cobrem quase todos os tamanhos de tela para Android e iOS

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

Normalmente, defino todas essas proporções na ordem especificada abaixo da janela do jogo, pois é útil ao testar diferentes tamanhos de tela :)

Área de consumo

Essa é a área que é adicionada à tela nas laterais ou na parte superior / inferior, dependendo da escala da câmera que você escolheu.

Para altura fixa, todos os elementos do jogo devem se encaixar preferencialmente na proporção 16: 9, que é a mais estreita. E o plano de fundo deve se estender até cobrir a proporção de 5: 4. O que garante que seu jogo nunca tenha faixas pretas nas laterais.

Para largura fixa, é quase a mesma, mas aqui os elementos devem caber na proporção 5: 4 e o BG deve se estender até 16: 9.

Limites

Às vezes, não podemos usar a abordagem de área dispensável, pois precisamos utilizar toda a tela disponível para o jogo.

Por exemplo, considere um jogo de retratos com altura fixa, pegando as moedas que caem do céu. Nisso, precisamos dar ao jogador a capacidade de se mover horizontalmente sobre a largura da tela disponível.

Portanto, precisamos dos limites da câmera em termos de coordenadas mundiais para saber exatamente onde estão os lados esquerdo, direito, superior ou inferior dos clipes da câmera na posição mundial.
Também podemos usar esses limites para ancorar elementos do jogo ou interface do usuário para o lado desejado da câmera.

Usando Camera.ViewportToWorldPoint, podemos obter os limites. O espaço da viewport é normalizado e relativo à câmera. O canto inferior esquerdo da câmera é (0,0); o canto superior direito é (1,1). A posição z está nas unidades mundiais da câmera. Para 2D / ortográfico, o z não importa.

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

Para a interface do usuário, podemos aplicar os mesmos conceitos que usamos para os elementos do jogo. Após a introdução da interface do usuário do Unity5 e a disponibilidade de plug-ins como o NGUI, isso não será um grande problema :)

Hash Buoy
fonte
0

Criei o Unity Asset 'Resolution Magic 2D' para resolver esse problema (anúncio: você pode obtê-lo na Unity Asset Store ou veja mais detalhes em grogansoft.com).

A maneira como lidei com o problema foi a seguinte ...

Defina uma área da tela que sempre deve estar visível, independentemente da proporção / resolução, e use uma simples transformação de retângulo para 'estêncil' esta região. Este é o seu formato de tela ideal. Usando um algoritmo simples, amplio a câmera até que a região bloqueada pelo retângulo seja a maior possível, mantendo-se 100% visível para a câmera.

Então sua área principal de jogo está sempre ocupando o máximo de tela possível. E desde que haja conteúdo 'extra' suficiente (por exemplo, seu plano de fundo) fora da área do retângulo que você definiu anteriormente, jogadores cuja tela não tenha a mesma proporção que o seu retângulo 'ideal' verá o conteúdo extra onde as barras pretas estariam ir.

Meu ativo também inclui alguma lógica para colocar a interface do usuário, mas isso é obsoleto devido ao novo sistema de interface do usuário do Unity.

Meu ativo fornece isso pronto para o uso com uma configuração mínima e funciona muito bem em todas as plataformas.

Se você usar essa técnica (ou o meu patrimônio), apenas projete seu jogo para ter espaço 'opcional' ao redor para acomodar telas maiores ou mais altas que o ideal (para evitar barras pretas).

Eu pessoalmente não faço jogos em 3D, então não sei se isso funcionaria em 3D (ou se é mesmo necessário).

É realmente difícil de explicar sem fotos, então visite meu site ( Resolution Magic 2D )

pumpkinszwan
fonte
0

A melhor solução para mim é usar o teorema das linhas que se cruzam para que não haja um corte nas laterais nem uma distorção na visão do jogo. Isso significa que você precisa recuar ou avançar dependendo da proporção da imagem.

unityfever
fonte
-3

Criei uma extensão AssetStore que permite uma troca de aspecto mais fácil chamada AspectSwitcher . Ele fornece um sistema para permitir que você especifique facilmente diferentes propriedades para diferentes aspectos. Geralmente, existem dois métodos que a maioria das pessoas usa para alternar aspectos. Uma é fornecer objetos de jogo diferentes para cada aspecto. A outra é criar um código personalizado que modifique as propriedades de um único objeto de jogo com base no aspecto atual. Isso geralmente requer muita codificação personalizada. Minha extensão tenta aliviar muita dor.

Jason
fonte
2
Essa resposta seria melhor, e pareceria menos spam, se você elaborasse as técnicas reais que poderíamos usar para resolver a questão do OP.
Josh