unity ugui剧情文本渐隐弹出实现

效果

galgame中很常见的文字弹出加渐隐出现的动效,这个动效没办法交给美术做。
在这里插入图片描述

思路

Text作为一个整体,没有办法获取到其中的任意一个字符,成了最难突破的地方,只能把Text组件作为整体来控制,当然N个Text组件,每个控制一个字符倒是也能实现,稍加一些优化简直是活字印刷术。但这种方法效率实在太差了,没办法采用。

unity ugui剧情文本渐隐弹出实现_第1张图片

放一张图,看一眼大概就知道核心思路是什么了。

原理是开一个协程,在每一帧将原来的字符串转化为带有富文本标记的字符串,然后在富文本标记中设定每一个文字在每一帧的透明度。

代码

核心代码如下,本次采用lua写的,过程可以参考一下

--用于拼接透16进制的透明度值
local Hex = { "0", "1", "2", "3",
              "4", "5", "6", "7",
              "8", "9", "A", "B",
              "C", "D", "E", "F" }
local Format = "{1}"
--渐变的光标以每秒36个字符的速度向后移动
local kTravelSpeed = 36
--渐变动画时长0.1秒
local kFadeDuration = 0.1
--参与渐变动画的字符数量
local kFadeCharCount = kTravelSpeed * kFadeDuration
--- @brief 播放文本过程
--- @public
function AVGTextPanel:PlayTextProcessing()
    self.isPlaying = true
    --源字符串长度
    local strLength = utf8.len(self.str)
    --富文本化字符串table
    local richStrTable = {}
    local charTable = {}
    for i = 1, strLength do
        --字符串中的每一个字符
        local char = utf8.sub(self.str, i, i + 1)
        table.insert(charTable, char)
        --为每个字符添加富文本标记 所有文字透明度为0
        local utf8RichChar = formatex(Format, formatex("#{0}{1}{2}", self.color, Hex[1], Hex[1]), char)
        table.insert(richStrTable, utf8RichChar)
    end
    --加入富文本格式后的字符串
    local richStr = table.concat(richStrTable, nil, 1, #richStrTable)
    --强制重绘当前ui自适应后的尺寸
    self.compText.text = richStr
    LayoutRebuilder.ForceRebuildLayoutImmediate(self.transform)
    local hasPlayedCharCount = 0 --已经完成渐变动画的字符数量
    local currentTime = 0 --当前经过的时间
    --存在字符未完成渐变动画
    while (hasPlayedCharCount < strLength) do
        self:WaitForSeconds(Time.deltaTime)
        currentTime = currentTime + Time.deltaTime
        --最后一个正在渐变的字符的位置
        local lastFadingCharPos = currentTime * kTravelSpeed
        --最后一个正在渐变的字符的索引
        local lastFadingCharIndex = math.floor(lastFadingCharPos)
        --对越界进行修正 索引最小为1
        local fixLastFadingCharIndex = Mathf.Min(strLength, lastFadingCharIndex)
        fixLastFadingCharIndex = Mathf.Max(1, fixLastFadingCharIndex)
        --循环中需要改变值 缓存一份数据
        local cacheHasPlayedCharCount = hasPlayedCharCount
        --遍历参与渐变的字符
        for i = fixLastFadingCharIndex, cacheHasPlayedCharCount, -1 do
            --透明度值
            local fadeValue = 255 * Mathf.Clamp01((lastFadingCharPos - i) / kFadeCharCount)
            local hex1 = math.floor(fadeValue / 16)
            local hex2 = math.floor(fadeValue % 16)
            richStrTable[i] = formatex(Format, formatex("#{0}{1}{2}", self.color, Hex[hex1 + 1], Hex[hex2 + 1]), charTable[i])
            --更新已经完成渐变动画的字符数量
            if fadeValue == 255 then
                hasPlayedCharCount = Mathf.Max(hasPlayedCharCount, i)
            end
        end
        richStr = table.concat(richStrTable, nil, 1, #richStrTable)
        self.compText.text = richStr
    end
    self:StopPlay()
end

你可能感兴趣的:(unity)