Unity 2D ile boy oranı farklılıklarını nasıl ele alıyorsunuz?


67

Bu soruya birçok cevap aldım, ancak hepsi genel ve genellikle çok kullanışlı değil. Eğitmenlerin hiçbiri en boy oranı hakkında konuşmuyor ve mobil cihazlarla ilgileniyor ve bunu yapmanın zilksiz bir yolu var, hepsinin de başıboşluğu ve kusurları var gibi görünüyor.

Gerçekten de iOS ve Android'de farklı boyut oranlarını elde etmek için hangi başarılı oyunların kullanıldığını bilmek isterim; zilyonlarca farklı boyutlarda varlıklar yapmadan.

Özellikle Unity ile masaüstü değil, kesinlikle mobil olarak konuşuyorum ve UI'yi umursamıyorum, sadece oyun tuvalini önemsiyorum.

Aklımda olan meseleler, belirli yerlerde olması gereken ve ekrandan düşemeyen önemli şeyler olduğu zamandır. Bugünlerde üstte veya altta siyah çubukların kullanılması kabul edilemez.


3
Bu soru çok geniştir, çünkü doğru yol neredeyse her şeye bağlıdır. Ne denedin Neden işe yaramadı?
Anko

3
Her şeyi denedim, orto kamera boyutunu ayarlamayı denedim, boyuta göre farklılık göstererek listelemek ve ölçeklendirmek için bütün sprite'ları eklemeye çalıştım, orto boyutunu screen.height / 2/100, birçok başka ayarlamaya çalıştım fikirler. Bazı işler, fakat hepsinin sorunları var. Farklı oyunların farklı olduğunu biliyorum ama bu konuyla ilgili hiçbir yerde kesinlikle tartışma yok ve “birliğin onu ele almasına izin vermek” kadar kolay değil.
Michael,

1
Peki neden işe yaramadılar? İyi bir çözüm neye benzerdi? (Bu arada, açıklığa kavuşturmak için soruyu da düzenleyebilirsiniz.)
Anko

7
Bazıları görüntüleri çarpıttı, bazıları doğru sıraya girmedi. Pek çok farklı konu var, ancak Unity ile geliştirilen oyunların% 65'i 2D, ve çalışmasını sağladı. Sadece insanların ne kullandığını bilmek ve tekerleği yeniden icat etmek zorunda kalmamak istiyorum. Kimse bundan bahsetmiyor ve nasıl idare edileceğine dair rehber ya da belge yok. Yine de bir sistemi yerine getirmeden bir mobil projede uzağa gidemezsiniz.
Michael,

1
“Aklımda olan meseleler, belirli yerlerde olması gereken ve ekranın dışına çıkamayacak kilit şeyler olduğundadır. Bugünlerde üstte veya altta siyah çubukların kullanılması kabul edilemez.” Elemanların ekrandan düşmemesi, sıfır bozulma garantisi yok, ancak harf / direk kutusu yok (siyah çubuklar ve benzeri). Bu gereksinimler uzlaştırılamaz. Son gereksinim muhtemelen en az önemlidir veya tuvali ekranda olması gerekenin ötesine yayarak gizlenebilir . Bu kadar katı şartlarda gördüğüm oyunların çoğu, sütun kutucuğunu / kenarlıkları dekore etmiş olacak.
Jibb Smart

Yanıtlar:


36

İstediğiniz şey, bilgisayar camera.orthographicSizeözelliğini kullanarak kamera görünüm çerçevesini dikey veya yatay olarak (gereksinimlerinize bağlı olarak) sınırlamak , böylece en boy oranı ve özünürlükten bağımsız olarak 2. sahnenizi oluşturabilirsiniz:

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

Bu konuda daha fazla bilgiye ihtiyacınız olursa lütfen sorunuz, ben de cevaplayacağım. ;) Saygılar ve şerefe.

GÜNCELLEME: Eliot Lash'ın nesne bağlama komut dosyasını, bununla birlikte gerektiğinde ekrandaki anahtar konumlara (ekran köşelerine / kenarlıklarına göre) yerleştirmek için bununla birlikte komut dosyası kullanın . Bunu yaparsanız, "CameraFit" ı "ViewportHandler" olarak yeniden adlandırın.

Çeşitli en boy oranları ekranlarını simüle önizleme: görüntü tanımını buraya girin


4
@Eliot Yukarıdaki MIT lisansı eklendi. Projelerinizde başarılar!
androidu

7
Harika, teşekkürler! İyi bir dönüş diğerini hak ediyor, işte GameObjects'in basit bir şekilde tutturulması
Eliot

