Unity 2D와의 종횡비 차이를 어떻게 처리합니까?


67

나는이 질문에 많은 답변을 얻었지만 그것들은 모두 일반적이며별로 유용하지 않습니다. 튜토리얼 중 어떤 것도 종횡비와 모바일 장치 처리에 대해 이야기하지 않으며 그것을 수행하는 방법이 있습니다. 모두가 가지고 있고 결함이있는 것 같습니다.

나는 거대한 크기의 자산을 만들지 않고 iOS와 Android에서 다양한 종횡비를 처리하는 데 성공한 게임이 무엇인지 알고 싶습니다.

나는 특히 Unity를 사용하여 데스크탑이 아닌 모바일로 엄격히 말하고 있으며 UI에 신경 쓰지 않고 게임 플레이 캔버스에만 신경 쓰고 있습니다.

내가 염두에두고있는 문제는 특정 장소에 있어야하고 화면에서 떨어질 수없는 주요 사항이있을 때입니다. 요즘에는 위나 아래에 검은 막대를 사용하는 것은 허용되지 않습니다.


3
올바른 방법은 거의 모든 것에 달려 있기 때문에이 질문은 매우 광범위합니다. 무엇을 시도 했습니까? 왜 작동하지 않습니까?
Anko

3
나는 모든 종류의 일을 시도하고, 직교 카메라 크기를 조정하려고 시도했으며, 모든 스프라이트를 첨부하고 종횡비의 차이에 따라 목록을 조정하고 화면에 수직 크기를 설정하려고 시도했습니다. 아이디어. 일부는 효과가 있지만 모두 문제가 있습니다. 나는 다른 게임이 그것을 다르게 취급한다는 것을 알고 있지만 어디에서 나이 주제에 대한 토론은 없으며, 많은 사람들이 주장하는 것처럼 "단일성을 처리하게하는 것"만큼 쉽지 않습니다.
Michael

1
그래서 그들은 왜 작동하지 않았습니까? 좋은 해결책은 무엇입니까? (그런 식으로, 당신은 명확하게 질문을 편집 할 수 있습니다.)
Anko

7
일부는 이미지를 왜곡하고 일부는 올바르게 정렬되지 않았습니다. 여러 가지 다른 문제가 있지만 Unity로 개발 된 게임의 65 %는 2D이며 작동합니다. 나는 사람들이 무엇을 사용하고 있는지 알고 싶어하며 바퀴를 재발 명 할 필요가 없습니다. 아무도 그것에 대해 이야기하지 않으며 그것을 다루는 방법에 대한 가이드 나 문서가 없습니다. 그러나 시스템을 갖추지 않고도 모바일 프로젝트를 시작할 수는 없습니다.
Michael

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

이에 대한 추가 정보가 필요하면 문의하십시오. 답장을 드리겠습니다. ;) 안부와 환호.

UPDATE : 사용 엘리엇 래쉬의 객체가 스크립트를 고정 (모서리 / 테두리를 화면에 상대적으로) 필요한 경우 화면에 키 위치에 물건을 올려이 하나와 함께. 그렇게하면 "CameraFit"의 이름을 "ViewportHandler"로 바꾸십시오.

다양한 종횡비 화면을 시뮬레이트하는 미리보기 : 여기에 이미지 설명을 입력하십시오


4
@Eliot 위의 MIT 라이센스를 추가했습니다. 프로젝트와 함께 행운을 빕니다!
androidu

7
환상적입니다, 감사합니다! 하나의 좋은 차례는 다른 하나의 가치가 있으므로 여기에 스크립트로 정의 된 도우미 지점에 GameObjects를 간단하게 고정하기 위해 작성한 오픈 소스 구성 요소가 있습니다. gist.github.com/fadookie/256947788c364400abe1
Eliot

1
MarcelCăşvan 아주 멋진 스크립트! 가로 방향의 세로 크기 (높이 / 폭)를 정의하려는 경우 선택하기위한 열거 형을 추가했습니다. 그냥 스크립트에 몇 줄을 추가했고, 내가 사용하는 GetComponent<Camera>().orthographicSize = UnitSize / 2f;높이 단위를 정의 / potrait의 위해
AM_

2
@ MarcelCăşvan 좋은 물건! 감사. ComputeFunction ()의 deviceWidth 및 deviceHeight 변수가 사용되지 않는 것으로 나타났습니다. 아마도 이것들을 삭제하는 것을 고려하십시오.
user2313267

1
CameraAnchor에서 "CameraFit이이 컨텍스트에서 정의되지 않았습니다"라는 오류가 발생합니다. 나중에 다른 사람이이 답변을 찾은 경우 원래 게시 된 이후 "CameraFit"의 이름이 "ViewportHandler"로 변경된 것 같습니다. 클래스 이름을 ViewportHandler에서 CameraFit으로 다시 바꿉니다.
Lenny

5

일반적으로 다른 크기의 자산이 필요하지 않습니다. 자동 생성 된 밉 맵이있는 가져온 텍스처와 스프라이트는 이미지의 원래 픽셀 크기보다 작거나 같은 크기로 렌더링 할 때 멋지게 보입니다.

