Як ви обробляєте відмінності співвідношення сторін за допомогою Unity 2D?


67

Я отримав багато відповідей на це питання, але всі вони є загальними і, як правило, не дуже корисними. Жоден з навчальних посібників не говорить про співвідношення сторін та поводження з мобільними пристроями, і існує мільйон способів це зробити, все, здається, має і недоліки.

Мені дуже хотілося б дізнатися, які успішні ігри використовували для обробки різних співвідношень сторін на iOS та Android, не роблячи мільйонів активів різного розміру.

Я строго кажучи мобільний, а не робочий стіл, спеціально з Unity, і мене не цікавить інтерфейс, я дбаю тільки про геймплейне полотно.

Я маю на увазі питання, коли є ключові речі, які повинні бути в певних місцях і не можуть впасти з екрана. Використання чорних смуг вгорі або внизу неприйнятно в ці дні.


3
Це питання дуже широке, оскільки правильний шлях залежить майже від усього. Що ви пробували? Чому це не вийшло?
Анко

3
Я пробував всілякі речі, я намагався регулювати розмір орто камери, я намагався приєднати до списку всі спрайти та змінити їх масштаб за різницею у співвідношенні сторін, встановивши розмір орто на екран. Висота / 2/100, багато інших ідеї. Деякі працюють, але всі вони мають проблеми. Я знаю, що різні ігри обробляють її по-різному, але немає абсолютно жодної дискусії на цю тему ніде, і це не так просто, як "просто дозволити єдності впоратися", як стверджують багато хто.
Майкл

1
Отже, чому вони не працювали? Як виглядатиме хороше рішення? (До речі, ви можете відредагувати питання і для уточнення.)
Анко

7
Деякі спотворювали зображення, деякі не вирівнювались правильно. Багато різних питань, але 65% ігор, розроблених з Unity, - це 2D, і вони змусили її працювати. Я просто хочу знати, чим користуються люди, і не потрібно винаходити колесо. Ніхто не говорить про це, і немає посібників і документів, як з цим впоратися. Тим не менш, ви не можете далеко в мобільному проекті, не маючи системи для цього.
Майкл

1
"Я маю на увазі проблеми, коли є ключові речі, які повинні бути в певних місцях і не можуть впасти з екрана. Використання чорних смуг вгорі або внизу неприйнятно в наші дні". Гарантія того, що елементи не відпадають від екрану, нульові спотворення, але не мають букв / стовпів (чорні смуги тощо). Ці вимоги непримиренні. Остання вимога, мабуть, є найменш важливою, або її можна приховати, висунувши полотно поза тим, що має бути на екрані. Більшість ігор, які я бачив з такими суворими вимогами, будуть прикрашені стовпчиками / бордюрами.
Jibb Smart

Відповіді:


36

Що ви хочете, це обмежити вікно перегляду камери на портрет або пейзаж (залежно від ваших потреб), обчислюючи camera.orthographicSizeвластивості, щоб ви могли побудувати свою 2d сцену незалежно від співвідношення сторін та роздільної здатності:

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

Якщо вам потрібна додаткова інформація про це, будь ласка, запитайте, і я відповім. ;) З повагою та ура.

ОНОВЛЕННЯ: Використовуйте сценарій фіксації об'єктів Еліота Лаша разом з цим, щоб розмістити об'єкти в ключових положеннях на екрані, якщо це необхідно (щодо кутів / меж екрану). Якщо це зробити, перейменуйте "CameraFit" на "ViewportHandler".

Попередній перегляд моделювання екранів різних пропорцій: введіть тут опис зображення


4
@Eliot Додано ліцензію MIT вище. Успіхів у ваших проектах!
androidu

7
Фантастично, дякую! Один хороший поворот заслуговує на інший, тому ось компонент з відкритим кодом, який я щойно написав для простого прив’язування GameObjects до помічників, визначених вашим сценарієм: gist.github.com/fadookie/256947788c364400abe1
Eliot