1
MarcelCăşvan Çok güzel senaryo! Manzara için potrait için birim büyüklüğü tanımlamak isteyip istemediğinizi seçmek için bir enum ekledim (yükseklik / genişlik). Sadece senaryoya birkaç satır eklemek zorunda kaldım ve GetComponent<Camera>().orthographicSize = UnitSize / 2f;
potrait

2
@ MarcelCăşvan harika şeyler! Teşekkürler. ComputeFunction () 'dan deviceWidth ve deviceHeight değişkenlerinin kullanılmadığını görüyorum. Belki bunları silmeyi düşünün.
user2313267

1
CameraAnchor şu hatayı veriyor: "CameraFit bu bağlamda tanımlanmadı" - Bu cevabı daha sonra bir başkasının bulması halinde, "CameraFit", "ViewportHandler" adını değiştirdi, çünkü asıl yayınlandığı için. Sınıfı ViewportHandler'dan yeniden CameraFit'e değiştirirseniz.
Lenny

5

Genellikle farklı boyutlardaki varlıklara ihtiyacınız yoktur; otomatik olarak oluşturulan mip haritalarına sahip içe aktarılan dokular ve sprite, görüntünün orijinal piksel boyutundan daha küçük veya ona eşit herhangi bir boyutta görüntülendiğinde hoş görünür.

Sahne düzeni zorluktur. İyi bir yaklaşım şöyledir (ve FYI, z = 0 konumunda 2B içeriğe bakarak bir 3B kamera kullanıyorum):

  1. İsteğe bağlı olarak piksel veya döşemelerde minimum "mantıksal" görüntü boyutuna karar verin. Bunun herhangi bir gerçek dünya çözünürlüğüne tekabül etmesi gerekmez, ancak desteklemek istediğiniz en dar / en kısa en boy oranını yansıtması gerekir . Örneğin, bir peyzaj oyunu için 480x320'yi seçmedim çünkü bu iPad'den daha geniş bir en boy oranı. Bu yüzden, 1024x768 - hatta 480x360 bile seçebilirim, bu da bana çalışması için iPhone boyutunda bir koordinat sistemi ve her iPad'deki (iPad Air 2 vb. Gibi) en boy oranını verir. Ayrıca, piksel koordinatlarından ziyade çini koordinatlarında da kolayca çalışabileceğinizi unutmayın - örneğin 15x11.25.
  2. Oyun mantığınızı, önemli olan her şey minimum ekran boyutunuzda olacak şekilde yerleştirilebilecek şekilde yerleştirilebilecek şekilde yerleştirilmelidir, ancak yalnızca dekoratif bir dolgu olsa bile, yanlardaki ilave odayı ilave içerikle doldurmaya hazır olun.
  3. İçeriğinizi ne kadar ölçeklendirmeniz gerektiğini belirleyin, böylece genişlik veya yükseklik minimum değerle eşleşir ve diğer eksen gereken minimum değerden büyük veya ona eşit olur. Bu "sığdırmak için ölçek" yapmak için, ekran piksel boyutunu minimum ekran boyutuna bölün ve elde edilen ölçek değerlerinden daha küçük olanı genel görünüm ölçeğiniz yapın.
  4. Oyun mantığı için etkili (gerçek) ekran boyutunu hesaplamak için görüntüleme ölçeğini kullanın.
  5. Kamerayı Z ekseni boyunca hareket ettirerek içeriğinizi ölçeklendirin.

Kod biçiminde:

  // 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