장면 레이아웃이 도전입니다. 한 가지 좋은 접근 방식은 다음과 같습니다 (그리고 참고로 z = 0에 위치한 2D 컨텐츠를 보는 3D 카메라를 사용합니다).

  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

막대를 사용하는 경우 실제로 구현하는 것이 매우 간단합니다 (OP가 모바일에 나쁘지 않다는 이점이 있기 때문에 OP가 허용 할 수 없다고 의견을 밝혔지만 게시하고 있지만 간단한 해결책입니다. 코드가 필요하지 않습니다)

Camera.orthographicSize는 측정 된 게임 단위의 양을 화면에 수직으로 맞추는 직교 카메라 (대부분의 2D 게임에서 사용) 내의 변수입니다 ( 2로 나눈 값 ( source )). 따라서 대부분의 장치에 맞는 종횡비를 선택하고 (내가 조사한 대부분의 화면이 16 : 9, 16:10, 3 : 2이므로 16 : 9를 선택했습니다) 비율로 오버레이하는 마스크를 추가하십시오.

:

내 게임에서 (이것은 광고가 아니므로 여기에 나열되어 있지 않으며, 원하는 경우 의견을 요청할 수 있습니다) 세로 모드를 사용합니다. 16 : 9 크기로 멋진 Ortho 카메라를 만들었습니다. 이것은 카메라가 장치의 화면 수직에 32 게임 높이 (y : 16 ~ -16)를 적용한다는 의미입니다.

그런 다음 -9에서 +9 사이의 게임으로 검은 마스크를 배치했습니다. 게임 화면 인 Voila는 모든 기기에서 똑같이 보이고 약간 더 넓은 기기에서는 조금 더 얇아 보입니다. 마스크에 관한 부정적인 피드백은 전혀 없었습니다. 가로 방향으로 그 값을 뒤집기 만하면 크기가 9 인 카메라를 만들 수 있습니다. 결정한대로 게임 단위 스케일에 맞게 값을 변경하십시오.

검은 막대가 크게 나타나는 것을 관찰 한 유일한 장소는 3 : 2의 iPad입니다. 그래도 불만은 없었습니다.


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

@Marcel의 답변과 코드는 훌륭하고 무슨 일이 일어나고 있는지 이해하는 데 도움이되었습니다. 정답입니다. 누군가가 내 특정 사례에 대해 내가 끝낸 일을 유용하게 생각할 수 있다고 생각했습니다. 정말 간단한 무언가를 원했기 때문에 하나의 스프라이트가 항상 화면에 표시되기 때문에 다음 몇 줄을 생각해 냈습니다.

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와 같은 다른 게임은 장치에 관계없이 동일한 것을보고 싶어합니다. 올바른 위치에 표시되지 않으면 게임이 제대로 작동하지 않습니다.
Michael


0

이 문제를 처리하는 방법에는 여러 가지가 있으며, 게임과 가장 잘 작동하는 방법에 따라 다릅니다. 예를 들어, Tyrant Unleashed 게임 에서는 측면에 중요하지 않은 디테일이있는 넓은 맵을 만들었으므로 좁은 장치에서는 측면을 잘라도 괜찮습니다. 그러나 다른 게임은 실제로 버튼을 움직이거나 화면에 더 잘 맞는 방식으로 개선하는 것이 좋습니다.

(또한 우리의 접근 방식의 일부는 모든 장치에서 일관된 높이를 유지하고 너비 만 변경하는 것입니다. 이는 확실히 우리의 삶을 더 쉽게 만들어 주지만 다시 특정 게임에 좋지 않을 수도 있습니다. 이미지가 다른 화면에서 약간 크기 조정되는 경우 아트 스타일이지만 픽셀 아트와 같은 경우에 중요 할 수 있습니다. 기본적으로 "Unity가 처리하도록"접근 방식입니다.


옵션이 아닌 프로젝트를 수행 했습니까? 내가 본 거의 모든 타워 디펜스 스타일 게임과 다른 많은 스타일을 사용하면 스크롤하지 않고도 장치에서 전체 게임 뷰를 볼 수 있으며 이는 여러 장치에서 일관됩니다. iOS에서는 자산을 만들고 스왑 할 수 있지만 Android에서는 불가능합니다 (그리고 실제로는 큰 PITA).
Michael

아뇨 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 게임에 대한 다른 많은 관행과 함께 다음 비디오에서 설명됩니다. :)

Unite 2014-Unity의 2D 모범 사례

종횡비

가장 넓은 화면 비율에서 가장 좁은 화면 비율에 따라 Android 및 iOS의 거의 모든 화면 크기를 커버

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

다른 화면 크기를 테스트하는 동안 편리하기 때문에 일반적으로 게임 창에서 주어진 순서대로 이러한 종횡비를 모두 설정합니다. :)

소모품 영역

선택한 카메라 배율에 따라 화면의 측면 또는 위 / 아래에 추가되는 영역입니다.

