导语:
在屏幕适配之正交摄像机(Orthographic Camera)下游戏区域适配中我们学习了如何在正交摄像机下进行游戏区域的适配,下面我们来学习如何在透视摄像机下如何进行游戏区域的适配。
1.创建一个Camera(摄像机),将Camera的Projection设置为PersPective
2.设置Field of View 为10(开发者可根据需要自行调整FieldOfView的值)
3.上代码
using System.Collections; using System.Collections.Generic; using UnityEngine; public class CameraAutoFix : MonoBehaviour { [SerializeField] private Transform background; private float designOrthographicSize; private float designHeight; private float designWidth; private float designAspect; private Camera _camera; public void Awake() { FixScreen(); } private void FixScreen() { ScreenOrientation designAutoRotation = Screen.orientation; _camera = this.gameObject.GetComponent<Camera>(); bool isOrthographic = _camera.orthographic; float aspect = Screen.width / (float)Screen.height; designHeight = 1920f; designWidth = 1080f; designAspect = designWidth / designHeight; if (isOrthographic) { OrthographicFix(designAutoRotation, aspect); return; } PerspectiveFix(designAutoRotation, aspect); } private void OrthographicFix(ScreenOrientation designAutoRotation, float aspect) { designOrthographicSize = 9.6f; float widthOrthographicSize = designOrthographicSize * designAspect; switch (designAutoRotation) { case ScreenOrientation.Portrait: if (aspect < designAspect) { _camera.orthographicSize = widthOrthographicSize / aspect; } if (aspect > designAspect) { _camera.orthographicSize = designOrthographicSize; //_camera.orthographicSize = designOrthographicSize * (aspect / designAspect); } break; case ScreenOrientation.AutoRotation: break; case ScreenOrientation.LandscapeLeft: break; case ScreenOrientation.LandscapeRight: break; case ScreenOrientation.PortraitUpsideDown: break; default: break; } } private void PerspectiveFix(ScreenOrientation designAutoRotation,float aspect) { float designFieldOfView = 10.0f; switch (designAutoRotation) { case ScreenOrientation.Portrait: if (aspect < designAspect) { _camera.fieldOfView = designFieldOfView * (designAspect / aspect); } break; case ScreenOrientation.AutoRotation: break; case ScreenOrientation.LandscapeLeft: break; case ScreenOrientation.LandscapeRight: break; case ScreenOrientation.PortraitUpsideDown: break; default: break; } if (background) { Vector3 scale = background.localScale; float scaleX = scale.x * (aspect / designAspect); background.localScale = new Vector3(scaleX * (_camera.fieldOfView / designFieldOfView), scaleX / aspect * (_camera.fieldOfView / designFieldOfView), scale.z); } } public struct CamereArea { public float height; public float width; public override string ToString() { return "(height:" + height + ";" + width + ")"; } } public CamereArea GetCameraAreaWithDistance(float distance) { float halfFOV = (_camera.fieldOfView * 0.5f) * Mathf.Deg2Rad; float aspect = _camera.aspect; float height = distance * Mathf.Tan(halfFOV); float width = height * aspect; CamereArea camereArea = new CamereArea() { height = height, width = width }; return camereArea; } public Vector3 ConvertWordPositionToCameraPosition(Vector3 wordPosition, float aimZ) { CamereArea camereArea = GetCameraAreaWithDistance(wordPosition.z - _camera.transform.position.z); CamereArea camereAreaAim = GetCameraAreaWithDistance(aimZ - _camera.transform.position.z); //Debug.Log("camereArea=" + camereArea + ",camereAreaAim=" + camereAreaAim); float heightRadio = camereAreaAim.height / (camereArea.height); float widthRadio = camereAreaAim.width / (camereArea.width); // Debug.Log("wordPosition:(" + wordPosition.x + "," + wordPosition.x + "," + wordPosition.z + ")"); // Debug.Log("heightRadio=" + heightRadio + ",widthRadio=" + widthRadio); Vector3 convertPosition = new Vector3(wordPosition.x * widthRadio, wordPosition.y * heightRadio, wordPosition.z); return convertPosition; } }