Как вы справляетесь с различиями пропорций в Unity 2D?

67

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

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

Я, строго говоря, мобильный, а не настольный компьютер, особенно с Unity, и меня не волнует интерфейс, меня интересует только игровой холст.

Проблемы, которые я имею в виду, это когда есть ключевые вещи, которые должны быть в определенных местах и ​​не могут выпасть из экрана. Использование черных полос сверху или снизу недопустимо в наши дни.

Майкл
источник
3
Этот вопрос очень широк, так как правильный путь зависит почти от всего. Что вы пробовали? Почему это не сработало?
Анко
3
Я пробовал все виды вещей, я пытался настроить размер орто-камеры, я пытался прикрепить все спрайты к списку и масштабировать их по разнице в соотношении сторон, установить орто-размер на screen.height / 2/100, многие другие идеи. Некоторые работают, но у всех есть проблемы. Я знаю, что в разных играх все по-разному, но эта тема нигде не обсуждается, и это не так просто, как «просто позволить единству справиться с этим», как утверждают многие.
Майкл
1
Итак, почему они не работают? Как будет выглядеть хорошее решение? (Кстати, вы можете отредактировать вопрос, чтобы уточнить тоже.)
Anko
7
Некоторые искажали изображения, некоторые неправильно выстраивались. Много разных проблем, но 65% игр, разработанных с Unity, являются 2D, и они заставили его работать. Я просто хочу знать, что люди используют, и не нужно изобретать велосипед. Никто не говорит об этом, и нет никаких руководств или документов о том, как справиться с этим. Тем не менее, вы не сможете продвинуться далеко в мобильном проекте, если у вас не будет системы для этого.
Майкл
1
«Проблемы, которые я имею в виду, это когда есть ключевые вещи, которые должны быть в определенных местах и ​​не могут выпасть из экрана. Использование черных полос сверху или снизу недопустимо в наши дни». Гарантия того, что элементы не упадут с экрана, не будут искажаться, но не будут помечены буквами / столбами (черные полосы и тому подобное). Эти требования несовместимы. Последнее требование, вероятно, наименее важно, или его можно скрыть, добавив холст за пределы того, что должно быть на экране. Большинство игр, которые я видел с такими строгими требованиями, будут украшены рамками / рамками.
Jibb Smart

Ответы:

36

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

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

Если вам нужна дополнительная информация по этому вопросу, пожалуйста, спросите, и я отвечу. ;) С уважением и ура.

ОБНОВЛЕНИЕ: используйте скрипт привязки объектов Eliot Lash вместе с этим, чтобы при необходимости размещать объекты на ключевых позициях на экране (относительно углов / границ экрана). Если вы это сделаете, переименуйте «CameraFit» в «ViewportHandler».

Предварительный просмотр, имитирующий различные форматы экрана: введите описание изображения здесь

androidu
источник
4
@Eliot Добавлена ​​лицензия MIT выше. Удачи в ваших проектах!
Android
7
Фантастика, спасибо! Один хороший поворот заслуживает другого, поэтому вот компонент с открытым исходным кодом, который я только что написал для простой привязки GameObjects к вспомогательным точкам, определенным вашим сценарием: gist.github.com/fadookie/256947788c364400abe1
Eliot
1
MarcelCăşvan Очень хороший сценарий! Я добавил перечисление для выбора, если вы хотите определить размер блока для портрета для ландшафта (высота / ширина). Просто нужно было добавить пару строк в сценарий, и я использую GetComponent<Camera>().orthographicSize = UnitSize / 2f;для портрета / определения единиц высоты
am_
2
@ MarcelCăşvan отличные вещи! Благодарю. Я вижу, что переменные deviceWidth и deviceHeight из ComputeFunction () не используются. Возможно, рассмотрите возможность удаления этих.
user2313267
1
CameraAnchor выдает ошибку: «CameraFit не определен в этом контексте» - в случае, если кто-то еще найдет этот ответ позже, кажется, что «CameraFit» просто переименовал в «ViewportHandler», так как это было первоначально опубликовано. Если вы просто переименуете класс из ViewportHandler обратно в CameraFit.
Ленни
5

Как правило, вам не нужны разные размеры ресурсов - импортированные текстуры и спрайты с автоматически сгенерированными картами MIP будут хорошо смотреться при рендеринге с любым размером, меньшим или равным исходному размеру пикселя изображения.

