Unity强制屏幕纵宽比脚本

强制屏幕到所需要的长宽比,可以根据需要自由选择是否应用强制比例.其中包括返回校正后的屏幕宽度,高度(Screen.width/height)和鼠标位置(Input.mousePosition).

将这个脚本放在编译顺序较优先的文件夹中,比如 Standard Assets, (Plugins是最先编译的),因此你可以用Js,C#等语言调用AspectUtility来使用它.首先要将它附加到Camera上,它同样可以附加给其他物体,如果你赋给其他物体,它将主动尝试找到标签为"Main Camera"的相机.对于WantedAspectRatio这个值,常见的是4:3为1.333333,16:10为1.6,16:9为1.777778,如果屏幕的纵宽比与设定的相同,不会有任何变化.如果与设定的纵宽比不同,将用黑色填充缺少的部分.
这样会导致有些方法返回不正确,比如Screen.width和Screen.height会返回实际屏幕尺寸,而不是主相机的尺寸,为了纠正这个问题,可以使用AspectUtility.screenWidth和AspectUtility.screenHeight.

同样的,Input.mousePosition也会有些问题,这种情况可以使用AspectUtility.mousePosition获取需要的值.

有一点要注意,这些变量在脚本刚唤醒的时候可能不能正确获取到,这就需要等待脚本开始后再访问它们.

当屏幕尺寸变化,例如Webplayer,采用4:3的比例,用户切换全屏后变成了16:9,这时候就需要用AspectUtility.SetCamera()重设脚本相机.

OnGUI代码在用AspectRatioEnforcer时需要做一些额外的工作.OnGUI的代码独立于Camera画在屏幕上的.所以相机改变了矩阵尺寸,它不会自动变化.这时候我们要特别处理一下.

如果你是用GUILayout来排列GUI,可以用GUILayout.BeginArea和EndArea来定义一个范围,像下面这样:
程序代码 js 代码
?
1
2
3
4
5
function OnGUI () {
     GUILayout.Label( "Hello" );
     GUILayout.Label( "there" );
}


修改它为:

程序代码 js 代码
?
1
2
3
4
5
6
7
8
function OnGUI () {
     GUILayout.BeginArea(AspectUtility.screenRect);
  
     GUILayout.Label( "Hello" );
     GUILayout.Label( "there" );
  
     GUILayout.EndArea();
}


如果已经用过BeginArea/EndArea,你可以直接在外面再嵌套AspectUtility.screenRect,它仍旧会处理好的.

如果你没有使用GUILayout,那么可以添加x和y的偏移来修正所有GUI的Rect,可以用AspectUtility.xOffset 和 AspectUtility.yOffset来得到偏移量,比如你平时这样写:

程序代码 js 代码
?
1
2
3
4
5
function OnGUI () {
     GUI.Label(Rect(50, 50, 100, 30), "Hello" );
     GUI.Label(Rect(75, 75, 100, 30), "there" );
}


现在改成:

程序代码 js 代码
?
1
2
3
4
5
6
7
8
function OnGUI () {
     var x = AspectUtility.xOffset;
     var y = AspectUtility.yOffset;
  
     GUI.Label(Rect(x + 50, y + 50, 100, 30), "Hello" );
     GUI.Label(Rect(x + 75, y + 75, 100, 30), "there" );
}


通常在OnGUI里获得鼠标位置用的是Event.current.mousePosition,在这里我们应该改使用AspectUtility.guiMousePosition.

AspectUtility.cs脚本
程序代码 csharp 代码
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
using UnityEngine;
  
public class AspectUtility : MonoBehaviour {
  
     public float _wantedAspectRatio = 1.3333333f;
     static float wantedAspectRatio;
     static Camera cam;
     static Camera backgroundCam;
  
     void Awake () {
         cam = camera;
         if (!cam) {
             cam = Camera.main;
         }
         if (!cam) {
             Debug.LogError ( "No camera available" );
             return ;
         }
         wantedAspectRatio = _wantedAspectRatio;
         SetCamera();
     }
  
     public static void SetCamera () {
         float currentAspectRatio = ( float )Screen.width / Screen.height;
         // If the current aspect ratio is already approximately equal to the desired aspect ratio,
         // use a full-screen Rect (in case it was set to something else previously)
         if (( int )(currentAspectRatio * 100) / 100.0f == ( int )(wantedAspectRatio * 100) / 100.0f) {
             cam.rect = new Rect(0.0f, 0.0f, 1.0f, 1.0f);
             if (backgroundCam) {
                 Destroy(backgroundCam.gameObject);
             }
             return ;
         }
         // Pillarbox
         if (currentAspectRatio > wantedAspectRatio) {
             float inset = 1.0f - wantedAspectRatio/currentAspectRatio;
             cam.rect = new Rect(inset/2, 0.0f, 1.0f-inset, 1.0f);
         }
         // Letterbox
         else {
             float inset = 1.0f - currentAspectRatio/wantedAspectRatio;
             cam.rect = new Rect(0.0f, inset/2, 1.0f, 1.0f-inset);
         }
         if (!backgroundCam) {
             // Make a new camera behind the normal camera which displays black; otherwise the unused space is undefined
             backgroundCam = new GameObject( "BackgroundCam" , typeof (Camera)).camera;
             backgroundCam.depth = int .MinValue;
             backgroundCam.clearFlags = CameraClearFlags.SolidColor;
             backgroundCam.backgroundColor = Color.black;
             backgroundCam.cullingMask = 0;
         }
     }
  
     public static int screenHeight {
         get {
             return ( int )(Screen.height * cam.rect.height);
         }
     }
  
     public static int screenWidth {
         get {
             return ( int )(Screen.width * cam.rect.width);
         }
     }
  
