一:矩形鏤空功能
1、新建一個場景,創建兩個按鈕,一個Image

2、導入shader,創建兩個材質,將兩個shader拖到兩個材質上。將材質拖動到Image組件的Material上。


3、創建腳本RectGuide,創建一個方法Guide(參數:Canvas(為了將世界轉換屏幕坐標提供需要的Camera,target(要鏤空的組件)),測試一下
- GetWorldCorners:在世界空間中得到計算的矩形的角。參數角的數組
- WorldToScreenPoint參數:camera(通過canvas傳入),vector3(世界坐標)


using Sytem.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class RectGuide : MonoBehaviour { private Material material; // 材質 private Vector3 center; // 鏤空區域的中心 private float width; // 鏤空區域的寬 private float height; // 鏤空區域的高 private RectTransform target;// 要顯示的目標,通過目標計算鏤空區域的中心,寬高 public Vector3[] targetCorners = new Vector3[4];//存儲要鏤空組件的四個角的數組 // 引導 public void Guide(Canvas canvas, RectTransform target) { this.target = target; // 將傳進來的目標組件賦值給target // 獲取中心點 // GetWorldCorners:在世界空間中得到計算的矩形的角。參數角的數組 target.GetWorldCorners(targetCorners); // 講四個角的世界坐標轉為屏幕坐標 for (int i = 0; i < targetCorners.Length; i++) { // WorldToScreenPoint參數:camera(通過canvas傳入),vector3(世界坐標) targetCorners[i]=RectTransformUtility.WorldToScreenPoint(canvas.worldCamera, targetCorners[i]); } } private void Update() { Guide(GameObject.Find("Canvas").GetComponent<Canvas>(),GameObject.Find("Button").GetComponent<RectTransform>()); } }
問題:shader的坐標的原點是中心,而轉換的屏幕坐標的原點是左下角,所以需要轉化
4、RectTransformUtility.ScreenPointToLocalPointInRectangle:屏幕坐標轉換為局部坐標
參數:
- RectTransform rect ------轉換為誰的局部坐標
- Vector2 screenPoint ------要轉換的屏幕坐標
- Camera cam, ------相機
- out Vector2 localPoint ---- 輸出的局部坐標
// 講四個角的世界坐標轉為屏幕坐標 for (int i = 0; i < targetCorners.Length; i++) { // WorldToScreenPoint參數:camera(通過canvas傳入),vector3(世界坐標) targetCorners[i]=RectTransformUtility.WorldToScreenPoint(canvas.worldCamera, targetCorners[i]); // 屏幕坐標轉換為局部坐標 //out的是vector2類型,事先聲明 Vector2 localPoint; RectTransformUtility.ScreenPointToLocalPointInRectangle(canvas.GetComponent<RectTransform>(), targetCorners[i], canvas.worldCamera, out localPoint); targetCorners[i] = localPoint; }
5、將上述代碼封裝成一個方法,完整的為:
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class RectGuide : MonoBehaviour { private Material material; // 材質 private Vector3 center; // 鏤空區域的中心 private float width; // 鏤空區域的寬 private float height; // 鏤空區域的高 private RectTransform target;// 要顯示的目標,通過目標計算鏤空區域的中心,寬高 public Vector3[] targetCorners = new Vector3[4];//存儲要鏤空組件的四個角的數組 // 引導 public void Guide(Canvas canvas, RectTransform target) { this.target = target; // 將傳進來的目標組件賦值給target // 獲取中心點 // GetWorldCorners:在世界空間中得到計算的矩形的角。參數角的數組 target.GetWorldCorners(targetCorners); // 講四個角的世界坐標轉為局部坐標坐標 for (int i = 0; i < targetCorners.Length; i++) { targetCorners[i] = WorldToScreenPoint(canvas, targetCorners[i]); } } //private void Update() //{ // Guide(GameObject.Find("Canvas").GetComponent<Canvas>(),GameObject.Find("Button").GetComponent<RectTransform>()); //} public Vector2 WorldToScreenPoint(Canvas canvas,Vector3 world) { //把世界坐標轉化為屏幕坐標 Vector2 screenPoint = RectTransformUtility.WorldToScreenPoint(canvas.worldCamera, world); // 屏幕坐標轉換為局部坐標 //out的是vector2類型,事先聲明 Vector2 localPoint; RectTransformUtility.ScreenPointToLocalPointInRectangle(canvas.GetComponent<RectTransform>(), screenPoint, canvas.worldCamera, out localPoint); return localPoint; } }
6、由獲取到的鏤空矩形四個角的局部坐標,計算鏤空區域的中心點,賦值給material材質,在賦值之前,要對聲明的材質變量,賦值
給材質賦值的時候要用它實際的名字_Center,而不是顯示的名字Center
private void Start() { // 獲取材質 material = transform.GetComponent<Image>().material; //如果沒有獲取到材質,就拋出異常 if(material == null) { throw new System.Exception("為獲取到材質"); } }
//計算中心點 center.x = targetCorners[0].x + (targetCorners[3].x - targetCorners[0].x) / 2; center.y = targetCorners[0].y + (targetCorners[1].y - targetCorners[0].y) / 2; //設置材質的中心點 material.SetVector("_Center", center);
完整代碼:改動組件的值,鏤空區域的中心點能夠跟隨移動
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class RectGuide : MonoBehaviour { private Material material; // 材質 private Vector3 center; // 鏤空區域的中心 private float width; // 鏤空區域的寬 private float height; // 鏤空區域的高 private RectTransform target;// 要顯示的目標,通過目標計算鏤空區域的中心,寬高 public Vector3[] targetCorners = new Vector3[4];//存儲要鏤空組件的四個角的數組 private void Start() { // 獲取材質 material = transform.GetComponent<Image>().material; //如果沒有獲取到材質,就拋出異常 if(material == null) { throw new System.Exception("為獲取到材質"); } } // 引導 public void Guide(Canvas canvas, RectTransform target) { this.target = target; // 將傳進來的目標組件賦值給target // 獲取中心點 // GetWorldCorners:在世界空間中得到計算的矩形的角。參數角的數組 target.GetWorldCorners(targetCorners); // 講四個角的世界坐標轉為局部坐標坐標 for (int i = 0; i < targetCorners.Length; i++) { targetCorners[i] = WorldToScreenPoint(canvas, targetCorners[i]); } //計算中心點 center.x = targetCorners[0].x + (targetCorners[3].x - targetCorners[0].x) / 2; center.y = targetCorners[0].y + (targetCorners[1].y - targetCorners[0].y) / 2; //設置材質的中心點 material.SetVector("_Center", center); } public Vector2 WorldToScreenPoint(Canvas canvas,Vector3 world) { //把世界坐標轉化為屏幕坐標 Vector2 screenPoint = RectTransformUtility.WorldToScreenPoint(canvas.worldCamera, world); // 屏幕坐標轉換為局部坐標 //out的是vector2類型,事先聲明 Vector2 localPoint; RectTransformUtility.ScreenPointToLocalPointInRectangle(canvas.GetComponent<RectTransform>(), screenPoint, canvas.worldCamera, out localPoint); return localPoint; } private void Update() { Guide(GameObject.Find("Canvas").GetComponent<Canvas>(), GameObject.Find("Button").GetComponent<RectTransform>()); } }
7、計算鏤空區域的寬和高
// 計算寬高 width = targetCorners[3].x - targetCorners[0].x; height = targetCorners[1].y - targetCorners[0].y; //設置材質的寬高 material.SetFloat("_SliderX", width); material.SetFloat("_SliderY", height);
這個后運行,寬高會比實際的大,所以將獲得的寬高/2
// 計算寬高 width = (targetCorners[3].x - targetCorners[0].x)/2; height = (targetCorners[1].y - targetCorners[0].y)/2; //設置材質的寬高 material.SetFloat("_SliderX", width); material.SetFloat("_SliderY", height);
到此完成的效果就是,鏤空區域能夠能隨button組件移動,寬高、中心都會跟隨button組件,但是還不能點擊,並且也不能有動畫
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class RectGuide : MonoBehaviour { private Material material; // 材質 private Vector3 center; // 鏤空區域的中心 private float width; // 鏤空區域的寬 private float height; // 鏤空區域的高 private RectTransform target;// 要顯示的目標,通過目標計算鏤空區域的中心,寬高 private Vector3[] targetCorners = new Vector3[4];//存儲要鏤空組件的四個角的數組 private void Start() { // 獲取材質 material = transform.GetComponent<Image>().material; //如果沒有獲取到材質,就拋出異常 if (material == null) { throw new System.Exception("為獲取到材質"); } } // 引導 public void Guide(Canvas canvas, RectTransform target) { this.target = target; // 將傳進來的目標組件賦值給target // 獲取中心點 // GetWorldCorners:在世界空間中得到計算的矩形的角。參數角的數組 target.GetWorldCorners(targetCorners); // 講四個角的世界坐標轉為局部坐標坐標 for (int i = 0; i < targetCorners.Length; i++) { targetCorners[i] = WorldToScreenPoint(canvas, targetCorners[i]); } //計算中心點 center.x = targetCorners[0].x + (targetCorners[3].x - targetCorners[0].x) / 2; center.y = targetCorners[0].y + (targetCorners[1].y - targetCorners[0].y) / 2; //設置材質的中心點 material.SetVector("_Center", center); // 計算寬高 width = (targetCorners[3].x - targetCorners[0].x)/2; height = (targetCorners[1].y - targetCorners[0].y)/2; //設置材質的寬高 material.SetFloat("_SliderX", width); material.SetFloat("_SliderY", height); } public Vector2 WorldToScreenPoint(Canvas canvas, Vector3 world) { //把世界坐標轉化為屏幕坐標 Vector2 screenPoint = RectTransformUtility.WorldToScreenPoint(canvas.worldCamera, world); // 屏幕坐標轉換為局部坐標 //out的是vector2類型,事先聲明 Vector2 localPoint; RectTransformUtility.ScreenPointToLocalPointInRectangle(canvas.GetComponent<RectTransform>(), screenPoint, canvas.worldCamera, out localPoint); return localPoint; } private void Update() { Guide(GameObject.Find("Canvas").GetComponent<Canvas>(), GameObject.Find("Button").GetComponent<RectTransform>()); } }
二、圓形鏤空
圓形和矩形大部分代碼都是一樣的,就是矩形要計算寬高,而圓形要計算半徑,所以可以創建一個基類GuideBase。
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class GuideBase : MonoBehaviour { // 將私有的變量,變成protect,這樣才可以繼承 protected Material material; // 材質 protected Vector3 center; // 鏤空區域的中心 protected RectTransform target;// 要顯示的目標,通過目標計算鏤空區域的中心,寬高 protected Vector3[] targetCorners = new Vector3[4];//存儲要鏤空組件的四個角的數組 protected virtual void Start() { // 獲取材質 material = transform.GetComponent<Image>().material; //如果沒有獲取到材質,就拋出異常 if (material == null) { throw new System.Exception("為獲取到材質"); } } // 引導 public virtual void Guide(Canvas canvas, RectTransform target) { this.target = target; // 將傳進來的目標組件賦值給target // 獲取中心點 // GetWorldCorners:在世界空間中得到計算的矩形的角。參數角的數組 target.GetWorldCorners(targetCorners); // 講四個角的世界坐標轉為局部坐標坐標 for (int i = 0; i < targetCorners.Length; i++) { targetCorners[i] = WorldToScreenPoint(canvas, targetCorners[i]); } //計算中心點 center.x = targetCorners[0].x + (targetCorners[3].x - targetCorners[0].x) / 2; center.y = targetCorners[0].y + (targetCorners[1].y - targetCorners[0].y) / 2; //設置材質的中心點 material.SetVector("_Center", center); } // 功能性的方法,不需要重寫,所以不需要創建成虛方法 public Vector2 WorldToScreenPoint(Canvas canvas, Vector3 world) { //把世界坐標轉化為屏幕坐標 Vector2 screenPoint = RectTransformUtility.WorldToScreenPoint(canvas.worldCamera, world); // 屏幕坐標轉換為局部坐標 //out的是vector2類型,事先聲明 Vector2 localPoint; RectTransformUtility.ScreenPointToLocalPointInRectangle(canvas.GetComponent<RectTransform>(), screenPoint, canvas.worldCamera, out localPoint); return localPoint; } }
繼承GuideBase后的RectGuide腳本
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class RectGuide : GuideBase { private float width; // 鏤空區域的寬 private float height; // 鏤空區域的高 // 引導 public override void Guide(Canvas canvas, RectTransform target) { //調用下base,中的方法 base.Guide(canvas,target); // 中心點的計算在base.Guide(canvas,target)有了, // 計算寬高 width = (targetCorners[3].x - targetCorners[0].x)/2; height = (targetCorners[1].y - targetCorners[0].y)/2; //設置材質的寬高 material.SetFloat("_SliderX", width); material.SetFloat("_SliderY", height); } private void Update() { Guide(GameObject.Find("Canvas").GetComponent<Canvas>(), GameObject.Find("Button").GetComponent<RectTransform>()); } }
繼承GuideBase后的CircleGuide腳本
using System.Collections; using System.Collections.Generic; using UnityEngine; public class CircleGuide : GuideBase { private float r; // 鏤空區域圓形的半徑 public override void Guide(Canvas canvas, RectTransform target) { base.Guide(canvas, target); float width = (targetCorners[3].x - targetCorners[0].x) / 2; float height = (targetCorners[1].y - targetCorners[0].y) / 2; //計算半徑,寬/2的平方 + 高/2的平方,之后開方 r = Mathf.Sqrt(width * width + height * height); // 賦值給材質 material.SetFloat("_Slider", r); } // Update is called once per frame void Update() { Guide(GameObject.Find("Canvas").GetComponent<Canvas>(), GameObject.Find("Button").GetComponent<RectTransform>()); } }
將image的材質換成CircleMateri,將CircleGuide腳本掛載到Image上,運行。
三、新手引導的方法封裝
1、在GuideBase中加上[RequireComponent(typeof(Image))],保證有image組件,而且移除不了。
材質的初始化,不在start中了。在Guide方法中(這點也沒搞懂)

2、創建GuideController腳本
- 創建枚舉,里面可以選擇引導的類型(Rect或者Circle)
- 需要保證有CircleGuide、RectGuide組件(自己創建的矩形鏤空和圓形鏤空,在這里里面可以將update測試代碼注釋了)
- 創建變量包括(矩形引導腳本組件、圓形引導組件、矩形材質、圓形材質(根據情況,自己選擇需要的材質,就不用自己手動拖到Image組件的Material上了),Image組件)
- 初始化,獲得(引導頁面)的圓形、矩形組件、image組件
- 創建方法Guide(參數:canvas\鏤空組件\引導類型),在這里用switch
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; // 枚舉,引導的類型 public enum GuideType { Rect, Circle } //組件:需要的組件將會自動被添加到game object(游戲物體)。上 [RequireComponent(typeof(CircleGuide))] [RequireComponent(typeof(RectGuide))] public class GuideController : MonoBehaviour { // private CircleGuide circleGuide; private RectGuide rectGuide; //材質不一樣,所以創建兩個材質 [SerializeField] private Material rectMat; [SerializeField] private Material circleMat; //需要image, private Image mask; // 在 private void Awake() { mask = transform.GetComponent<Image>(); if (rectMat==null || circleMat==null) { throw new System.Exception("材質未賦值"); } circleGuide = transform.GetComponent<CircleGuide>(); rectGuide = transform.GetComponent<RectGuide>(); } public void Guide(Canvas canvas,RectTransform target,GuideType guideType) { // TODO switch (guideType) { case GuideType.Rect: mask.material = rectMat; rectGuide.Guide(canvas, target); break; case GuideType.Circle: mask.material = circleMat; circleGuide.Guide(canvas, target); break; } } }
3、創建GuidePanel腳本
獲取canvas、GuideController guideController、調用guideController中的Guide方法,傳入參數,2秒后切換button_cir組件鏤空
using System.Collections; using System.Collections.Generic; using UnityEngine; public class GuidePanel : MonoBehaviour { GuideController guideController; Canvas canvas; private void Awake() { canvas = GetComponentInParent<Canvas>(); } // Start is called before the first frame update void Start() { guideController = GetComponent<GuideController>(); guideController.Guide(canvas, GameObject.Find("Button").GetComponent<RectTransform>(),GuideType.Rect); Invoke("test", 2); } void test() { guideController.Guide(canvas, GameObject.Find("Button_cir").GetComponent<RectTransform>(), GuideType.Circle); } // Update is called once per frame void Update() { } }
4、創建頁面,將GuideController腳本、GuidePanel腳本掛上,記得更改image組件的大小、顏色、透明度。
四、事件滲透
問題:現在雖然鏤空,但是按鈕不能點擊
1、給需要能點擊的UI控件上綁定,實現一個接口ICanvasRaycastFilter
在方法IsRaycastLocationValid中判斷當前點擊的位置是否符合響應事件的條件,return true事件不能滲透,false能滲透
應用場景:
1.引導挖洞
2.ui事件觸發,並且不影響下面的其他控件的事件響應
2、RectTransformUtility.RectangleContainsScreenPoint(target, sp);矩形區域包不包含鼠標點擊的點
3、在GuideController腳本中改
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; // 枚舉,引導的類型 public enum GuideType { Rect, Circle } //組件:需要的組件將會自動被添加到game object(游戲物體)。上 [RequireComponent(typeof(CircleGuide))] [RequireComponent(typeof(RectGuide))] public class GuideController : MonoBehaviour,ICanvasRaycastFilter { // private CircleGuide circleGuide; private RectGuide rectGuide; //材質不一樣,所以創建兩個材質 [SerializeField] private Material rectMat; [SerializeField] private Material circleMat; //需要image, private Image mask; private RectTransform target; // 在 private void Awake() { mask = transform.GetComponent<Image>(); if (rectMat==null || circleMat==null) { throw new System.Exception("材質未賦值"); } circleGuide = transform.GetComponent<CircleGuide>(); rectGuide = transform.GetComponent<RectGuide>(); } public void Guide(Canvas canvas,RectTransform target,GuideType guideType) { //引導的時候,將傳入的target賦值 this.target = target; // TODO switch (guideType) { case GuideType.Rect: mask.material = rectMat; rectGuide.Guide(canvas, target); break; case GuideType.Circle: mask.material = circleMat; circleGuide.Guide(canvas, target); break; } } /// <summary> /// /// </summary> /// <param name="sp">鼠標點的點(屏幕坐標),看看在不在鏤空區域,在就把事件滲透,不在攔截</param> /// <param name="eventCamera"></param> /// <returns></returns> public bool IsRaycastLocationValid(Vector2 sp, Camera eventCamera) { if (target==null) { return true; }//點擊不了 // 看看鼠標點擊在不在鏤空區域 return !RectTransformUtility.RectangleContainsScreenPoint(target, sp); } }
五、完善優化
1、加動畫,需要在GuideBase中寫個Guide重載函數,矩形更改寬高,圓形更改半徑,都不用在基類中寫
//寫個重載函數 public virtual void Guide(Canvas canvas, RectTransform target,float scale,float time) { }
2、找到子類,重寫,在里面不用調用基類的方法,以圓形為例
using System.Collections; using System.Collections.Generic; using UnityEngine; public class CircleGuide : GuideBase { private float r; // 鏤空區域圓形的半徑 private float scaleR; //變化之前的半徑大小 private float timer; //計時器 private float time; // 時間 private bool isScaling; // 是否正在變化 //重寫引導,沒有動畫 public override void Guide(Canvas canvas, RectTransform target) { base.Guide(canvas, target); float width = (targetCorners[3].x - targetCorners[0].x) / 2; float height = (targetCorners[1].y - targetCorners[0].y) / 2; //計算半徑,寬/2的平方 + 高/2的平方,之后開方 r = Mathf.Sqrt(width * width + height * height); // 賦值給材質 material.SetFloat("_Slider", r); } //重寫引導,有動畫 public override void Guide(Canvas canvas, RectTransform target, float scale, float time) { //base.Guide(canvas, target, scale, time);不用調用因為是空的 this.Guide(canvas,target); scaleR = r * scale; this.material.SetFloat("_Slider", scaleR); this.time = time; isScaling = true; timer = 0; } private void Update() { if (isScaling) { // 每秒變化1/time,時間越短變化的就得越快 //deltaTime時間增量,保證不同幀率移動的是一樣的 timer += Time.deltaTime * 1 / time; this.material.SetFloat("_Slider", Mathf.Lerp(scaleR, r, timer)); if(timer >= 1) { timer = 0; isScaling = false; } } } // Update is called once per frame //void Update() //{ // Guide(GameObject.Find("Canvas").GetComponent<Canvas>(), GameObject.Find("Button_cir").GetComponent<RectTransform>()); //} }
3、GuideController腳本中,創建重載函數
public void Guide(Canvas canvas, RectTransform target, GuideType guideType, float scale, float time) { //引導的時候,將傳入的target賦值 this.target = target; // TODO switch (guideType) { case GuideType.Rect: mask.material = rectMat; rectGuide.Guide(canvas, target, scale, time); break; case GuideType.Circle: mask.material = circleMat; circleGuide.Guide(canvas, target, scale, time); break; } }
4、在GuidePanel,test中調用
void test() { //guideController.Guide(canvas, GameObject.Find("Button_cir").GetComponent<RectTransform>(), GuideType.Circle); guideController.Guide(canvas, GameObject.Find("Button_cir").GetComponent<RectTransform>(), GuideType.Circle,2,0.5f); }
5、矩形類似,可以用繼承,但是我沒有用,暈,直接按照circle格式寫的,類似,到此RectGuide全部代碼
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class RectGuide : GuideBase { private float width; // 鏤空區域的寬 private float height; // 鏤空區域的高 private float scaleW; //變化之前的寬 private float scaleH; //變化之前的高 private float timer; //計時器 private float time; // 時間 private bool isScaling; // 是否正在變化 // 引導 public override void Guide(Canvas canvas, RectTransform target) { //調用下base,中的方法 base.Guide(canvas,target); // 中心點的計算在base.Guide(canvas,target)有了, // 計算寬高 width = (targetCorners[3].x - targetCorners[0].x)/2; height = (targetCorners[1].y - targetCorners[0].y)/2; //設置材質的寬高 material.SetFloat("_SliderX", width); material.SetFloat("_SliderY", height); } //重寫引導,有動畫 public override void Guide(Canvas canvas, RectTransform target, float scale, float time) { //base.Guide(canvas, target, scale, time);不用調用因為是空的 this.Guide(canvas, target); scaleW = width * scale; scaleH = height * scale; this.material.SetFloat("_SliderX", scaleW); this.material.SetFloat("_SliderY", scaleH); this.time = time; isScaling = true; timer = 0; } private void Update() { if (isScaling) { // 每秒變化1/time,時間越短變化的就得越快 //deltaTime時間增量,保證不同幀率移動的是一樣的 timer += Time.deltaTime * 1 / time; this.material.SetFloat("_SliderX", Mathf.Lerp(scaleW, width, timer)); this.material.SetFloat("_SliderY", Mathf.Lerp(scaleH, height, timer)); if (timer >= 1) { timer = 0; isScaling = false; } } } //private void Update() //{ // Guide(GameObject.Find("Canvas").GetComponent<Canvas>(), GameObject.Find("Button").GetComponent<RectTransform>()); //} }
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; // 枚舉,引導的類型 public enum GuideType { Rect, Circle } //組件:需要的組件將會自動被添加到game object(游戲物體)。上 [RequireComponent(typeof(CircleGuide))] [RequireComponent(typeof(RectGuide))] public class GuideController : MonoBehaviour,ICanvasRaycastFilter { // private CircleGuide circleGuide; private RectGuide rectGuide; //材質不一樣,所以創建兩個材質 [SerializeField] private Material rectMat; [SerializeField] private Material circleMat; //需要image, private Image mask; private RectTransform target; // 在 private void Awake() { mask = transform.GetComponent<Image>(); if (rectMat==null || circleMat==null) { throw new System.Exception("材質未賦值"); } circleGuide = transform.GetComponent<CircleGuide>(); rectGuide = transform.GetComponent<RectGuide>(); } public void Guide(Canvas canvas, RectTransform target, GuideType guideType) { //引導的時候,將傳入的target賦值 this.target = target; // TODO switch (guideType) { case GuideType.Rect: mask.material = rectMat; rectGuide.Guide(canvas, target); break; case GuideType.Circle: mask.material = circleMat; circleGuide.Guide(canvas, target); break; } } public void Guide(Canvas canvas, RectTransform target, GuideType guideType, float scale, float time) { //引導的時候,將傳入的target賦值 this.target = target; // TODO switch (guideType) { case GuideType.Rect: mask.material = rectMat; rectGuide.Guide(canvas, target, scale, time); break; case GuideType.Circle: mask.material = circleMat; circleGuide.Guide(canvas, target, scale, time); break; } } /// <summary> /// /// </summary> /// <param name="sp">鼠標點的點(屏幕坐標),看看在不在鏤空區域,在就把事件滲透,不在攔截</param> /// <param name="eventCamera"></param> /// <returns></returns> public bool IsRaycastLocationValid(Vector2 sp, Camera eventCamera) { if (target==null) { return true; }//點擊不了 // 看看鼠標點擊在不在鏤空區域 return !RectTransformUtility.RectangleContainsScreenPoint(target, sp); } }
using System.Collections; using System.Collections.Generic; using UnityEngine; public class GuidePanel : MonoBehaviour { GuideController guideController; Canvas canvas; private void Awake() { canvas = GetComponentInParent<Canvas>(); } // Start is called before the first frame update void Start() { guideController = GetComponent<GuideController>(); //guideController.Guide(canvas, GameObject.Find("Button").GetComponent<RectTransform>(),GuideType.Rect); guideController.Guide(canvas, GameObject.Find("Button").GetComponent<RectTransform>(),GuideType.Rect,3,1.5f); Invoke("test", 2); } void test() { //guideController.Guide(canvas, GameObject.Find("Button_cir").GetComponent<RectTransform>(), GuideType.Circle); guideController.Guide(canvas, GameObject.Find("Button_cir").GetComponent<RectTransform>(), GuideType.Circle,3,1.0f); } // Update is called once per frame void Update() { } }
鏈接:https://pan.baidu.com/s/1BzGGotE8imnp1nYo9T4pAQ
提取碼:uvf1
復制這段內容后打開百度網盤手機App,操作更方便哦