Макет сцены является проблемой. Один хороший подход заключается в следующем (и к вашему сведению я использую 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
AbePralle
источник
2

Если вы прибегаете к использованию баров, то на самом деле это довольно просто реализовать (я публикую это, хотя ФП высказал мнение, что это неприемлемо, потому что он имеет преимущество, заключающееся в том, что он не так уж плох на мобильных устройствах, и это простое решение, которое не требует никакого кода вообще)

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

Пример :

В моей игре (не перечисленной здесь, так как это не реклама, можете попросить в комментариях при желании) мы используем портретный режим. Чтобы сделать простое 16: 9, я сделал свою камеру Ortho размером 16. Это означает, что камера будет приспосабливать 32 игровые единицы высоты (у: 16-16 в моем случае) к вертикали экрана устройства.

Затем я поместил черные маски с игрой между -9 и +9. Вуаля, экран игры выглядит одинаково на всех устройствах и немного тоньше на устройствах, которые немного шире. У меня не было абсолютно никаких отрицательных отзывов относительно масок. Для создания пейзажа просто переверните эти значения, и тогда вы сделаете камеру размером 9. Измените значения так, чтобы они соответствовали тому, что вы решили в соответствии с масштабом вашей игровой единицы.

Единственное место, где мы наблюдали черную полосу, - 3: 2 на iPad. Даже тогда у меня не было жалоб.

McAden
источник
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;
    }
}

Я добавил это в камеру и перетащил свой спрайт (это мой фон) в единственное свойство скрипта. Если вам не нужны чёрные полосы (горизонтальные или вертикальные), вы можете поставить больший фон за этим ...

maltalef
источник
0

Есть несколько способов решения этой проблемы, и не существует идеального решения (по крайней мере, я его еще не нашел), и тип используемого вами решения будет сильно зависеть от типа игры, в которой вы находитесь. разработки.

Независимо от того, что вы делаете, вы должны начать с выбора минимально возможного разрешения, которое вы хотели бы поддерживать, и построить свои спрайты для этого разрешения. Так что если вы заинтересованы в разработке для iOS, то, согласно http://www.iosres.com/, самое низкое разрешение устройства iOS - 480x320.

Оттуда вы можете начать увеличивать спрайты до более высоких разрешений. Предостережение заключается в том, что в конечном итоге вы начнете замечать, что спрайты начинают размываться по мере увеличения масштаба, и в этом случае вы можете переключиться на другой набор спрайтов, созданный для более высоких разрешений.

Или вы можете полностью игнорировать масштабирование и просто решить отображать больше игрового экрана для более высоких разрешений (я полагаю, именно так Terraria делает это, например). Однако для многих игр это не подходит; соревновательные игры например.

Использование черных полос сверху или снизу недопустимо в наши дни.

Это? Многие игры, которые хотят использовать соотношение сторон 4: 3, делают это. Поскольку вы используете Unity, вы можете использовать скрипт AspectRatioEnforcer, чтобы помочь в этом.

бондарь
источник
Я ориентируюсь на мобильные устройства, поэтому не могу изменить соотношение сторон или разрешение. Использование активов с низким разрешением не является приемлемым решением. В некоторых играх (особенно в 3D) это не проблема, вы просто показываете более или менее. Но в таких играх, как Kingdom Rush, Tower Defense и другие игры, такие как Alex, вы хотите видеть одно и то же независимо от устройства. Если вещи не отображаются в нужных местах, игра не будет работать должным образом.
Майкл
0

Есть несколько способов решения этой проблемы, это зависит от вашей игры и того, что будет работать лучше всего. Например, в нашей игре Tyrant Unleashed мы просто делали широкие карты с неважной детализацией по бокам, чтобы можно было обрезать стороны на более узких устройствах. Однако другие игры могут быть лучше с подходом, в котором вы фактически перемещаете кнопки или что-то, чтобы лучше соответствовать экрану.

(Также частью нашего подхода является поддержание постоянной высоты на всех устройствах, только изменяя ширину. Это, безусловно, облегчает нам жизнь, но, опять же, это может или не может быть полезным для вашей конкретной игры. Это не имеет значения в наш художественный стиль, если изображения немного масштабируются на разных экранах, в то время как это может иметь значение для чего-то вроде пиксельной графики. По сути, это подход «пусть Unity справится с этим»)

jhocking
источник
Вы делали какие-либо проекты, где это было невозможно? Почти во всех играх в стиле Tower Defense, которые я видел, и во многих других стилях вы можете видеть весь игровой вид на устройстве без прокрутки, и это одинаково для всех устройств. На IOS вы можете создавать активы и менять их местами, но это становится невозможным (и в любом случае просто большим PITA) на Android.
Майкл
Нет, не имею Кстати, я только добавил более подробную информацию о размере экрана
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;
        }
    }
}
sdabet
источник
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-игр :)

