using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; /// /// 矩形遮罩镂空 /// public class RectGuidance : MonoBehaviour { public static RectGuidance instance; /// /// 高亮显示目标 /// public Image target; /// /// 区域范围缓存 /// private Vector3[] corners = new Vector3[4]; /// /// 镂空区域中心 /// private Vector4 center; /// /// 最终的偏移x /// private float targetOffsetX = 0; /// /// 最终的偏移y /// private float targetOffsetY = 0; /// /// 遮罩材质 /// private Material material; /// /// 当前的偏移x /// private float currentOffsetX = 0f; /// /// 当前的偏移y /// private float currentOffsetY = 0f; /// /// 事件渗透组件 /// private GuidanceEventPenetrate eventPenetrate; Canvas canvas; private void Awake() { instance = this; canvas = GameObject.Find("MainUI").GetComponent(); eventPenetrate = GetComponent(); material = GetComponent().material; } public void Init(Image target) { this.target = target; if (eventPenetrate != null) { eventPenetrate.SetTargetImage(target); } //获取高亮区域的四个顶点的世界坐标 target.rectTransform.GetWorldCorners(corners); for (int i = 0; i < corners.Length; i++) { Debug.Log("corners i:" + i + " vec3:" + corners[i]); } //计算高亮显示区域在画布中的范围 targetOffsetX = Vector2.Distance(WorldToCanvasPos(canvas, corners[0]), WorldToCanvasPos(canvas, corners[3])) / 2f; targetOffsetY = Vector2.Distance(WorldToCanvasPos(canvas, corners[0]), WorldToCanvasPos(canvas, corners[1])) / 2f; //计算高亮显示区域的中心 float x = corners[0].x + ((corners[3].x - corners[0].x) / 2); float y = corners[0].y + ((corners[1].y - corners[0].y) / 2); Vector3 centerWorld = new Vector3(x, y, 0); Vector2 center = WorldToCanvasPos(canvas, centerWorld); //设置遮罩材质中的中心变量 Vector4 centerMat = new Vector4(center.x, center.y, 0, 0); material = GetComponent().material; material.SetVector("_Center", centerMat); //计算当前高亮显示区域的半径 RectTransform canRectTransform = canvas.transform as RectTransform; if (canRectTransform != null) { //获取画布区域的四个顶点 canRectTransform.GetWorldCorners(corners); //计算偏移初始值 for (int i = 0; i < corners.Length; i++) { if (i % 2 == 0) { currentOffsetX = Mathf.Max(Vector3.Distance(WorldToCanvasPos(canvas, corners[i]), center), currentOffsetX); } else { currentOffsetY = Mathf.Max(Vector3.Distance(WorldToCanvasPos(canvas, corners[i]), center), currentOffsetY); } } } //设置遮罩材质中当前偏移的变量 material.SetFloat("_SliderX", currentOffsetX); material.SetFloat("_SliderY", currentOffsetY); } public void InitForCamera(Image target, float x, float y, Vector2 offect) { this.target = target; if (eventPenetrate != null) { eventPenetrate.SetTargetImage(target); } Vector2 center = target.GetComponent().anchoredPosition; center += offect; material.SetVector("_Center", center); material.SetFloat("_SliderX", x); material.SetFloat("_SliderY", y); } public void InitForCamera(Image target, Vector2 center, float x, float y) { this.target = target; if (eventPenetrate != null) { eventPenetrate.SetTargetImage(target); } material.SetVector("_Center", center); material.SetFloat("_SliderX", x); material.SetFloat("_SliderY", y); } /// /// 收缩速度 /// private float shrinkVelocityX = 0f; private float shrinkVelocityY = 0f; //private void Update() //{ //从当前偏移量到目标偏移量差值显示收缩动画 // float valueX = Mathf.SmoothDamp(currentOffsetX, targetOffsetX, ref shrinkVelocityX, shrinkTime); // float valueY = Mathf.SmoothDamp(currentOffsetY, targetOffsetY, ref shrinkVelocityY, shrinkTime); // if (!Mathf.Approximately(valueX, currentOffsetX)) // { // currentOffsetX = valueX; // material.SetFloat("_SliderX", currentOffsetX); // } // if (!Mathf.Approximately(valueY, currentOffsetY)) // { // currentOffsetY = valueY; // material.SetFloat("_SliderY", currentOffsetY); // } //} //立刻显示阴影区域 public void ShowImmediately() { //return; float valueX = Mathf.SmoothDamp(currentOffsetX, targetOffsetX, ref shrinkVelocityX, 0); float valueY = Mathf.SmoothDamp(currentOffsetY, targetOffsetY, ref shrinkVelocityY, 0); if (!Mathf.Approximately(valueX, currentOffsetX)) { currentOffsetX = valueX; material.SetFloat("_SliderX", targetOffsetX); } if (!Mathf.Approximately(valueY, currentOffsetY)) { currentOffsetY = valueY; material.SetFloat("_SliderY", targetOffsetY); } } /// /// 世界坐标转换为画布坐标 /// /// 画布 /// 世界坐标 /// private Vector2 WorldToCanvasPos(Canvas canvas, Vector3 world) { Vector2 position; RectTransformUtility.ScreenPointToLocalPointInRectangle(canvas.transform as RectTransform, world, canvas.GetComponent(), out position); return position; } }