文章目录
前言
本文内容为UI控件,水平、垂直方向均变化的自适应处理。即UI与屏幕大小同比例变形。
同时包含:锚点重置、场景备份与还原功能
一、功能代码
1.锚点重置
代码如下:
private void StandardizedAnchor(Transform parent)
{
if (Judge_IfSetAnchor(parent))
{
foreach (Transform child in parent)//遍历子物体
{
ResetUI(child);
float x = child.localPosition.x;
float y = child.localPosition.y;
float x1 = parent.localPosition.x;
float y1 = parent.localPosition.y;
child.localPosition = new Vector2(x + x1, y + y1);
if (child.childCount > 0)
{
StandardizedAnchor(child);
}
}
if (!parent.GetComponent<Canvas>())//CanvasScaler不进行修改
{
parent.GetComponent<RectTransform>().anchorMin = new Vector2(0, 0);
parent.GetComponent<RectTransform>().anchorMax = new Vector2(1, 1);//锚点
parent.GetComponent<RectTransform>().offsetMin = new Vector2(0, 0);
parent.GetComponent<RectTransform>().offsetMax = new Vector2(0, 0);//位置
}
}
}
private bool Judge_IfSetAnchor(Transform parent)
{
if (parent.GetComponent<Canvas>())//CanvasScaler修改子物体
{
return true;
}
string[] prefixs = new string[] { };//设置自身及子物体锚点的 判断标准_前缀
string[] suffixs = new string[] { "_obj" };//设置自身及子物体锚点的 判断标准_后缀
bool ifSetAnchor = false;//是否设置自身及子物体锚点的
foreach(string child in prefixs)
{
if ((parent.name.Length > child.Length) && (parent.name.Substring(0, child.Length) == child))
{
ifSetAnchor = true;
}
}
foreach (string child in suffixs)
{
if ((parent.name.Length > child.Length) && (parent.name.Substring(parent.name.Length - child.Length, child.Length) == child))
{
ifSetAnchor = true;
}
}
return ifSetAnchor;
}
private void ResetUI(Transform obj)
{
if (obj.GetComponent<Canvas>())//CanvasScaler不进行修改
{
return;
}
Vector2 size = new Vector2(obj.GetComponent<RectTransform>().rect.width, obj.GetComponent<RectTransform>().rect.height);
Vector2 pos = new Vector2(0,0);
float x1 = 0.5f, y1 = 0.5f , x2 = 0.5f , y2 = 0.5f;
if (obj.GetComponent<RectTransform>().anchorMin.x!=0.5f
|| obj.GetComponent<RectTransform>().anchorMax.x != 0.5f)
{
x1 = obj.GetComponent<RectTransform>().anchorMin.x;
x2 = obj.GetComponent<RectTransform>().anchorMax.x;
pos = new Vector2(ScreenSize.x * (x1 + x2 - 1) / 2, pos.y);
}
else
{
pos = new Vector2(obj.localPosition.x, pos.y);
}
if (obj.GetComponent<RectTransform>().anchorMin.y!=0.5f
|| obj.GetComponent<RectTransform>().anchorMax.y != 0.5f)
{
y1 = obj.GetComponent<RectTransform>().anchorMin.y;
y2 = obj.GetComponent<RectTransform>().anchorMax.y;
pos = new Vector2(pos.x, ScreenSize.y * (y1 + y2 - 1) / 2);
}
else
{
pos = new Vector2(pos.x, obj.localPosition.y);
}
obj.GetComponent<RectTransform>().anchorMin = new Vector2(0.5f, 0.5f);
obj.GetComponent<RectTransform>().anchorMax = new Vector2(0.5f, 0.5f);//锚点
obj.localPosition = pos;
obj.GetComponent<RectTransform>().sizeDelta = size;
}
锚点重置处理分为两种:
1、符合Judge_IfSetAnchor()中前后缀的UI,做全屏化处理。
2、全屏化处理UI的子物体,如果不符合1,则将锚点重置为屏幕中心。
2.场景备份
代码如下:
private void CopyScene()//场景备份
{
Debug.Log("开始备份");
Scene OriginalScene;
string CopyScenePath;
OriginalScene = SceneManager.GetActiveScene();
CopyScenePath = Return_TheCopyScenePath(OriginalScene);
EditorSceneManager.SaveScene(OriginalScene, CopyScenePath, true);
Debug.Log("备份完成,备份场景路径:" + CopyScenePath);
}
private string Return_TheCopyScenePath(UnityEngine.SceneManagement.Scene OriginalScene)
{
string CopyScenePath;
CopyScenePath = OriginalScene.path.Substring(0, OriginalScene.path.Length - 6);
CopyScenePath = CopyScenePath + "_copy.unity";
return CopyScenePath;
}
场景备份说明:
1、备份的场景与原场景在相同路径下
2、两者的判定标准为是否存在_copy后缀
3.场景还原
代码如下:
private void AutomaticLoad_CopyScene()
{
BeginAutomaticRestoreScene = false;//修改 开始自动还原 状态
Scene originalScene,copyScene;
string copyScenePath;
GameObject[] scriptRootChilds;
bool isChange=false;
originalScene = SceneManager.GetActiveScene();
copyScenePath = originalScene.path.Substring(0, originalScene.path.Length - 6);
copyScenePath = copyScenePath + "_copy.unity";//获取备份场景地址
copyScene=EditorSceneManager.OpenScene(copyScenePath, OpenSceneMode.Additive);
scriptRootChilds = copyScene.GetRootGameObjects();
foreach (GameObject child in scriptRootChilds)
{
if (child.name == MountScript_obj.name)
{
child.GetComponentInChildren<UI_Scene_Adapter1>().BeginManualRestoreScene = true;
isChange = true;
break;
}
}//修改备份场景中的BeginRestore状态
if (isChange)
{
EditorSceneManager.SaveScene(copyScene, copyScenePath, false);
EditorSceneManager.CloseScene(copyScene, false);
EditorSceneManager.OpenScene(copyScenePath);//打开备份场景
}
else
{
Debug.Log("修改备份场景-BeginRestore失败");
EditorSceneManager.CloseScene(copyScene, false);
}
}
private void ManualLoad_CopyScene()
{
Debug.Log("开始还原");
Scene copyScene;
string originalScenePath;
BeginManualRestoreScene = false;//修改 开始手动还原 状态
gameObject.GetComponent<UI_Scene_Adapter1>().enabled = false;//禁用脚本
copyScene = SceneManager.GetActiveScene();
EditorSceneManager.SaveScene(copyScene);//保存备份场景
originalScenePath = copyScene.path.Substring(0, copyScene.path.Length - 11);
originalScenePath = originalScenePath + ".unity";//获取原场景地址
EditorSceneManager.SaveScene(copyScene, originalScenePath, false);//备份场景替换原场景
Debug.Log("还原完成");
}
自动还原与手动还原的区别:
1、手动还原,在备份场景中使用。
选择BeginManualRestoreScene后,自动查找原场景并进行替换。
2、自动还原,在原场景中使用
选择BeginAutomaticRestoreScene后,自动查找备份场景并修改备份场景的BeginManualRestoreScene,之后自动跳转到备份场景并进行手动还原。
4.UI自适应
private void Start_UIAdapter()
{
Debug.Log("开始UI自适应");
Vector2[] anchorMinAndMax;//锚点坐标
Vector3[] corners = new Vector3[4];//存储控件四个角的坐标
string first_control_name = null;//第一个自适应控件的名称
string last_control_name = null;//最后一个自适应控件的名称
float beginTime, endTime;//自适应开始时间与结束时间
int changeNum = 0;//修改的控件数
bool isAdapter;//当前控件是否进行UI自适应
beginTime = Time.realtimeSinceStartup;//初始化开始时间记录
Init_UIAdapterNeedData();
CopyScene();//场景备份
StandardizedAnchor(RootUI); Debug.Log("标准化UI锚点完成");
CanvasChilds = RootUI.GetComponentsInChildren<Transform>(true);
foreach (RectTransform childControl in CanvasChilds)//遍历子物体
{
controlNum = controlNum + 1;
isAdapter = IfAdapterByControl(childControl);
if (isAdapter)
{
corners = AnchorIgnorTheRotate(childControl);
anchorMinAndMax = ComputeAnchorMinAndMax(corners);
SetAnchorMinAndMax(childControl, anchorMinAndMax);
changeNum = changeNum + 1;
}
if (controlNum == 1)
{
first_control_name = childControl.name;
}
else
{
last_control_name = childControl.name;
}
}
endTime = Time.realtimeSinceStartup;
Debug.Log("全部UI自适应已完成");
Debug.Log("共遍历子控件:" + controlNum + "个," + "共修改子控件:" + changeNum + "个," + "开始于" + first_control_name + "控件,结束于" + last_control_name + "控件,耗费时间:" + (endTime - beginTime).ToString("f3") + "s");
}
private void Init_UIAdapterNeedData()
{
Debug.Log("开始UI自适应");
BeginUIAdapter = false;
controlNum = -1;//初始化控件数量记录
}
private bool IfAdapterByControl(Transform control)
{
string[] prefixs = new string[] { };//是否不执行UI自适应的 判断标准_前缀
string[] suffixs = new string[] {"_img","_btn","_txt"};//是否执行UI自适应的 判断标准_后缀
string controlName;//控件名字
bool ifSetAnchor = false;//是否执行UI自适应
controlName = control.name;//获取控件名字
foreach (string child in suffixs)
{
if ((controlName.Length > child.Length) && (controlName.Substring(controlName.Length - child.Length, child.Length) == child))
{
ifSetAnchor = true;
}
}
foreach (string child in prefixs)
{
if ((controlName.Length > child.Length) && (controlName.Substring(0, child.Length) == child))
{
ifSetAnchor = false;
}
}
return ifSetAnchor;
}
private Vector3[] AnchorIgnorTheRotate(Transform Control)
{
#region 变量定义
Vector3[] ControlCorners = new Vector3[4];
Vector3[] NewControlCorners = new Vector3[4];
Vector3 ControlRotation;
int j = -1;
#endregion
ControlRotation = Control.rotation.eulerAngles;//物体旋转角度,四元数转欧拉角
Control.GetComponent<RectTransform>().GetWorldCorners(ControlCorners);//获取物体四个角的世界坐标(以父物体为世界坐标系),左下、左上、右上和右下
#region 控件旋转角度判断
if (System.Math.Abs(ControlRotation.z) == 0 || System.Math.Abs(ControlRotation.z) % 360 == 0)//物体不进行旋转
{
j = 0;
}
else if (System.Math.Abs(ControlRotation.z) % 270 == 0)//物体旋转270度
{
j = 3;
}
else if (System.Math.Abs(ControlRotation.z) % 180 == 0)//物体旋转180度
{
j = 2;
}
else if (System.Math.Abs(ControlRotation.z) % 90 == 0)//子物体旋转90度
{
j = 1;
}
#endregion
#region 统一控件四个角的坐标
if (j != -1)
{
for (int i = 0; i < 4; i++)
{
NewControlCorners[i] = ControlCorners[j];
j++;
if (j > 3)
{
j = 0;
}
}
}
#endregion
return NewControlCorners;
}
private Vector2[] ComputeAnchorMinAndMax(Vector3[] ControlCorners)
{
Vector3[] CanvasCorners = new Vector3[4];//最高级父物体四角坐标,Canvas菜单
Vector2[] MinAndMaxAnchor = new Vector2[2];//控件锚点坐标
float wight, height;
float anchorMin_x, anchorMin_y, anchorMax_x, anchorMax_y;//左下角锚点X坐标、左下角锚点Y坐标、右上角锚点X坐标、右上角锚点Y坐标
RootCanvas.GetComponent<RectTransform>().GetWorldCorners(CanvasCorners);
wight = CanvasCorners[2].x * 2;
height = CanvasCorners[2].y * 2;
anchorMin_x = float.Parse(((wight / 2 + ControlCorners[0].x) / wight).ToString("f3"));
anchorMin_y = float.Parse(((height / 2 + ControlCorners[0].y) / height).ToString("f3"));
anchorMax_x = float.Parse(((wight / 2 + ControlCorners[2].x) / wight).ToString("f3"));
anchorMax_y = float.Parse(((height / 2 + ControlCorners[2].y) / height).ToString("f3"));
MinAndMaxAnchor[0] = new Vector2(anchorMin_x, anchorMin_y);
MinAndMaxAnchor[1] = new Vector2(anchorMax_x, anchorMax_y);
return MinAndMaxAnchor;
}
private void SetAnchorMinAndMax(Transform Control,Vector2[] AnchorMinAndMax)
{
Control.GetComponent<RectTransform>().anchorMin = new Vector2(AnchorMinAndMax[0].x, AnchorMinAndMax[0].y);//设置锚点的anchorMin
Control.GetComponent<RectTransform>().anchorMax = new Vector2(AnchorMinAndMax[1].x, AnchorMinAndMax[1].y);//设置锚点的anchorMax
Control.GetComponent<RectTransform>().offsetMin = new Vector2(0, 0);//设置offsetMin
Control.GetComponent<RectTransform>().offsetMax = new Vector2(0, 0);//设置offsetMax
Control.GetComponent<RectTransform>().localScale = new Vector3(1,1,1);
}
UI自适应说明:
1、开始UI自适应后,自动进行场景备份和锚点重置。
2、UI自适应,包含对旋转90、180、270、360图片的处理
3、在IfAdapterByControl()里,通过前后缀,判定是否进行UI自适应处理。
二、代码总览
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using UnityEditor.SceneManagement;
[ExecuteInEditMode]
public class UI_Adapter : MonoBehaviour {
public bool BeginAutomaticRestoreScene = false;//开始自动还原
public bool BeginManualRestoreScene = false;//开始手动还原
public bool BeginStandardizedAnchor = false;//开始重置坐标
public bool BeginCopy = false;//开始备份
#region UI设置
public bool BeginUIAdapter = false;//开始UI自适应
public GameObject MountScript_obj;//当前脚本需挂载到顶级节点的下级节点中
public Transform RootUI;
public Vector2 ScreenSize = new Vector2(1920,1080);
public CanvasScaler RootCanvas;//Canvas菜单,即UI最高父物体
private Transform[] CanvasChangeChilds=null;//所有子物体的集合
private Transform[] CanvasChilds = null;//所有子物体的集合
private int controlNum;//计数-完成自适应的控件数目
#endregion
private void Awake()
{
BeginAutomaticRestoreScene = false;
BeginStandardizedAnchor = false;
BeginCopy = false;
BeginUIAdapter = false;
if (BeginManualRestoreScene)
{
ManualLoad_CopyScene();
}
else
{
gameObject.GetComponent<UI_Adapter>().enabled = false;//添加脚本后,禁用脚本
}
}
private void Update()
{
if(BeginStandardizedAnchor)
{
Debug.Log("开始标准化UI锚点");
StandardizedAnchor(RootUI);
BeginStandardizedAnchor = false;
Debug.Log("标准化UI锚点完成");
gameObject.GetComponent<UI_Adapter>().enabled = false;//位置重置完成后,禁用脚本
}
if(BeginUIAdapter)
{
Start_UIAdapter();
gameObject.GetComponent<UI_Adapter>().enabled = false;//UI自适应完成后,禁用脚本
}
if(BeginCopy)
{
CopyScene();
gameObject.GetComponent<UI_Adapter>().enabled = false;//场景备份后,禁用脚本
}
if(BeginAutomaticRestoreScene)//在原场景中使用
{
Debug.Log("开始自动还原");
AutomaticLoad_CopyScene();
}
if(BeginManualRestoreScene)//在备份的场景中使用
{
Debug.Log("开始手动还原");
ManualLoad_CopyScene();
}
}
#region 场景备份与还原代码
#region 场景备份代码
private void CopyScene()//场景备份
{
Debug.Log("开始备份");
Scene OriginalScene;
string CopyScenePath;
OriginalScene = SceneManager.GetActiveScene();
CopyScenePath = Return_TheCopyScenePath(OriginalScene);
EditorSceneManager.SaveScene(OriginalScene, CopyScenePath, true);
Debug.Log("备份完成,备份场景路径:" + CopyScenePath);
}
private string Return_TheCopyScenePath(UnityEngine.SceneManagement.Scene OriginalScene)
{
string CopyScenePath;
CopyScenePath = OriginalScene.path.Substring(0, OriginalScene.path.Length - 6);
CopyScenePath = CopyScenePath + "_copy.unity";
return CopyScenePath;
}
#endregion
#region 场景还原代码
private void AutomaticLoad_CopyScene()
{
BeginAutomaticRestoreScene = false;//修改 开始自动还原 状态
Scene originalScene,copyScene;
string copyScenePath;
GameObject[] scriptRootChilds;
bool isChange=false;
originalScene = SceneManager.GetActiveScene();
copyScenePath = originalScene.path.Substring(0, originalScene.path.Length - 6);
copyScenePath = copyScenePath + "_copy.unity";//获取备份场景地址
copyScene=EditorSceneManager.OpenScene(copyScenePath, OpenSceneMode.Additive);
scriptRootChilds = copyScene.GetRootGameObjects();
foreach (GameObject child in scriptRootChilds)
{
if (child.name == MountScript_obj.name)
{
child.GetComponentInChildren<UI_Adapter>().BeginManualRestoreScene = true;
isChange = true;
break;
}
}//修改备份场景中的BeginRestore状态
if (isChange)
{
EditorSceneManager.SaveScene(copyScene, copyScenePath, false);
EditorSceneManager.CloseScene(copyScene, false);
EditorSceneManager.OpenScene(copyScenePath);//打开备份场景
}
else
{
Debug.Log("修改备份场景-BeginRestore失败");
EditorSceneManager.CloseScene(copyScene, false);
}
}
private void ManualLoad_CopyScene()
{
Debug.Log("开始还原");
Scene copyScene;
string originalScenePath;
BeginManualRestoreScene = false;//修改 开始手动还原 状态
gameObject.GetComponent<UI_Adapter>().enabled = false;//禁用脚本
copyScene = SceneManager.GetActiveScene();
EditorSceneManager.SaveScene(copyScene);//保存备份场景
originalScenePath = copyScene.path.Substring(0, copyScene.path.Length - 11);
originalScenePath = originalScenePath + ".unity";//获取原场景地址
EditorSceneManager.SaveScene(copyScene, originalScenePath, false);//备份场景替换原场景
Debug.Log("还原完成");
}
#endregion
#endregion
#region 标准化-锚点
private void StandardizedAnchor(Transform parent)
{
if (Judge_IfSetAnchor(parent))
{
foreach (Transform child in parent)//遍历子物体
{
ResetUI(child);
float x = child.localPosition.x;
float y = child.localPosition.y;
float x1 = Parent.localPosition.x;
float y1 = Parent.localPosition.y;
child.localPosition = new Vector2(x + x1, y + y1);
if (child.childCount > 0)
{
StandardizedAnchor(child);
}
}
if (!parent.GetComponent<Canvas>())//CanvasScaler不进行修改
{
parent.GetComponent<RectTransform>().anchorMin = new Vector2(0, 0);
parent.GetComponent<RectTransform>().anchorMax = new Vector2(1, 1);//锚点
parent.GetComponent<RectTransform>().offsetMin = new Vector2(0, 0);
parent.GetComponent<RectTransform>().offsetMax = new Vector2(0, 0);//位置
}
}
}
private bool Judge_IfSetAnchor(Transform parent)
{
if (parent.GetComponent<Canvas>())//CanvasScaler修改子物体
{
return true;
}
string[] prefixs = new string[] { };//设置自身及子物体锚点的 判断标准_前缀
string[] suffixs = new string[] { "_obj" };//设置自身及子物体锚点的 判断标准_后缀
bool ifSetAnchor = false;//是否设置自身及子物体锚点的
foreach(string child in prefixs)
{
if ((parent.name.Length > child.Length) && (parent.name.Substring(0, child.Length) == child))
{
ifSetAnchor = true;
}
}
foreach (string child in suffixs)
{
if ((parent.name.Length > child.Length) && (parent.name.Substring(parent.name.Length - child.Length, child.Length) == child))
{
ifSetAnchor = true;
}
}
return ifSetAnchor;
}
private bool ResetUI(Transform obj)
{
if (obj.GetComponent<Canvas>())//CanvasScaler不进行修改
{
return false;
}
Vector2 size = new Vector2(obj.GetComponent<RectTransform>().rect.width, obj.GetComponent<RectTransform>().rect.height);
Vector2 pos = new Vector2(0,0);
float x1 = 0.5f, y1 = 0.5f , x2 = 0.5f , y2 = 0.5f;
if (obj.GetComponent<RectTransform>().anchorMin.x!=0.5f
|| obj.GetComponent<RectTransform>().anchorMax.x != 0.5f)
{
x1 = obj.GetComponent<RectTransform>().anchorMin.x;
x2 = obj.GetComponent<RectTransform>().anchorMax.x;
pos = new Vector2(ScreenSize.x * (x1 + x2 - 1) / 2, pos.y);
}
else
{
pos = new Vector2(obj.localPosition.x, pos.y);
}
if (obj.GetComponent<RectTransform>().anchorMin.y!=0.5f
|| obj.GetComponent<RectTransform>().anchorMax.y != 0.5f)
{
y1 = obj.GetComponent<RectTransform>().anchorMin.y;
y2 = obj.GetComponent<RectTransform>().anchorMax.y;
pos = new Vector2(pos.x, ScreenSize.y * (y1 + y2 - 1) / 2);
}
else
{
pos = new Vector2(pos.x, obj.localPosition.y);
}
obj.GetComponent<RectTransform>().anchorMin = new Vector2(0.5f, 0.5f);
obj.GetComponent<RectTransform>().anchorMax = new Vector2(0.5f, 0.5f);//锚点
obj.localPosition = pos;
obj.GetComponent<RectTransform>().sizeDelta = size;
return true;
}
#endregion
#region UI自适应代码
private void Start_UIAdapter()
{
Debug.Log("开始UI自适应");
Vector2[] anchorMinAndMax;//锚点坐标
Vector3[] corners = new Vector3[4];//存储控件四个角的坐标
string first_control_name = null;//第一个自适应控件的名称
string last_control_name = null;//最后一个自适应控件的名称
float beginTime, endTime;//自适应开始时间与结束时间
int changeNum = 0;//修改的控件数
bool isAdapter;//当前控件是否进行UI自适应
beginTime = Time.realtimeSinceStartup;//初始化开始时间记录
Init_UIAdapterNeedData();
CopyScene();//场景备份
StandardizedAnchor(RootUI); Debug.Log("标准化UI锚点完成");
CanvasChilds = RootUI.GetComponentsInChildren<Transform>(true);
foreach (RectTransform childControl in CanvasChilds)//遍历子物体
{
controlNum = controlNum + 1;
isAdapter = IfAdapterByControl(childControl);
if (isAdapter)
{
corners = AnchorIgnorTheRotate(childControl);
anchorMinAndMax = ComputeAnchorMinAndMax(corners);
SetAnchorMinAndMax(childControl, anchorMinAndMax);
changeNum = changeNum + 1;
}
if (controlNum == 1)
{
first_control_name = childControl.name;
}
else
{
last_control_name = childControl.name;
}
}
endTime = Time.realtimeSinceStartup;
Debug.Log("全部UI自适应已完成");
Debug.Log("共遍历子控件:" + controlNum + "个," + "共修改子控件:" + changeNum + "个," + "开始于" + first_control_name + "控件,结束于" + last_control_name + "控件,耗费时间:" + (endTime - beginTime).ToString("f3") + "s");
}
private void Init_UIAdapterNeedData()
{
Debug.Log("开始UI自适应");
BeginUIAdapter = false;
controlNum = -1;//初始化控件数量记录
}
private bool IfAdapterByControl(Transform control)
{
string[] prefixs = new string[] { };//是否不执行UI自适应的 判断标准_前缀
string[] suffixs = new string[] {"_img","_btn","_txt"};//是否执行UI自适应的 判断标准_后缀
string controlName;//控件名字
bool ifSetAnchor = false;//是否执行UI自适应
controlName = control.name;//获取控件名字
foreach (string child in suffixs)
{
if ((controlName.Length > child.Length) && (controlName.Substring(controlName.Length - child.Length, child.Length) == child))
{
ifSetAnchor = true;
}
}
foreach (string child in prefixs)
{
if ((controlName.Length > child.Length) && (controlName.Substring(0, child.Length) == child))
{
ifSetAnchor = false;
}
}
return ifSetAnchor;
}
private Vector3[] AnchorIgnorTheRotate(Transform Control)
{
#region 变量定义
Vector3[] ControlCorners = new Vector3[4];
Vector3[] NewControlCorners = new Vector3[4];
Vector3 ControlRotation;
int j = -1;
#endregion
ControlRotation = Control.rotation.eulerAngles;//物体旋转角度,四元数转欧拉角
Control.GetComponent<RectTransform>().GetWorldCorners(ControlCorners);//获取物体四个角的世界坐标(以父物体为世界坐标系),左下、左上、右上和右下
#region 控件旋转角度判断
if (System.Math.Abs(ControlRotation.z) == 0 || System.Math.Abs(ControlRotation.z) % 360 == 0)//物体不进行旋转
{
j = 0;
}
else if (System.Math.Abs(ControlRotation.z) % 270 == 0)//物体旋转270度
{
j = 3;
}
else if (System.Math.Abs(ControlRotation.z) % 180 == 0)//物体旋转180度
{
j = 2;
}
else if (System.Math.Abs(ControlRotation.z) % 90 == 0)//子物体旋转90度
{
j = 1;
}
#endregion
#region 统一控件四个角的坐标
if (j != -1)
{
for (int i = 0; i < 4; i++)
{
NewControlCorners[i] = ControlCorners[j];
j++;
if (j > 3)
{
j = 0;
}
}
}
#endregion
return NewControlCorners;
}
private Vector2[] ComputeAnchorMinAndMax(Vector3[] ControlCorners)
{
Vector3[] CanvasCorners = new Vector3[4];//最高级父物体四角坐标,Canvas菜单
Vector2[] MinAndMaxAnchor = new Vector2[2];//控件锚点坐标
float wight, height;
float anchorMin_x, anchorMin_y, anchorMax_x, anchorMax_y;//左下角锚点X坐标、左下角锚点Y坐标、右上角锚点X坐标、右上角锚点Y坐标
RootCanvas.GetComponent<RectTransform>().GetWorldCorners(CanvasCorners);
wight = CanvasCorners[2].x * 2;
height = CanvasCorners[2].y * 2;
anchorMin_x = float.Parse(((wight / 2 + ControlCorners[0].x) / wight).ToString("f3"));
anchorMin_y = float.Parse(((height / 2 + ControlCorners[0].y) / height).ToString("f3"));
anchorMax_x = float.Parse(((wight / 2 + ControlCorners[2].x) / wight).ToString("f3"));
anchorMax_y = float.Parse(((height / 2 + ControlCorners[2].y) / height).ToString("f3"));
MinAndMaxAnchor[0] = new Vector2(anchorMin_x, anchorMin_y);
MinAndMaxAnchor[1] = new Vector2(anchorMax_x, anchorMax_y);
return MinAndMaxAnchor;
}
private void SetAnchorMinAndMax(Transform Control,Vector2[] AnchorMinAndMax)
{
Control.GetComponent<RectTransform>().anchorMin = new Vector2(AnchorMinAndMax[0].x, AnchorMinAndMax[0].y);//设置锚点的anchorMin
Control.GetComponent<RectTransform>().anchorMax = new Vector2(AnchorMinAndMax[1].x, AnchorMinAndMax[1].y);//设置锚点的anchorMax
Control.GetComponent<RectTransform>().offsetMin = new Vector2(0, 0);//设置offsetMin
Control.GetComponent<RectTransform>().offsetMax = new Vector2(0, 0);//设置offsetMax
Control.GetComponent<RectTransform>().localScale = new Vector3(1,1,1);
}
#endregion
}
三、知识点
1.anchorMin 与 anchorMax
2.offsetMin 与 offsetMax
3.localPosition
4.sizeDelta
5.rect
6.GetWorldCorners()
四、知识点说明文章链接
https://www.cnblogs.com/w-wfy/p/7800757.html
https://blog.csdn.net/jmu201521121014/article/details/105725175