unity-新手引导

关于 unity 项目的新手引导制作。。。


比较老的新手引导的做法是上下左右四个遮罩组合,把需要 点击 的地方镂空出来。

这里的做法是顶层用一个遮罩全部遮挡住,遮罩上用个 Button 接收点击事件,然后后把事件传递给 目标控件

  • 效果图

    这里写图片描述

  • 预制件

    这里写图片描述

    这里写图片描述

  • 逻辑代码(都是lua),完整版

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    --======================================================================
    -- 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 接口的方法

      1
      2
      3
      public static void ExecutePointerClick(GameObject go) {
      ExecuteEvents.Execute<IPointerClickHandler>(go, new PointerEventData(EventSystem.current), ExecuteEvents.pointerClickHandler);
      }
  • 触发事件显示引导

    1
    EventTrigger(EventEnum.GuideShow, self._view._Btn2.gameObject) -- _Btn2 这个就是需要被引导的 ui 按钮