Çubukları kullanmaya başlarsanız, uygulanması gerçekten oldukça basittir (OP'nin kabul edilemez olduğu görüşünü bildirmesine rağmen bunu gönderiyorum çünkü mobil cihazlara yakın olmaktan da yararlanma avantajına sahiptir ve bu basit bir çözümdür. hiç bir kod gerektirmez)

Camera.orthographicSizeorto kamera içindeki (çoğu 2D oyunun kullandığı) ölçülen oyun birimlerinin miktarını ekran üzerinde dikey olarak ( 2'ye bölünür ) ( kaynak ) kullanan bir değişkendir . Bu nedenle, cihazların çoğuna uyan en boy oranını seçin (araştırdığım çoğu ekran 16: 9, 16:10, 3: 2 olduğu için 16: 9'u seçtim) ve oranını kaplayan bir maske ekleyin.

Örnek :

Oyunumda (burada bir reklam olmadığı için listelenmemiş, istenirse yorum sorabilir) portre modunu kullanıyoruz. Güzel bir basit 16: 9 yapmak için Ortho kamerayı 16 boyutunda yaptım. Bu, kameranın 32 oyun birimini (benim durumumda y: 16 ila -16) cihazın dikey ekranına uyarlayacağı anlamına geliyor.

Daha sonra -9 ile +9 arası bir oyuna sahip siyah maskeler yerleştirdim. Voila, oyunun ekranı tüm cihazlarda aynı görünüyor ve biraz daha geniş olan cihazlarda biraz daha zayıf görünüyor. Maskelerle ilgili kesinlikle hiçbir olumsuz geribildirim almadım. Manzara yapmak için bu değerleri çevirin ve sonra kamerayı 9 boyutuna getirin.

Siyah çubuğun belirgin şekilde göründüğü tek yer iPad'de 3: 2. O zaman bile, hiçbir şikayetim olmadı.


1

Bunu şu anda üzerinde çalışmakta olduğum bir oyunda yapıyorum. 1140x720 olan bir arka plan resmim var. En önemli bitler (asla kırpılmaması gerekenler) 960x640 orta alanda bulunur. Bu kodu kameramın başlat işlevinde çalıştırıyorum:

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

Ayrıca düğmeler için yazı tipi boyutu ve benzeri boyutlar tanımlarım. Test ettiğim her boyut oranında iyi çalışıyor. Ayarladığımdan bu yana bir süre geçti, bu yüzden bir adım eksik olabilir. Beklendiği gibi çalışmazsa haberim olsun ve bir şey bırakıp bırakmadığımı göreceğim.


1

@ Marcel'in cevabı ve kodu harika ve neler olduğunu anlamama yardımcı oldu. Bu kesin cevap. Sadece birisinin kendi davam için yaptıklarımı da faydalı bulabileceğini düşündüm: gerçekten çok basit bir şey istediğim için, bir sprite her zaman ekranda olmak için, şu birkaç satırla karşılaştım:

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

Bunu kameraya ekledim ve sprite'ımı (arka planım) betiğin tek özelliğine sürükledim. Eğer siyah çubuk istemiyorsanız (yatay ya da dikey), bunun arkasına daha büyük bir arka plan koyabilirsiniz ...


0

Bu sorunu çözmenin birkaç yolu vardır ve mükemmel bir çözüm yoktur (en azından henüz bir tane bulamadım) ve birlikte gelen çözümün türü büyük ölçüde seçtiğiniz oyun türüne bağlı olacak gelişmekte.

Siz ne yaparsanız yapın, desteklemek ve spritlerinizi o çözünürlükte oluşturmak istediğiniz en düşük çözünürlüğü seçerek başlamalısınız. Bu nedenle, iOS için geliştirme yapmak istiyorsanız, http://www.iosres.com/ e göre en düşük iOS cihaz çözünürlüğü 480x320'dir.

Oradan, daha yüksek çözünürlükleri karşılamak için sprite ölçeklendirmeye başlayabilirsiniz. Bunun ihmali, spriteların ölçtüğünüz kadar uzağa bulanıklaşmaya başladığını fark etmeye başlayacağınızdır; bu durumda daha yüksek çözünürlükler için oluşturulan başka bir sprite grubuna geçebilirsiniz.

Ya da ölçeklendirmeyi tamamen görmezden gelebilir ve sadece daha yüksek çözünürlükler için oyun ekranını daha fazla göstermeye karar verebilirsiniz (mesela Terraria böyle yapar). Ancak, birçok oyun için bu uygun değildir; örneğin rekabetçi oyunlar.

Bugünlerde üstte veya altta siyah çubukların kullanılması kabul edilemez.

Bu mu? 4: 3 oran oranlarını zorlamak isteyen birçok oyun bunu yapar. Unity'yi kullandığınızdan beri , ona yardım etmek için AspectRatioEnforcer komut dosyasını kullanabilirsiniz.


Cep telefonunu hedefliyorum, bu yüzden en / boy oranını veya çözünürlüğünü değiştiremiyorum. Düşük çözünürlüklü varlıkların kullanılması kabul edilebilir bir çözüm değildir. Bazı oyunlar (özellikle 3B) sorun değil, az ya da çok gösterirsin. Ancak Kingdom Rush, kule savunma ve Alex gibi diğer oyunların oyundan bağımsız olarak aynı şeyi görmek istersiniz. İşler doğru yerlerde görünmezse, oyun düzgün çalışmaz.
Michael,


0

Bu konuyu ele almanın birden fazla yolu vardır, bu oyununuza ve neyin işe yarayacağına bağlıdır. Mesela, Tyrant Unleashed adlı oyunumuzda sadece tarafları önemsiz ayrıntılarla açıklayan geniş haritalar yaptık, böylece daha dar cihazlarda kenarları kesmek sorun değil. Bununla birlikte, diğer oyunlar düğmeleri gerçekte kaydırdığınız bir yaklaşımla veya ekrana daha iyi sığacak bir şeyle daha iyi olabilir.

(Yaklaşımımızın bir parçası da tüm cihazlarda tutarlı bir yükseklik tutuyor, sadece genişliği değiştiriyor. Bu kesinlikle bizim için hayatı kolaylaştırıyor, ancak yine de bu sizin oyununuz için iyi bir şey olabilir veya olmayabilir.) resimlerimiz biraz farklı ekranlarda ölçeklendiyse, bizim sanat tarzımız, piksel sanatı gibi bir şey için önemli olabilir.


Bunun seçenek olmadığı herhangi bir proje yaptınız mı? Neredeyse gördüğüm kule savunma tarzı oyunların ve diğer birçok stilin tüm oyun görünümünü aygıtta kaydırma yapmadan görebilirsiniz ve bu, cihazlar arasında tutarlı. IOS'de varlıklar oluşturabilir ve bunları değiştirebilir, ancak Android'de bu imkansız hale gelir (ve gerçekten de sadece büyük bir PITA).
Michael,

Hayır yapmadım. btw Sadece ekran boyutu hakkında biraz daha ayrıntı ekledim
jhocking

0

targetAspectKameraya bir parametre ekleyen orthographicSizeve ekran oranına göre uyarlayan aşağıdaki betiği kullanıyorum ( bu blog gönderisinde daha fazla ayrıntı ):

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

Benim yöntemim çoğunlukla başkalarının verdiği çözümlere benziyor :) Oyunu, ekran boyutundan bağımsız kılmak için kullandığım yaklaşımı ayrıntılı olarak açıklamaya çalışacağım.