1
MarcelCăşvan Дуже приємний сценарій! Я додав перерахунок для вибору, якщо ви хочете визначити розмір одиниці для портрета для ландшафту (висота / ширина). Просто довелося додати кілька рядків до сценарію, і я використовую GetComponent<Camera>().orthographicSize = UnitSize / 2f;для портрет / визначення одиниць висоти
am_

2
@ MarcelCăşvan чудові речі! Дякую. Я бачу, що змінні ширини пристрою та пристроюHeight з ComputeFunction () не використовуються. Можливо, розгляньте можливість їх видалення.
user2313267

1
CameraAnchor кидає помилку: "CameraFit не визначений у цьому контексті" - Якщо хтось інший знайде цю відповідь пізніше, здається, що "CameraFit" просто перейменовано на "ViewportHandler", оскільки це було спочатку розміщено. Якщо ви просто перейменуєте клас із ViewportHandler назад у CameraFit.
Ленні

5

Зазвичай вам не потрібні різні розміри об’єктів - імпортовані текстури та спрайти з автоматично згенерованими картами mip виглядатимуть добре, якщо вони будуть надані будь-якого розміру, меншого або рівного початкового розміру пікселя зображення.

Макет сцени - це виклик. Один з хороших підходів полягає в наступному (і FYI я використовую 3D-камеру, дивлячись на 2D-вміст, розташований на z = 0):

  1. Довільно вирішуйте про мінімальний "логічний" розмір дисплея або в пікселях, або в плитках. Це не повинно відповідати жодній реальній роздільній здатності, але воно повинно відображати вузьке / найкоротше співвідношення сторін, яке ви хочете підтримати. Наприклад, для пейзажної гри я б не вибрав 480x320, оскільки це ширше співвідношення сторін, ніж iPad. Тож я можу вибрати 1024x768 - або навіть 480x360, що дає мені оригінальну систему координат розміру iPhone для роботи та таке ж співвідношення сторін, як і кожен iPad (включаючи iPad Air 2 тощо). Також зауважте, що ви можете так само легко працювати в координатах плиток, а не в піксельних координатах - наприклад, 15x11.25.
  2. Програмуйте свою логіку гри так, щоб усе важливе розміщувалося в межах вашого мінімального розміру дисплея, але будьте готові заповнити додатковий простір з боків додатковим вмістом, навіть якщо це лише декоративна наповнювач.
  3. Визначте, скільки потрібно для масштабування вмісту, щоб ширина або висота відповідали мінімальному значенню, а інша вісь була більшою або дорівнює мінімально необхідній. Для цього "масштаб підходить", розділіть розмір пікселя екрана на мінімальний розмір дисплея і візьміть менші з отриманих значень шкали як загальну шкалу перегляду.
  4. Використовуйте шкалу перегляду для обчислення ефективного (фактичного) розміру відображення для логічних ігор.
  5. Насправді масштабуйте вміст, переміщуючи камеру по осі Z.

У формі коду:

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

Якщо ви вирішите скористатись барами, це насправді досить просто здійснити (я публікую це, навіть якщо ОП заявила, що це є неприйнятним, оскільки це має перевагу бути не настільки поганим на мобільному, і це просте рішення, яке не вимагає жодного коду)

Camera.orthographicSize- це змінна в межах ортокамери (яку використовують більшість 2D-ігор), яка відповідає розміреній кількості ігрових одиниць вертикально на екрані ( розділеній на 2 ) ( джерело ). Таким чином, виберіть співвідношення сторін, яке відповідає переважній більшості пристроїв (я вибрав 16: 9, оскільки більшість екранів, які я досліджував, це 16: 9, 16:10, 3: 2) та додайте маску, яка накладає це співвідношення.

Приклад :

У моїй грі (не вказаній тут, оскільки це не реклама, за бажанням можна запитати в коментарях) ми використовуємо портретний режим. Щоб зробити гарне просте 16: 9, я зробив свою камеру Ortho розміром 16. Це означає, що камера адаптуватиме 32 ігрових одиниці висоти (у моєму випадку від 16 до -16) у вертикальну частину екрана пристрою.

