unity中的UI开发难点梳理

1.unity中的几种position的梳理

unity中有很多种position,当我们使用他们的时候难免会出现各种疑惑,主要分为:localposition,position,anchoredPosition这几种,我将会对他们一一进行梳理。

首先是localPosition:

localPosition

localPostion是子物体相对与父物体的位置,是一个相对的位置,如过该物体没有父物体的话,那么他的Vector3参数和position的位置其实是一样的。但是需要注意的是,在计算世界坐标的位置时,父级变换的rotation和scale将应用与本地的位置。这意味着,虽然position中的一像素距离始终是一个单位,但是localPosition中的一单位像素距离将会受到父级scale的影响不一定始终为1像素。

position

position是世界坐标,他其实含义很简单,就是一个记录世界坐标的Vector3类型的属性。

anchoredPosition

anchoredPosition是一个Vec2类型的属性,他其实是rectTransform的pivot相对于锚点的位置,一般来说轴心pivot和锚点是处在同一个点的,但是有时候为了实现不同的需求会更改他们的位置,这个时候rectTransform会根据轴心pivot来计算其他四个锚点的位置。
通过代码设置RectTransform的位置:

 public RectTransform rectTransform;
    void Start()
    {
        if (rectTransform != null)
        {
            rectTransform.anchoredPosition = new Vector2(100, 200);//设置相对锚点偏移量
            rectTransform.anchorMin = new Vector2(0.5f, 0.5f); // 锚点最小值
            rectTransform.anchorMax = new Vector2(0.5f, 0.5f); // 锚点最大值
            rectTransform.pivot = new Vector2(0.5f, 0.5f); // 中心点
            rectTransform.anchoredPosition = new Vector2(150, 150); // 设置位置
        }
    }

pivot

pivot是RectTransform中比较重要的一个属性也叫做轴心,主要作用是作为RectTransform的旋转和缩放时候的基准点,我们用的锚点位置也是基于这个轴心的基础上的相对坐标。

root

这个属性时transform的属性,如果该物体没有父物体时则会返回自己,该属性不会返回空值。

sizeDelta

sizeDelta是RectTransform中一个很重要的属性,他是用来衡量与RectTransform的各个锚点距离的一个属性。如果锚点在一起,则 sizeDelta 与 size 相同。如果锚点位于父级的四个角中,则 sizeDelta 是矩形与其父级相比下的大小。

RectTransform中的 transform.SetSiblingIndex()方法

该方法可以更改同一层级下的子物体的顺序,当我们需要让某个clone出的子物体的显示层级不用那么大时,可以通过该方法改变子物体的顺序来实现该功能。

 transform.SetSiblingIndex(index)

2.RectTransform的布局更新

一般来说RectTransform的数据布局跟新是在Start()函数执行完后的回调函数中执行的,所以一般来说如果RectTransform中使用了content size fitter组件来自适应高度宽度的话,是无法在Start函数或者Awake函数中获取到RectTransform组件的自适应高度或者自适应宽度的,我们如果想要提前跟新RectTransorm组件的自适应高宽度的话,可以直接使用Canvas.ForceUpdateCanvases()方法强制所有画布更新其内容来RectTransform的数值。

当然这个方法也不是唯一的也可以使用的因为他很坑所有画布内容全都跟新了,Start函数回调时又得算一遍,性能开销很大,这个时候我们也可以使用LayoutRebuilder.ForceRebuildLayoutImmediate(go.GetComponent());来强制跟新所需物体,这个方法可以单独跟新一个所需的组件避免了性能上的冗余开销。

3.弹tips时如何让tips根据点击位置自动适应屏幕的左右显示

将世界坐标转化为屏幕坐标,返回一个Vector3类型的参数,然后计算屏幕的中心位置,Screen.width是屏幕宽度的最大值,根据这个临界值来判断传入的点的位置时处于屏幕的左边还是右边来判断显示的tips弹窗是显示在哪边,高度同理。

	local pos = UIManager.UICamera:WorldToScreenPoint(self.ctn_RewardPreview.position)
	local center = Screen.width / 2
	local towardType = pos.x > center and "left" or "right"

4.如何将特效绑定到Spine骨骼上

spine提供了一个BoneFollower的组件,可以将gameObject绑定在spine骨骼上面。

5.激活或者/禁用动画状态