Ekran Yönü

Ekran yönüne bağlı olarak (Manzara veya Portre), kameranın sabit bir yükseklikte mi, yoksa sabit genişlikte mi ölçekleneceğini dikkate almanız gerekir. Çoğunlukla peyzaj odaklı oyunlar için sabit genişliği ve portre odaklı oyunlar için sabit yüksekliği seçiyorum.

Kamera ölçeklendirme

Tartışıldığı gibi, bu sabit yükseklik veya sabit genişlik olabilir.

Sabit Yükseklik : Oyunun dikey alanı her zaman ekran yüksekliğine uyacaktır. Ekran en boy oranı değiştikçe, ekranın soluna ve sağına eklenen fazladan boşluk olacaktır. Bunu uygulamak için hiçbir şeyi kodlamanız gerekmez, bu birlik kamerasının varsayılan davranışıdır.

Sabit Genişlik : Oyunun yatay alanı her zaman ekran genişliğine uyacaktır. Ekranın en boy oranı değiştikçe üste ve aşağıya fazladan boşluk eklenir. Bunu uygulamak için küçük bir kod parçası yazmanız gerekir. Daha sonra kod formu güncelleme işlevini kaldırdığınızdan ve uyanık duruma getirdiğinizden emin olun.

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

Editörde, görüntülemek istediğiniz dünya alanı alanını tanımlamak için targetWidth'i değiştirebilirsiniz. Bu kod aşağıdaki videoda 2D oyunlar için pek çok başka uygulama ile birlikte açıklanmıştır :)

Unite 2014 - 2D Birlikteki En İyi Uygulamalar

En Boy Oranı

En genişinden en darına doğru en boy oranı listelendikten sonra, android ve iOS için neredeyse tüm ekran boyutlarını kapsar

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

Genelde tüm bu ekran oranlarını oyun ekranının altında verilen sıraya göre ayarlıyorum, çünkü farklı ekran boyutlarını test ederken kullanışlıdır :)

Harcanabilir Alan

Bu, seçtiğiniz kamera ölçeklemesine bağlı olarak ekrana yanlara veya üste / aşağıya eklenen alandır.

Sabit yükseklik için tüm oyun elemanları tercihen en dar olan 16: 9 oranına sığmalıdır. Ve arka plan 5: 4 oranını kaplayana kadar uzamalıdır. Bu da oyununuzun asla yanlarda siyah şeritler bulunmamasını sağlar.

Sabit genişlik için hemen hemen aynıdır ancak burada elementler 5: 4 oranına sığmalı ve BG 16: 9'a kadar uzatmalıdır.

sınırlar

Bazen oyun alanı için mevcut tüm ekranı kullanmamız gerektiğinden, harcanabilir alan yaklaşımını kullanamayız.