Потім я розмістив чорні маски з грою між -9 та +9. Voila, екран гри виглядає точно так само на всіх пристроях і трохи худше на пристроях, трохи ширших. У мене абсолютно немає негативних відгуків щодо масок. Щоб зробити пейзаж, просто переверніть ці значення, і тоді ви зробите камеру розміром 9. Змініть значення, щоб вони відповідали тому, що ви вирішили, - це масштаб ігрової одиниці.

Єдине місце, де ми помітили, що чорна смуга помітно відображається, - це на iPad 3: 2. Вже тоді у мене жодних скарг не було.


1

Я роблю це в грі, над якою зараз працюю. У мене фонове зображення розміром 1140x720. Найважливіші біти (ті, які ніколи не повинні бути обрізані) містяться в середній області 960x640. Я запускаю цей код у функції запуску моєї камери:

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

Я також визначаю інші розміри, крім розміру шрифту, для кнопок тощо. Він добре працює на кожному тестовому співвідношенні. Минув час, коли я його встановив, тож я, можливо, пропущу крок. Дайте мені знати, якщо це не спрацює, як очікувалося, і я побачу, якщо я щось залишив.


1

@ Відповідь та код Марселя чудові і допомогли мені зрозуміти, що відбувається. Це остаточна відповідь. Я просто подумав, що хтось може також виявити корисним те, що я в кінцевому підсумку робив для мого конкретного випадку: оскільки я хотів, щоб на екрані завжди було щось дійсно просте, один спрайт, я придумав ці кілька рядків:

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

Я додав це до камери і перетягнув спрайт (це мій фон) до єдиного властивості сценарію. Якщо ви не хочете, щоб чорні смуги (горизонтальні чи вертикальні), ви можете поставити більший фон за цим ...


0

Існує кілька способів вирішити цю проблему, і немає ідеального рішення (принаймні, я ще не знайшов), і тип рішення, з яким ви збираєтесь, сильно залежатиме від типу гри, яку ви розвивається.

Незалежно від того, чим ви займаєтесь, вам слід почати з вибору найменшої можливої ​​роздільної здатності, яку ви хочете підтримати, і створити свої спротиви до цієї резолюції. Тож якщо ви зацікавлені в розробці для iOS, згідно http://www.iosres.com/, найнижча роздільна здатність пристрою iOS становить 480x320.

Звідти ви можете почати масштабувати спрайт, щоб відповідати більш високим дозволам. Застереження до цього полягає в тому, що ви, зрештою, почнете помічати, що спрайти починають розмиватися далі в масштабі, і в цьому випадку ви можете перейти на інший набір спрайтів, побудований для більш високої роздільної здатності.

Або ви можете повністю ігнорувати масштабування і просто вирішити відображати більше екрану гри для отримання більш високої роздільної здатності (я вважаю, що так це робить Terraria, наприклад). Однак для багатьох ігор це не підходить; конкурентні ігри, наприклад.

Використання чорних смуг вгорі або внизу неприйнятно в ці дні.

Є це? Дуже багато ігор, які хочуть примусити співвідношення сторін 4: 3. Оскільки ви використовуєте Unity, ви можете скористатися сценарієм AspectRatioEnforcer, щоб допомогти у цьому.


Я націлений на мобільний телефон, тому не можу змінити співвідношення сторін чи роздільну здатність. Використання активів низької роздільної здатності не є прийнятним рішенням. У деяких іграх (особливо в 3D) це не проблема, ви просто показуєте більше або менше. Але такі ігри, як Kingdom Rush, захист вежі та інші ігри, такі як Alex, ви хочете бачити те саме, незалежно від пристрою. Якщо все не відображається в потрібних місцях, гра не працюватиме належним чином.
Майкл


0

