关于 unity 项目的新手引导制作
比较老的新手引导的做法是上下左右四个遮罩组合,把需要 点击 的地方镂空出来。
这里的做法是顶层用一个遮罩全部遮挡住,遮罩上用个 Button 接收点击事件,然后后把事件传递给 目标控件
效果图
预制件
逻辑代码(都是lua),完整版
--====================================================================== -- descrip: 新手引导 --====================================================================== local CTool = require "logic.common.tool" local EventEnum = require "logic.base.event_enum" local CObjectBase = require "logic.object.base_object" local CGuideMgr = class(CObjectBase) CGuideMgr.__name = "CGuideMgr" function CGuideMgr.Init(self) CObjectBase.Init(self) self._path = "Assets/res/Prefabs/ui/PnlMask.prefab" self._rootTran = nil self._BtnMask = nil self._BtnTarget = nil self._Finger = nil -- 手指特效 self._clickTarget = nil self._isForceGuide = false -- 是否强制引导 self._guideRect = nil self:InitEvent() end function CGuideMgr.InitMask(self) local guideCanvas = gGame:GetUIMgr():GetUIGuideCanvasObj() self._guideRect = guideCanvas.transform:GetComponent("RectTransform") self._rootTran = CTool.Instantiate(self._path, guideCanvas.transform).transform GameObject.DontDestroyOnLoad(self._rootTran.gameObject) self._BtnMask = self._rootTran:GetComponent("Button") self._BtnTarget = self._rootTran:Find("BtnTarget"):GetComponent("Button") self._Finger = self._rootTran:Find("e_ui_xingshou_01") UIEventListener.Get(self._BtnMask.gameObject).onClick = LuaHelper.VoidDelegate(function() self:HandlerBtnMask() end) UIEventListener.Get(self._BtnTarget.gameObject).onClick = LuaHelper.VoidDelegate(function() self:HandlerBtnTarget() end) end function CGuideMgr.InitEvent(self) self:RegistEventListener(EventEnum.GuideShow, function(...) self:ShowMask(...) end) end function CGuideMgr.ShowMask(self, target, isForce) if not self._rootTran then self:InitMask() end self._isForceGuide = isForce or false self._clickTarget = target self._rootTran.gameObject:SetActive(true) -- 这里是将遮罩上 Button 根据传进来的对象的位置 摆放 好,这个Button 其实可以降 alpha 调为0,就可以直接看到 目标对象 local uiCam = gGame:GetUIMgr():GetUICamera() local targetPos = target.transform.position local screenPos = Utils.WorldToScreenPoint(uiCam, targetPos) local v2 = Vector2.New(screenPos.x, screenPos.y) local localPos = Utils.ScreenPointToLocalPointInRectangle(self._guideRect, v2, uiCam) local dstPos = Vector3.New(localPos.x, localPos.y, 0) self._BtnTarget.transform.localPosition = dstPos self._Finger.transform.localPosition = dstPos -- print("--- localPos, x:{0}, y:{1}", localPos.x, localPos.y) -- 设置 Button 大小 local targetRect = target.transform:GetComponent("RectTransform") print("--- targetRect, width:{0}, height:{1}", targetRect.rect.width, targetRect.rect.height) local mv = self._BtnMask:GetComponent("MaskValue") -- 这个其实修改遮罩中的 圆形镂空 缩放的效果,其实就是修改 shader 的值 mv:SetValue(50, 100, Vector4.New(localPos.x, localPos.y, 0, 0)) end function CGuideMgr.HideMask(self) self._clickTarget = nil if not self._rootTran then return end self._rootTran.gameObject:SetActive(false) self._BtnMask:GetComponent("MaskValue"):Pause() end function CGuideMgr.DestroyMask(self) self._clickTarget = nil if not self._rootTran then return end GameObject.Destroy(self._rootTran.gameObject) self._rootTran = nil self._BtnMask = nil self._BtnTarget = nil self._guideRect = nil end function CGuideMgr.HandlerBtnMask(self) if self._isForceGuide then return end self:HideMask() end function CGuideMgr.HandlerBtnTarget(self) Utils.ExecutePointerClick(self._clickTarget) self._clickTarget = nil self:HideMask() end return CGuideMgr
Utils.ExecutePointerClick(self._clickTarget)
这个方法触发 go 对象上实现了IPointerClickHandler
接口的方法
public static void ExecutePointerClick(GameObject go) { ExecuteEvents.Execute<IPointerClickHandler>(go, new PointerEventData(EventSystem.current), ExecuteEvents.pointerClickHandler); }
触发事件显示引导
EventTrigger(EventEnum.GuideShow, self._view._Btn2.gameObject) -- _Btn2 这个就是需要被引导的 ui 按钮