Örneğin, gökten düşen paraları yakalamak, sabit yükseklikte bir portre oyunu düşünün. Bu konuda, oyuncuya mevcut ekran genişliği boyunca yatay hareket etme yeteneği vermemiz gerekiyor.

Bu nedenle, kameranın sınırlarının, dünyadaki kameranın sol, sağ, üst veya alt kısımlarının dünyadaki tam olarak nerede olduğunu bilmek için koordine etmesi gerekir.
Bu sınırları oyun oyunlarını veya UI'yı kameranın istediğiniz bir tarafına tutturmak için de kullanabiliriz.

Camera.ViewportToWorldPoint kullanarak sınırları alabiliriz. Viewport alanı normalleştirilir ve kameraya göre ayarlanır. Kameranın sol alt kısmı (0,0); sağ üst (1,1). Z konumu kameradaki dünya birimlerinde. 2D / ortografik için z önemli değil.

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

Kullanıcı arayüzü için, oyun elemanları için kullandığımız konseptleri uygulayabiliriz. Unity5 UI'nın tanıtılmasından ve NGUI gibi eklentilerin kullanılabilirliğinden sonra, bu pek sorun olmayacak :)


0

Bu sorunu çözmek için Unity Asset 'Çözünürlük Magic 2D' yi yarattım (reklam: Unity Asset Store'dan edinebilir veya grogansoft.com adresinde daha fazla ayrıntı görebilirsiniz).

Problemi çözme yöntemim şu şekildedi ...

En boy oranı / çözünürlüğüne bakılmaksızın her zaman görünür olması gereken ekranın bir alanını tanımlayın ve bu bölgeyi 'şablonlamak' için basit bir dikdörtgen dönüşümü kullanın. Bu sizin ideal ekran şeklinizdir. Basit bir algoritma kullanarak daha sonra, kameranın dikdörtgeni tarafından engellenen bölge kamera için% 100 görünürken olabildiğince büyük olmasına kadar yakınlaştırırım.

O zaman ana oyun alanınız her zaman mümkün olduğunca ekranı kaplıyor. Daha önce tanımladığınız dikdörtgen alanın dışında yeterli 'ekstra' içerik (ör. Arka planınız) olduğu sürece, ekranı 'ideal' dikdörtgenizle aynı en boy oranı olmayan oyuncular, siyah çubukların aksi durumda olacağı ekstra içeriği göreceklerdir. Git.

Varlığım ayrıca UI yerleştirmek için bir mantık içeriyor, ancak bu Unity'nin yeni UI sistemi nedeniyle çoğunlukla kullanılmıyor.

Varlığım bunu kutudan minimum kurulumla sağlıyor ve tüm platformlarda gayet iyi çalışıyor.

Bu tekniği (veya varlığımı) kullanırsanız, oyununuzu, idealden daha geniş veya daha uzun ekranlara yerleştirmek için (isteğe bağlı siyah çubuklardan kaçınmak için) 'isteğe bağlı' alana sahip olacak şekilde tasarladığınızdan emin olun.

Kişisel olarak 3B oyunlar yapmıyorum, bu yüzden bunun 3B olarak çalışıp çalışmayacağını (veya gerekli olup olmadığını) bilmiyorum.

Resimler olmadan açıklamak gerçekten zor, bu yüzden lütfen web sitemi ziyaret edin ( Resolution Magic 2D )


0

Benim için en iyi çözüm, kesişen çizgilerin teoremini kullanmaktır, böylelikle taraflarda bir kesilme veya oyun görüşünün bozulmaması söz konusu değildir. Bu, farklı en boy oranına bağlı olarak geriye veya ileriye adım atmanız gerektiği anlamına gelir.


-3

Aradım kolay yönü geçiş için izin veren bir AssetStore uzantısı yarattı AspectSwitcher . Farklı yönler için kolayca farklı özellikler belirlemenizi sağlayan bir sistem sunar. Genelde çoğu insanın yön değiştirmek için kullandığı iki yöntem vardır. Biri, her yön için farklı oyun nesneleri sağlamaktır. Diğeri, tek bir oyun nesnesinin özelliklerini, mevcut duruma göre değiştiren özel bir kod oluşturmaktır. Bu genellikle çok fazla sayıda özel kodlama gerektirir. Uzatmam bu acının çoğunu hafifletmeye çalışıyor.


2
Bu sorunun cevabı daha iyi olur ve daha az spam görünüyor, eğer OP'nin sorusunu ele almak için kullanabileceğiniz teknikler hakkında detaylı bilgi verirseniz.
Josh
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.