Існує кілька способів вирішити це питання, це залежить від вашої гри та того, що буде найкраще працювати. Наприклад, у нашій грі Tyrant Unleashed ми просто склали широкі карти з неважливою деталізацією з боків, щоб добре було відрізати сторони на більш вузьких пристроях. Однак інші ігри можуть бути кращими з підходом, коли ви фактично зміщуєте кнопки навколо чи щось, щоб краще підходити до екрана.

(Також частиною нашого підходу є також збереження постійної висоти на всіх пристроях, лише змінюючи ширину. Це, безумовно, полегшує нам життя, але знову ж таки це може бути або не корисно для вашої конкретної гри. Це не має значення в наш стиль мистецтва, якщо зображення трохи масштабуються на різних екранах, тоді як це може мати значення для щось подібне до піксельного мистецтва. В основному, це підхід "хай Unity впорається з цим")


Ви робили якісь проекти, де це не було варіантом? Практично всі ігри в стилі оборони вежі, які я бачив, і в багатьох інших стилях ви можете бачити весь вигляд гри на пристрої без прокрутки, і це відповідає всім пристроям. На IOS ви можете заробляти активи та обмінюватись ними, але це стає неможливим (і все-таки просто великим PITA) на Android.
Майкл

Ні, я ні. btw Я тільки що додав ще детальну інформацію про розмір екрана
jhocking

0

Я використовую наступний скрипт, який додає targetAspectпараметр до камери та адаптує його orthographicSizeвідповідно до співвідношення екрана (детальніше в цій публікації блогу ):

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

Мій метод здебільшого схожий на рішення, які дають інші :) Я спробую детально пояснити підхід, який я використовую, щоб гра не залежала від розміру екрана.

Екранна орієнтація

Залежно від орієнтації екрана (Пейзаж або Портрет), вам слід врахувати, чи буде фотокамера масштабуватися з фіксованою висотою або фіксованою шириною. Здебільшого я вибираю фіксовану ширину для ігор, орієнтованих на пейзаж, і фіксовану висоту для ігор, орієнтованих на портрет.

Масштабування камери

Як обговорювалося, це може бути як фіксованої висоти, так і фіксованої ширини.

Фіксована висота : вертикальна область гри завжди буде відповідати висоті екрану. І коли зміна співвідношення екрана змінюватиметься додаткове місце ліворуч та праворуч від екрана. Для цього вам не потрібно нічого кодувати, це поведінка камери єдності за замовчуванням.

Фіксована ширина : Горизонтальна область гри завжди буде відповідати ширині екрану. І додаткове місце додаватиметься вгорі та внизу, оскільки зміна співвідношення сторін екрана. Для цього вам потрібно написати невеликий фрагмент коду. Згодом переконайтесь, що ви видалили функцію оновлення кодової форми та помістили її у стан.

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

У редакторі ви можете змінити targetWidth, щоб визначити область світового простору, яку ви хочете відобразити. Цей код пояснюється у наступному відео разом із багатьма іншими практиками щодо 2D ігор :)

Об'єднайте 2014 - 2D кращі практики в єдності

Співвідношення сторін

Наступне співвідношення сторін, перелічене від найширшого до самого вузького, охоплює майже всі розміри екрана як для android, так і для iOS

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

Зазвичай я встановлюю всі ці пропорції в заданому порядку під вікном гри, оскільки це зручно під час тестування на різні розміри екрана :)

Площа, що витрачається

Це область, яка додається до екрана в сторони або вгору / внизу залежно від обраного вами масштабування камери.

Для фіксованої висоти бажано, щоб всі ігрові елементи розміщувались у співвідношенні 16: 9, яке є найвужчим. А фон повинен подовжуватися, поки він не охоплює співвідношення 5: 4. Це гарантує, що у вашій грі ніколи немає чорних смужок в сторони.

Для фіксованої ширини вона майже однакова, але тут елементи повинні відповідати співвідношенню 5: 4, а БГ повинен подовжуватися до 16: 9.

Межі

