unity 游戏 引导

UI的实现借鉴Unity 新手引导 遮罩效果_Liam's blog-CSDN博客_unity遮罩

目的:新手引导为独立模块,通过配置表来动态的实现。降低和其他模块的耦合。

配置表设计:

1、引导组表,包含 引导组id,引导id,是否是强引导

2、引导表,包含 id,组id,UI界面的id,引导的UI的Name,遮罩类型,触发条件,触发值,需要执行的动作,执行动作的参数,完成条件,完成后的动作

单个引导的逻辑

1、判断是否触发

2、显示遮罩

3、执行动作

4、判断是否完成

5、执行完成后的动作

主要的几个难点:

1、查找UI

        2D的UI通过获取当前的UI的根节点,通过GetChild来获得

        /// <summary>
        /// 在层级未知的情况下查找子物体
        /// </summary>
        /// <param name="parentTF">父物体变换组件</param>
        /// <param name="childName">子物体名称</param>
        /// <returns></returns>
        public static Transform GetChild(Transform parentTF, string childName)
        {
            //在子物体中查找
            Transform childTF = parentTF.Find(childName);

            if (childTF != null)
            {
                return childTF;
            }
            //将问题交由子物体
            int count = parentTF.childCount;
            for (int i = 0; i < count; i++)
            {
                childTF = GetChild(parentTF.GetChild(i), childName);
                if (childTF != null)
                {
                    return childTF;
                }
            }
            return null;
        }

        3D的物体

//尽量将路径写全,可以减少查询时间
GameObject.Find(UiName)

        对于动态加载的scrollview中的view,可以先找出一个view,然后查找他的父transform下的第几个view

2、遮罩的坐标转换

        查找出需要遮罩的UI,显示和点击的透传,都需要转换成UIPos.

//工具类用到的方法

public static Vector2 WorldPosToUIPos(Camera world_cam, Vector3 world_pos, Camera ui_cam, RectTransform ui_rect)
        {
            Vector2 mouseDown = world_cam.WorldToScreenPoint(world_pos);
            Vector2 localPoint;
            RectTransformUtility.ScreenPointToLocalPointInRectangle(ui_rect, mouseDown, ui_cam, out localPoint);
            return localPoint;
        }

 public static Vector3[] GetWorldCorners(RectTransform rt)
        {
            Vector3[] v = new Vector3[4];
            rt.GetWorldCorners(v);
            return v;
        }

下面是lua的代码

--注意self.GuideCarmera,如果是3D的需要传入3D相机,2D的为UI相机
self.maskTargetRTF = targetObj:GetComponent("RectTransform")
local center = Vector4(0, 0, 0, 0)
local tempV3s = LuaUtility.GetWorldCorners(self.maskTargetRTF)
local screenV2s = {} --转换世界坐标到屏幕坐标
for i = 0, 3, 1 do
    local sp = LuaUtility.WorldPosToUIPos(self.GuideCarmera, tempV3s[i], self.UICamera, self.UICanvasRTF)
    screenV2s[i] = {}
    screenV2s[i].x = sp.x
    screenV2s[i].y = sp.y
end
--计算中心点
center.x = screenV2s[0].x + (screenV2s[3].x - screenV2s[0].x) / 2
center.y = screenV2s[0].y + (screenV2s[1].y - screenV2s[0].y) / 2
--计算宽高
local width = (screenV2s[3].x - screenV2s[0].x) / 2
local height = (screenV2s[1].y - screenV2s[0].y) / 2



--下面是设置遮罩的UI
--设置中心点
self.material:SetVector("_Center", center)
--设置宽高
self.material:SetFloat("_SliderX", width)
self.material:SetFloat("_SliderY", height)

3、点击透传的问题

        首先,需要拦截点击

    //实现 lua 点击透传的过滤问题
    public class UIFocus : MonoBehaviour, ICanvasRaycastFilter
    {
        public bool IsFocus = false;

        private LuaFuncIsRaycastDelegate isRaycastDelegate;
        public bool IsRaycastLocationValid(Vector2 sp, Camera eventCamera)
        {
            if (isRaycastDelegate != null)
            {
                return isRaycastDelegate(sp, eventCamera);
            }
            return IsFocus;
        }
        public void SetIsRaycastFunction(LuaFuncIsRaycastDelegate isRaycastDelegate)
        {
            this.isRaycastDelegate = isRaycastDelegate;
        }
    }

        然后,将这个添加到引导的UI上

self.uiFocus = self.maskImgGo:AddComponent(typeof(CS.UIFocus))

        设置回调方法

self.panel.uiFocus:SetIsRaycastFunction(
        function(sp, camera)
            return self:IsRaycastLocationValid(sp, camera)
        end
    )

        判断方法

--点击是否需要透传
function GuideFormCtrl:IsRaycastLocationValid(sp, eventCamera)
    if self.guide ~= nil then
        if self.maskTargetRTF then
            local isRay = self:IsRaycastInMask(sp)
                return not isRay
        end
        return true
    end
    return false
end
--点击是否需要透传
function GuideFormCtrl:IsRaycastInMask(sp)
    if self.maskTargetRTF then
        local isRay =
            RectTransformUtility.RectangleContainsScreenPoint(
            self.maskTargetRTF,
            sp,
            (self.GuideCarmera or self.UICamera)
        )
        return isRay
    end
    return false
end

总结:

        还是需要在其他界面进行埋点,回调发送消息,业务逻辑在新手引导中完成。后续还有问题再记录下

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值