可以通过animator控制器中的参数来激活动画

Animator animator = GetComponent<Animator>();
//替换控制器中的Trigger
animator.SetTrigger("Name")
Animator animator = GetComponent<Animator>();
//设置bool变量开启或关闭动画
animator.SetBool("Name", true)
Animator animator = GetComponent<Animator>();
//禁用animator组件来暂停或恢复动画的播放
animator.enabled = false

6.使用Dotween组件来实现icon顺时针或者逆时针的晃动效果

实现此功能我们一般使用Dotween组件中的通用的DoShakeRotation方法,这个方法中含有六个参数

---晃动时间,晃动强度Vec3, 震动次数,晃动角度,是否平滑淡出,随机类型(Full完全随机, Harmonic平衡的模式)
tran:DoShakeRotation(shakeDuration, shakeRotation, shakeVibrate, shakeRandomNess, fadeOut, randomNessMode)

7.table.sort()方法使用的注意事项

table.sort()方法使用时必须是连续的非空table,否则会报错,两个数比较的时候如果相等一定要返回false,否则会报错。

8.使用scrollView的注意

主要有几个需要注意的属性如下:

  1. Movement Type:共有Unrestricted、Elastic 或 Clamped三种模式。使用 Elastic 或 Clamped 可强制内容保持在滚动矩形的边界内。Elastic 模式在内容到达滚动矩形边缘时弹回内容。
  2. Elasticity:Elastic 模式的反弹量。
  3. Inertia:如果设置 Inertia,则拖动指针再松开时内容将继续移动。如果未设置 Inertia,则只有进行拖动时内容才移动。(一般是建议点上)
  4. 当我们需要切换scrollView的滑动条时,可以更改scrollRect的verticalNormalizedPosition属性和horizontalNormalizedPosition属性,这两个属性的区间都在[0, 1]之间,需要滑动列表置顶时把这个值改为1,需要滑到底部时设置为0。

主要事件只有OnValueChanged:滚动矩形的滚动位置发生变化时调用的 UnityEvent。该事件可将当前滚动位置作为 Vector2 类型动态参数发送。(可以传当前的滚动位置)

9.游戏开发过程中碰到多语言需要截断一定宽度内的字体加上省略号

其实就是把字符串循环一遍,累加判断有没有超过当前的最大宽度,如果超了直接截取加上省略号,如果没超过就直接显示。由于我们项目涉及多语言开发,所以只能通过字节数来判断是什么语言,避免多语言时一个字符被截成两半。

function class:SetTextInWidth(textGo, text, maxLength)
    local maxWidth = maxLength or textGo:GetComponent(typeof(RectTransform)).rect.width - 35
    textGo.text = text

    local preferredWidth = textGo.preferredWidth
    if preferredWidth > maxWidth then
        local truncatedText = self:TruncateText(text, maxWidth, textGo)
        textGo.text = truncatedText .. "..."
    end
end


function class:TruncateText(text, maxWidth, textGo)
    local start = 1
    local finish = #text
    local result = text

    -- 获取截断的文本
    while start <= finish do
        local mid = math.floor((start + finish) / 2)
        local testText = StrUtil.GetSubStringUtf8(text, 1, mid)
        textGo.text = testText

        local width = textGo.preferredWidth

        if width > maxWidth then
            finish = mid - 1
        else
            result = testText
            start = mid + 1
        end
    end

    return result
end

-- 0xxxxxxx - 1 byte
-- 110yxxxx - 192, 2 byte
-- 1110yyyy - 225, 3 byte
-- 11110zzz - 240, 4 byte
local function checkSize(char)
    if not char then
        print("not char")
        return 0
    elseif char > 240 then
        return 4
    elseif char > 225 then
        return 3
    elseif char > 192 then
        return 2
    else
        return 1
    end
end

function StrUtil.GetSubStringUtf8(str, startChar, numChars)
    local startIndex = 1
    while startChar > 1 do
        local char = string.byte(str, startIndex)
        startIndex = startIndex + checkSize(char)
        startChar = startChar - 1
    end

    local currentIndex = startIndex

    while numChars > 0 and currentIndex <= #str do
        local char = string.byte(str, currentIndex)
        currentIndex = currentIndex + checkSize(char)
        numChars = numChars -1
    end
    return str:sub(startIndex, currentIndex - 1)
end
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值