Іноді ми не можемо використати підхід, що витрачається на область, оскільки нам потрібно використовувати весь доступний екран для гри.

Наприклад, розглянемо портретну гру з фіксованою висотою, ловлячи монети, що падають з неба. У цьому нам потрібно дати можливість гравцеві рухатися горизонтально по доступній ширині екрана.

Отже, нам потрібні межі камери з точки зору світових координат, щоб знати, де саме ліворуч, праворуч, верхній або нижній частині камери на світовому положенні.
Ми також можемо використовувати ці межі для прив’язки ігрових елементів або інтерфейсу користувача до потрібної сторони камери.

Використовуючи Camera.ViewportToWorldPoint, ми можемо отримати межі. Простір перегляду в порталі нормалізується і відносно камери. У нижній лівій частині камери розмір (0,0); праворуч вгорі (1,1). Позиція z знаходиться у світових одиницях від камери. Для 2D / ортографічного z не має значення.

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

Для користувальницького інтерфейсу ми можемо застосувати ті самі поняття, які використовувались для ігрових елементів. Після введення інтерфейсу Unity5 та наявності плагінів типу NGUI це не складе особливих проблем :)


0

Я створив Unity Asset 'Resolution Magic 2D', щоб вирішити цю саму проблему (оголошення: ви можете отримати її в магазині Unity Asset Store або переглянути докладнішу інформацію на grogansoft.com).

Я вирішував проблему таким чином:

Визначте область екрана, яка завжди повинна бути видимою незалежно від співвідношення сторін / роздільної здатності, і використовуйте просте перетворення прямокутника, щоб "трафарет" вийшов з цього регіону. Це ваша ідеальна форма екрану. За допомогою простого алгоритму я збільшую камеру до тих пір, поки область, заблокована прямокутником, не стане максимально великою, поки все ще є 100% видимою для камери.

Тоді ваша основна ігрова область завжди займає якомога більше екрану. І поки існує достатній "додатковий" вміст (наприклад, ваш фон) за межами прямокутника, який ви визначили раніше, гравці, екрани яких не мають такого ж співвідношення сторін, як ваш "ідеальний" прямокутник, побачать додатковий вміст там, де чорні смуги інакше йти.

Мій актив також включає певну логіку розміщення інтерфейсу користувача, але це в основному застаріло завдяки новій системі інтерфейсу Unity.

Мій актив надає це з коробки з мінімальними налаштуваннями, і це працює дуже добре на всіх платформах.

Якщо ви користуєтеся цією технікою (або моїм активом), просто переконайтеся, що ви розробили гру, щоб мати "необов'язковий" простір навколо, щоб розмістити екрани, ширші або вище, ніж ваш ідеал (щоб уникнути чорних смуг).

Я особисто не роблю 3D-ігри, тож не знаю, чи це працювало б у 3D (чи це навіть потрібно).

Це неможливо пояснити без малюнків, тому, будь ласка, відвідайте мій веб-сайт ( Resolution Magic 2D )


0

Найкращим рішенням для мене є використання теореми про пересічні лінії, щоб не було ні відрізаного боку, ні спотворення ігрового виду. Це означає, що вам потрібно відступити назад або вперед залежно від різного співвідношення сторін.


-3

Я створив розширення AssetStore, яке дозволяє легше перемикати аспекти під назвою AspectSwitcher . Він забезпечує систему, що дозволяє вам легко вказувати різні властивості для різних аспектів. Зазвичай існує два способи, якими користується більшість людей для переключення аспектів. Одне полягає у наданні різних ігрових об’єктів для кожного аспекту. Інша полягає у створенні спеціального коду, який модифікує властивості одного ігрового об'єкта на основі поточного аспекту. Для загального кодування потрібно багато. Моє розширення намагається полегшити багато цього болю.


2
Ця відповідь була б кращою і здавалася б менш спам-фальшивою, якби ви детальніше розглядали фактичні методи, які можна використовувати для вирішення питання ОП.
Джош
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.