고정 된 높이의 경우 모든 게임 요소는 가장 좁은 16 : 9 비율에 맞아야합니다. 그리고 배경은 5 : 4 비율을 커버 할 때까지 확장되어야합니다. 게임의 측면에 검은 색 스트립이 없는지 확인하십시오.

고정 너비의 경우 거의 동일하지만 여기서 요소는 5 : 4 비율에 맞고 BG는 16 : 9까지 확장되어야합니다.

범위

때로는 게임 플레이에 사용 가능한 전체 화면을 사용해야하기 때문에 소모품 영역 접근 방식을 사용할 수없는 경우가 있습니다.

예를 들어, 하늘에서 떨어지는 동전을 잡는 고정 높이의 세로 게임을 생각해보십시오. 여기에서 플레이어가 사용 가능한 화면 너비 위로 가로로 이동할 수 있도록해야합니다.

따라서 월드 좌표에서 카메라의 왼쪽, 오른쪽, 상단 또는 하단이 정확히 어디에 있는지 알기 위해서는 월드 좌표 측면에서 카메라의 경계가 필요합니다.
이 경계를 사용하여 게임 요소 또는 UI를 카메라의 원하는면에 고정 할 수도 있습니다.

Camera.ViewportToWorldPoint를 사용하면 범위를 얻을 수 있습니다. 뷰포트 공간은 정규화되고 카메라를 기준으로합니다. 카메라의 왼쪽 하단은 (0,0)입니다. 오른쪽 상단은 (1,1)입니다. z 위치는 카메라에서 월드 단위입니다. 2D / orthographic의 경우 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

UI의 경우 게임 요소에 사용한 것과 동일한 개념을 적용 할 수 있습니다. Unity5 UI를 소개하고 NGUI와 같은 플러그인을 사용할 수있게되면 문제가되지 않습니다. :)


0

이 문제를 해결하기 위해 Unity Asset 'Resolution Magic 2D'를 만들었습니다 (ad : Unity Asset Store에서 가져 오거나 grogansoft.com에서 자세한 내용을 볼 수 있음).

내가 문제를 해결하는 방법은 다음과 같습니다.

화면비 / 해상도에 관계없이 항상 볼 수있는 화면 영역을 정의하고 간단한 사각형 변환을 사용하여이 영역을 '스텐실 아웃'하십시오. 이상적인 화면 모양입니다. 그런 다음 간단한 알고리즘을 사용하여 사각형으로 차단 된 영역이 가능한 한 100 % 커질 때까지 카메라를 확대 / 축소합니다.

그러면 주 게임 영역은 항상 가능한 한 많은 화면을 차지합니다. 이전에 정의한 사각형 영역 외부에 충분한 '추가'콘텐츠 (예 : 배경)가있는 한 화면이 '이상적'사각형과 동일한 종횡비가 아닌 플레이어는 검은 막대가 그렇지 않은 경우 추가 콘텐츠를 볼 수 있습니다. 가다.

내 자산에는 UI를 배치하기위한 논리가 포함되어 있지만 Unity의 새로운 UI 시스템으로 인해 더 이상 사용되지 않습니다.

내 자산은 최소한의 설정으로 즉시 제공되며 모든 플랫폼에서 실제로 잘 작동합니다.

이 기술 (또는 내 자산)을 사용하는 경우 이상적인 것보다 넓거나 큰 화면을 수용 할 수 있도록 '선택적'공간을 갖도록 게임을 디자인해야합니다 (검은 색 막대를 피하기 위해).

나는 개인적으로 3D 게임을 만들지 않기 때문에 이것이 3D로 작동하는지 (또는 필요한 경우) 알 수 없습니다.

사진 없이는 설명하기가 어렵 기 때문에 내 웹 사이트를 방문하십시오 ( Resolution Magic 2D )


0

나를위한 가장 좋은 해결책은 교차 선의 정리를 사용하여 측면이 잘 리거나 게임 뷰가 왜곡되지 않도록하는 것입니다. 이는 다른 종횡비에 따라 뒤로 또는 앞으로 이동해야 함을 의미합니다.


-3

나는라고 쉽게 화면 전환을 허용하는 AssetStore 확장 생성 AspectSwitcher을 . 다양한 측면에 대해 다른 속성을 쉽게 지정할 수있는 시스템을 제공합니다. 일반적으로 대부분의 사람들이 측면을 전환하는 데 사용하는 두 가지 방법이 있습니다. 하나는 각 측면마다 다른 게임 오브젝트를 제공하는 것입니다. 다른 하나는 현재 측면을 기반으로 단일 게임 오브젝트의 속성을 수정하는 사용자 지정 코드를 만드는 것입니다. 일반적으로 많은 사용자 지정 코딩이 필요합니다. 내 확장은 그 많은 고통을 완화하려고 시도합니다.


2
OP의 질문을 해결하는 데 사용할 수있는 실제 기술에 대해 자세히 설명하면이 대답이 더 좋으며 덜 스팸처럼 보입니다.
Josh
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.