Unite 2014 - 2D лучшие практики в Unity

Соотношение сторон

Следующее соотношение сторон, перечисленное от самого широкого до самого узкого, охватывает практически все размеры экрана как для Android, так и для iOS

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

Я обычно устанавливаю все эти пропорции в заданном порядке под окном игры, так как это удобно при тестировании на экранах разных размеров :)

Расходная область

Это область, которая добавляется на экран по бокам или сверху / снизу в зависимости от выбранного вами масштаба камеры.

Для фиксированной высоты все игровые элементы должны предпочтительно соответствовать соотношению 16: 9, которое является самым узким. И фон должен расширяться до 5: 4. Что гарантирует, что ваша игра никогда не имеет черных полос по бокам.

Для фиксированной ширины это почти то же самое, но здесь элементы должны соответствовать соотношению 5: 4, а BG должен быть увеличен до 16: 9.

Bounds

Иногда мы не можем использовать подход с использованием расходных площадей, поскольку нам нужно использовать весь доступный экран для игры.

Например, рассмотрим портретную игру с фиксированной высотой, ловящую монеты, падающие с неба. В этом нам нужно дать игроку возможность перемещаться горизонтально по доступной ширине экрана.

Следовательно, нам нужны границы камеры в терминах мировых координат, чтобы знать, где именно слева, справа, сверху или снизу камеры закрепляются на мировой позиции.
Мы также можем использовать эти границы для привязки игровых элементов или пользовательского интерфейса к желаемой стороне камеры.

Используя Camera.ViewportToWorldPoint, мы можем получить границы bounds.Viewport по отношению к камере. Нижний левый угол камеры (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 UI и наличия плагинов, таких как NGUI, это не будет большой проблемой :)

Хэш-буй
источник
0

Я создал Unity Asset 'Resolution Magic 2D', чтобы решить эту проблему (объявление: вы можете получить его в Unity Asset Store или узнать подробности на grogansoft.com).

Я решил эту проблему следующим образом ...

Определите область экрана, которая всегда должна быть видимой независимо от соотношения сторон / разрешения, и используйте простое преобразование прямоугольника, чтобы «растянуть» эту область. Это ваша идеальная форма экрана. Используя простой алгоритм, я затем увеличиваю камеру, пока область, заблокированная прямоугольником, не станет настолько большой, насколько это возможно, и при этом будет на 100% видимой для камеры.

Тогда ваша основная игровая зона всегда занимает как можно больше экрана. И до тех пор, пока имеется достаточно «дополнительного» контента (например, вашего фона) за пределами области прямоугольника, которую вы определили ранее, игроки, чей экран не имеет такое же соотношение сторон, как ваш «идеальный» прямоугольник, будут видеть дополнительный контент, где в противном случае черные полосы были бы идти.

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

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

Если вы используете эту технику (или мой актив), просто убедитесь, что вы разрабатываете свою игру так, чтобы вокруг нее было «дополнительное» пространство для размещения экранов, которые шире или выше вашего идеала (чтобы избежать черных полос).

Я лично не делаю 3D-игры, поэтому я не знаю, будет ли это работать в 3D (или даже если это необходимо).

Без картинок это действительно сложно объяснить, поэтому, пожалуйста, посетите мой сайт ( Resolution Magic 2D )

pumpkinszwan
источник
0

Лучшее решение для меня - использовать теорему о пересекающихся линиях, чтобы не было ни среза по сторонам, ни искажения игрового вида. Это означает, что вы должны сделать шаг назад или вперед в зависимости от разного соотношения сторон.

unityfever
источник
-3

Я создал расширение AssetStore, которое упрощает переключение аспектов под названием AspectSwitcher . Он предоставляет систему, позволяющую легко указывать разные свойства для разных аспектов. Как правило, есть два метода, которые большинство людей используют для переключения аспектов. Одним из них является предоставление различных игровых объектов для каждого аспекта. Другой заключается в создании пользовательского кода, который изменяет свойства одного игрового объекта на основе текущего аспекта. Как правило, это требует много пользовательского кодирования. Мое расширение пытается облегчить эту боль.

Джейсон
источник
2
Этот ответ был бы лучше и казался бы менее спамовым, если бы вы подробно остановились на реальных методах, которые можно использовать для решения вопроса ОП.
Джош