纳金网

标题: Unity3D自适应屏幕方案 [打印本页]

作者: 狂风大尉    时间: 2015-9-30 23:24
标题: Unity3D自适应屏幕方案

如果做手机游戏,必不可少的需要涉及到自适应屏幕这个问题,本篇文章不做过多讲解。直接上代码。

AspectUtility.cs脚本来自网络,因考虑到宽屏和窄屏适应问题,设置一个可调节的区间段会比较好,所以此处做过部分修改。
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEngine;

  4. public class AspectUtility : MonoBehaviour
  5. {
  6.     public Vector2 maxAspectRatio = new Vector2(16, 9);
  7.     public Vector2 minAspectRatio = new Vector2(3, 2);
  8.     public bool landscapeModeOnly = true;

  9.     private float _wantedAspectRatio = 1.5f;
  10.     static public bool _landscapeModeOnly = true;
  11.     static float wantedAspectRatio;
  12.     static Camera cam;
  13.     static Camera backgroundCam;

  14.     void Awake()
  15.     {
  16.         if (Screen.width * maxAspectRatio.y > Screen.height * maxAspectRatio.x)
  17.         {
  18.             _wantedAspectRatio = maxAspectRatio.x / maxAspectRatio.y;
  19.         }
  20.         else if (Screen.width * minAspectRatio.y < Screen.height * minAspectRatio.x)
  21.         {
  22.             _wantedAspectRatio = minAspectRatio.x / minAspectRatio.y;
  23.         }
  24.         else
  25.         {
  26.             _wantedAspectRatio = (float)Screen.width / Screen.height;
  27.         }

  28.         _landscapeModeOnly = landscapeModeOnly;
  29.         cam = camera;
  30.         if (!cam)
  31.         {
  32.             cam = Camera.main;
  33.             Debug.Log("Setting the main camera " + cam.name);
  34.         }
  35.         else
  36.         {
  37.             Debug.Log("Setting the main camera " + cam.name);
  38.         }

  39.         if (!cam)
  40.         {
  41.             Debug.LogError("No camera available");
  42.             return;
  43.         }
  44.         wantedAspectRatio = _wantedAspectRatio;
  45.         SetCamera();
  46.     }

  47.     public static void SetCamera()
  48.     {
  49.         float currentAspectRatio = 0.0f;
  50.         if (Screen.orientation == ScreenOrientation.LandscapeRight ||
  51.             Screen.orientation == ScreenOrientation.LandscapeLeft)
  52.         {
  53.             Debug.Log("Landscape detected...");
  54.             currentAspectRatio = (float)Screen.width / Screen.height;
  55.         }
  56.         else
  57.         {
  58.             Debug.Log("Portrait detected...?");
  59.             if (Screen.height > Screen.width && _landscapeModeOnly)
  60.             {
  61.                 currentAspectRatio = (float)Screen.height / Screen.width;
  62.             }
  63.             else
  64.             {
  65.                 currentAspectRatio = (float)Screen.width / Screen.height;
  66.             }
  67.         }
  68.         // If the current aspect ratio is already approximately equal to the desired aspect ratio,
  69.         // use a full-screen Rect (in case it was set to something else previously)

  70.         Debug.Log("currentAspectRatio = " + currentAspectRatio + ", wantedAspectRatio = " + wantedAspectRatio);

  71.         if ((int)(currentAspectRatio * 100) / 100.0f == (int)(wantedAspectRatio * 100) / 100.0f)
  72.         {
  73.             cam.rect = new Rect(0.0f, 0.0f, 1.0f, 1.0f);
  74.             if (backgroundCam)
  75.             {
  76.                 Destroy(backgroundCam.gameObject);
  77.             }
  78.             return;
  79.         }

  80.         // Pillarbox
  81.         if (currentAspectRatio > wantedAspectRatio)
  82.         {
  83.             float inset = 1.0f - wantedAspectRatio / currentAspectRatio;
  84.             cam.rect = new Rect(inset / 2, 0.0f, 1.0f - inset, 1.0f);
  85.         }
  86.         // Letterbox
  87.         else
  88.         {
  89.             float inset = 1.0f - currentAspectRatio / wantedAspectRatio;
  90.             cam.rect = new Rect(0.0f, inset / 2, 1.0f, 1.0f - inset);
  91.         }
  92.         if (!backgroundCam)
  93.         {
  94.             // Make a new camera behind the normal camera which displays black; otherwise the unused space is undefined
  95.             backgroundCam = new GameObject("BackgroundCam", typeof(Camera)).camera;
  96.             backgroundCam.depth = int.MinValue;
  97.             backgroundCam.clearFlags = CameraClearFlags.SolidColor;
  98.             backgroundCam.backgroundColor = Color.black;
  99.             backgroundCam.cullingMask = 0;
  100.         }
  101.     }

  102.     public static int screenHeight
  103.     {
  104.         get
  105.         {
  106.             return (int)(Screen.height * cam.rect.height);
  107.         }
  108.     }

  109.     public static int screenWidth
  110.     {
  111.         get
  112.         {
  113.             return (int)(Screen.width * cam.rect.width);
  114.         }
  115.     }

  116.     public static int xOffset
  117.     {
  118.         get
  119.         {
  120.             return (int)(Screen.width * cam.rect.x);
  121.         }
  122.     }

  123.     public static int yOffset
  124.     {
  125.         get
  126.         {
  127.             return (int)(Screen.height * cam.rect.y);
  128.         }
  129.     }

  130.     public static Rect screenRect
  131.     {
  132.         get
  133.         {
  134.             return new Rect(cam.rect.x * Screen.width, cam.rect.y * Screen.height, cam.rect.width * Screen.width, cam.rect.height * Screen.height);
  135.         }
  136.     }

  137.     public static Vector3 mousePosition
  138.     {
  139.         get
  140.         {
  141.             Vector3 mousePos = Input.mousePosition;
  142.             mousePos.y -= (int)(cam.rect.y * Screen.height);
  143.             mousePos.x -= (int)(cam.rect.x * Screen.width);
  144.             return mousePos;
  145.         }
  146.     }

  147.     public static Vector2 guiMousePosition
  148.     {
  149.         get
  150.         {
  151.             Vector2 mousePos = Event.current.mousePosition;
  152.             mousePos.y = Mathf.Clamp(mousePos.y, cam.rect.y * Screen.height, cam.rect.y * Screen.height + cam.rect.height * Screen.height);
  153.             mousePos.x = Mathf.Clamp(mousePos.x, cam.rect.x * Screen.width, cam.rect.x * Screen.width + cam.rect.width * Screen.width);
  154.             return mousePos;
  155.         }
  156.     }
  157. }
复制代码
原文:http://wiki.unity3d.com/index.php?title=AspectRatioEnforcer
以上脚本可以实现3D场景的自适应,如果采用NGUI布局UI界面,只需要再进行以下处理即可:
  1. UIRoot root = _uiCamera2D.transform.parent.GetComponent<UIRoot>();
  2.         int height;
  3.         if (AspectUtility.screenWidth * UIConfig.instance.uiSize.y > AspectUtility.screenHeight * UIConfig.instance.uiSize.x)
  4.         {
  5.             height = (int)UIConfig.instance.uiSize.y;
  6.             if (root != null)
  7.             {
  8.                 root.maximumHeight = height;
  9.                 root.minimumHeight = height;
  10.             }
  11.         }
  12.         else
  13.         {
  14.             height = (int)(AspectUtility.screenHeight * UIConfig.instance.uiSize.x / AspectUtility.screenWidth);
  15.             if (root != null)
  16.             {
  17.                 root.minimumHeight = height;
  18.                 root.maximumHeight = height;
  19.             }
  20.         }
复制代码
其中的_uiCamera2D自然就是NGUI的2D照相机了




欢迎光临 纳金网 (http://rs.narkii.com/club/) Powered by Discuz! X2.5