     public static int xOffset {
         get {
             return ( int )(Screen.width * cam.rect.x);
         }
     }
  
     public static int yOffset {
         get {
             return ( int )(Screen.height * cam.rect.y);
         }
     }
  
     public static Rect screenRect {
         get {
             return new Rect(cam.rect.x * Screen.width, cam.rect.y * Screen.height, cam.rect.width * Screen.width, cam.rect.height * Screen.height);
         }
     }
  
     public static Vector3 mousePosition {
         get {
             Vector3 mousePos = Input.mousePosition;
             mousePos.y -= ( int )(cam.rect.y * Screen.height);
             mousePos.x -= ( int )(cam.rect.x * Screen.width);
             return mousePos;
         }
     }
  
     public static Vector2 guiMousePosition {
         get {
             Vector2 mousePos = Event.current.mousePosition;
             mousePos.y = Mathf.Clamp(mousePos.y, cam.rect.y * Screen.height, cam.rect.y * Screen.height + cam.rect.height * Screen.height);
             mousePos.x = Mathf.Clamp(mousePos.x, cam.rect.x * Screen.width, cam.rect.x * Screen.width + cam.rect.width * Screen.width);
             return mousePos;
         }
     }
}


AspectUtilityEnhanced.cs脚本:

程序代码 csharp 代码
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
using UnityEngine;
  
public class AspectUtility : MonoBehaviour {
  
     public float _wantedAspectRatio = 1.5f;
     public bool landscapeModeOnly = true ;
     static public bool _landscapeModeOnly = true ;
     static float wantedAspectRatio;
     static Camera cam;
     static Camera backgroundCam;
  
     void Awake () {
         _landscapeModeOnly = landscapeModeOnly;
         cam = camera;
         if (!cam) {
             cam = Camera.main;
             Debug.Log ( "Setting the main camera " + cam.name);
         }
         else {
             Debug.Log ( "Setting the main camera " + cam.name);
         }
  
         if (!cam) {
             Debug.LogError ( "No camera available" );
             return ;
         }
         wantedAspectRatio = _wantedAspectRatio;
         SetCamera();
     }
  
     public static void SetCamera () {
         float currentAspectRatio = 0.0f;
         if (Screen.orientation == ScreenOrientation.LandscapeRight ||
             Screen.orientation == ScreenOrientation.LandscapeLeft) {
             Debug.Log ( "Landscape detected..." );
             currentAspectRatio = ( float )Screen.width / Screen.height;
         }
         else {
             Debug.Log ( "Portrait detected...?" );
             if (Screen.height  > Screen.width && _landscapeModeOnly) {
                 currentAspectRatio = ( float )Screen.height / Screen.width;
             }
             else {
                 currentAspectRatio = ( float )Screen.width / Screen.height;
             }
         }
         // If the current aspect ratio is already approximately equal to the desired aspect ratio,
         // use a full-screen Rect (in case it was set to something else previously)
  
         Debug.Log ( "currentAspectRatio = " + currentAspectRatio + ", wantedAspectRatio = " + wantedAspectRatio);
  
         if (( int )(currentAspectRatio * 100) / 100.0f == ( int )(wantedAspectRatio * 100) / 100.0f) {
             cam.rect = new Rect(0.0f, 0.0f, 1.0f, 1.0f);
             if (backgroundCam) {
                 Destroy(backgroundCam.gameObject);
             }
             return ;
         }
  
         // Pillarbox
         if (currentAspectRatio > wantedAspectRatio) {
             float inset = 1.0f - wantedAspectRatio/currentAspectRatio;
             cam.rect = new Rect(inset/2, 0.0f, 1.0f-inset, 1.0f);
         }
         // Letterbox
         else {
             float inset = 1.0f - currentAspectRatio/wantedAspectRatio;
             cam.rect = new Rect(0.0f, inset/2, 1.0f, 1.0f-inset);
         }
         if (!backgroundCam) {
             // Make a new camera behind the normal camera which displays black; otherwise the unused space is undefined
             backgroundCam = new GameObject( "BackgroundCam" , typeof (Camera)).camera;
             backgroundCam.depth = int .MinValue;
             backgroundCam.clearFlags = CameraClearFlags.SolidColor;
             backgroundCam.backgroundColor = Color.black;
             backgroundCam.cullingMask = 0;
         }
     }
  
     public static int screenHeight {
         get {
             return ( int )(Screen.height * cam.rect.height);
         }
     }
  
     public static int screenWidth {
         get {
             return ( int )(Screen.width * cam.rect.width);
         }
     }
  
     public static int xOffset {
         get {
             return ( int )(Screen.width * cam.rect.x);
         }
     }
  
     public static int yOffset {
         get {
             return ( int )(Screen.height * cam.rect.y);
         }
     }
  
     public static Rect screenRect {
         get {
             return new Rect(cam.rect.x * Screen.width, cam.rect.y * Screen.height, cam.rect.width * Screen.width, cam.rect.height * Screen.height);
         }
     }
  
     public static Vector3 mousePosition {
         get {
             Vector3 mousePos = Input.mousePosition;
             mousePos.y -= ( int )(cam.rect.y * Screen.height);
             mousePos.x -= ( int )(cam.rect.x * Screen.width);
             return mousePos;
         }
     }
  
     public static Vector2 guiMousePosition {
         get {
             Vector2 mousePos = Event.current.mousePosition;
             mousePos.y = Mathf.Clamp(mousePos.y, cam.rect.y * Screen.height, cam.rect.y * Screen.height + cam.rect.height * Screen.height);
             mousePos.x = Mathf.Clamp(mousePos.x, cam.rect.x * Screen.width, cam.rect.x * Screen.width + cam.rect.width * Screen.width);
             return mousePos;
         }
     }
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值