unity实战之弹幕功能

简介: 使用unity也可以实现追剧弹幕效果

前言

最近项目需要加一个弹幕的功能。天天追剧的我,对于弹幕这个东西简直不要太熟悉,但是突然让做一个这样一个功能,还是有点戳手不及。
先来欣赏一个视频网站上的弹幕吧,如下:

UI

创建按钮,命名为barrage_btn,用于控制弹幕的开关,下面有2张图片,分别命名为hideImg和showImg,用于显示弹幕开关的状态
创建发射弹幕按钮,命名为shoot_btn。
创建输入框input_barrage
创建弹幕移动载体(父类)barrageBg
1.png

代码

local ui = nil
local barrageProto = {
[1] = { word = "哈哈哈哈", },
[2] = { word = "小可爱来了", },
[3] = { word = "终于上线了", },
[4] = { word = "小木好逗啊", },
[5] = { word = "我永远喜欢做游戏", },
[6] = { word = "爱上游戏开发登场了", },
[7] = { word = "为Unity而来", },
}
local barragePool = {}
local barrageLineY = {-100, 0, 100, 150, 200, 250, 300}--从上到下每行弹幕位置
local myBarrage = {}

function herotalent:start()
    ui = {}
    ui.shootBtn = base:findobj("barrage_btn")
    utils.addclickevent(ui.shootBtn, base.ShootBarrage)
    ui.inputBarrage = base:findinput("input_barrage")
    ui.inputBarrage.characterLimit = 20--每条弹幕的字数限制
    ui.inputBarrageObj = base:findobj("bg")
    ui.barrage_btn = base:findobj("barrage_btn")
    utils.addclickevent(ui.barrage_btn, base.ClickCloseBarrageBtn)
    ui.closeBarrageObj = base:findobj("barrage_btn/hideImg")
    ui.showBarrageObj = base:findobj("barrage_btn/showImg")
    ui.barrageBgRect = base:findrect("barrageBg")
    ui.startPointObj = base:findobj("startPoint")
end

function herotalent:commit()
    ui.barrageBgRect.gameObject.transform:DOLocalMoveX(-8000, 68)
    base.RefreshUI()
end

function herotalent.RefreshUI()
    base.CreateBarragePool()
end

function base.ClickCloseBarrageBtn()
    SetActive(ui.closeBarrageObj, not ui.closeBarrageObj.activeInHierarchy)
    SetActive(ui.showBarrageObj, not ui.showBarrageObj.activeInHierarchy)
    SetActive(ui.inputBarrageObj, not ui.closeBarrageObj.activeInHierarchy)
    corStopBol = not ui.closeBarrageObj.activeInHierarchy
    if ui.closeBarrageObj.activeInHierarchy then 
        coroutine.resume(base.barCor)
    end
end

function base.ShootBarrage()
    if ui.inputBarrage.text ~= nil and ui.inputBarrage.text ~= "" then 
        if pb.isWarningInPutStr(ui.inputBarrage.text) then 
            printlog("弹幕内容包含违规字")
        else
            table.insert(myBarrage, ui.inputBarrage.text)
            base.ClickCloseBarrageBtn()
        end
        ui.inputBarrage.text = ""
    end
end

function base.CreateBarragePool()
    local randomseed = 10000 --随机种子
    math.randomseed(randomseed)
    local totalNum = table.tablelen(barrageProto)
    local time = 50
    local clearTime = 2
    local barrageGroup = {}
    base.barCor = coroutine.start(function()
        while time > 0 do 
            local waitTime = math.random(0, 1.0)
            while waitTime > 0 do
                waitTime = waitTime - 0.2
                time = time - 0.2
                clearTime = clearTime - 0.2
                coroutine.wait(0.2)
                if corStopBol then 
                    DOTween.Pause(ui.barrageBgRect.gameObject.transform)
                    coroutine.yield()
                    DOTween.Play(ui.barrageBgRect.gameObject.transform)
                end
            end
            local startPoint = ui.barrageBgRect.gameObject.transform:InverseTransformPoint(ui.startPointObj.transform.position)
            local index = 7
            local barText = nil
            local myBarrageBol = false
            if #myBarrage > 0 then 
                barText = myBarrage[1]
                for i = 6, 1, -1 do
                    if barragePool[i] then
                        local sizeX = barragePool[i]:GetComponent("RectTransform").sizeDelta.x / 2
                        if startPoint.x - barragePool[i].transform.localPosition.x > sizeX then 
                            index = i
                            break
                        end
                    else
                        index = i
                        break
                    end
                end
                myBarrageBol = true
            else
                local line = math.random(1, 6)
                barText = barrageProto[math.random(1, totalNum)].word
                if barragePool[line] then 
                    local sizeX = barragePool[line]:GetComponent("RectTransform").sizeDelta.x / 2
                    if startPoint.x - barragePool[line].transform.localPosition.x > sizeX then 
                        index = line
                    else
                        index = nil
                    end
                else
                    index = line
                end
            end
            if index then 
                local barObj = poolManager.AddObj("Modules/login/barrage.prefab", ui.barrageBgRect.gameObject)
                table.insert(barrageGroup, barObj)
                barObj:GetComponent("Text").text = barText
                UnityEngine.UI.LayoutRebuilder.ForceRebuildLayoutImmediate(barObj:GetComponent("RectTransform"))
                barObj.transform.localPosition = Vector2.New(startPoint.x + barObj:GetComponent("RectTransform").sizeDelta.x / 2, barrageLineY[index])
                barragePool[index] = barObj
                if myBarrageBol then 
                    table.remove(myBarrage, 1)
                end
            end
            local clearIndex = {}
            if clearTime <= 0 then
                for k, v in ipairs(barrageGroup) do 
                    local tempX = v:GetComponent("RectTransform").sizeDelta.x * 2
                    if startPoint.x - v.transform.localPosition.x > tempX + 1440 then 
                        poolManager.RemoveObj("Modules/login/barrage.prefab", v)
                        table.insert(clearIndex, k)
                    end
                end
                if #clearIndex > 0 then 
                    for i = #clearIndex, 1, -1 do
                        table.remove(barrageGroup, clearIndex[i])
                    end
                end
                clearTime = 2
            end
        end
    end)
end

效果

运行效果如下:
6655546.gif

相关文章
|
11月前
|
小程序 PHP 图形学
热门小游戏源码(Python+PHP)下载-微信小程序游戏源码Unity发实战指南​
本文详解如何结合Python、PHP与Unity开发并部署小游戏至微信小程序。涵盖技术选型、Pygame实战、PHP后端对接、Unity转换适配及性能优化,提供从原型到发布的完整指南,助力开发者快速上手并发布游戏。
|
12月前
|
C# 图形学 开发者
【Unity3D实例-功能-镜头】俯视角
本文介绍了Unity中常用的俯视角镜头实现方法,涵盖模型添加、角色Tag设置、摄像机脚本编写及测试运行,帮助开发者快速掌握俯视角在策略与模拟类游戏中的应用技巧。
625 0
|
12月前
|
人工智能 定位技术 C#
【Unity3D实例-功能-移动】通过鼠标点击进行角色移动
本文介绍了如何在Unity中实现鼠标点击控制角色移动的功能。通过安装导航网格、设置地图与角色、烘焙路径及编写脚本,带领读者一步步构建角色自动寻路系统,增强游戏交互体验。
536 0
|
C# 图形学 开发者
【Unity3D实例-功能-移动】复杂移动(Blend Tree方式)
本文介绍了使用Unity中Blend Tree实现角色移动控制的完整教程,涵盖动画器设置、Blend Tree创建、CharacterController组件添加及代码控制,帮助开发者实现流畅自然的角色动画效果。
371 0
|
图形学 开发者
【Unity3D实例-功能-移动】角色移动-通过WSAD(CharacterController方式)
本文介绍了如何在Unity中使用CharacterController组件实现角色灵活移动。内容包括模型准备、动画处理、添加组件、编写移动脚本及测试运行,帮助开发者快速掌握角色控制技巧,打造流畅的游戏体验。
564 0
|
C# 图形学 开发者
【Unity3D实例-功能-移动】角色移动-通过WSAD(Rigidbody方式)
本文介绍了如何在Unity中使用Rigidbody组件实现角色自由移动,包括模型准备、组件添加、脚本编写与测试运行,帮助开发者快速掌握基础角色控制技巧。
509 0
|
C# 图形学
【Unity3D实例-功能-移动】角色移动-通过WSAD(Transform方式)
本文介绍了如何在Unity中实现角色移动功能,使用Transform组件控制角色基础移动,并详细讲解了模型导入、动画设置、动画控制器配置及移动脚本编写等内容,适合Unity初学者学习角色控制的基础知识。
495 0
|
图形学 UED
unity Tab键实现切换输入框功能
该脚本用于简化输入框之间的Tab键切换操作。只需将脚本挂载在InputField上,无需其他设置。脚本通过监听Tab键和Shift键组合,自动选择下一个或上一个可交互的InputField,提升用户体验。
|
开发者 图形学 API
从零起步,深度揭秘:运用Unity引擎及网络编程技术,一步步搭建属于你的实时多人在线对战游戏平台——详尽指南与实战代码解析,带你轻松掌握网络化游戏开发的核心要领与最佳实践路径
【8月更文挑战第31天】构建实时多人对战平台是技术与创意的结合。本文使用成熟的Unity游戏开发引擎,从零开始指导读者搭建简单的实时对战平台。内容涵盖网络架构设计、Unity网络API应用及客户端与服务器通信。首先,创建新项目并选择适合多人游戏的模板,使用推荐的网络传输层。接着,定义基本玩法,如2D多人射击游戏,创建角色预制件并添加Rigidbody2D组件。然后,引入网络身份组件以同步对象状态。通过示例代码展示玩家控制逻辑,包括移动和发射子弹功能。最后,设置服务器端逻辑,处理客户端连接和断开。本文帮助读者掌握构建Unity多人对战平台的核心知识,为进一步开发打下基础。
1257 0
|
图形学 C++ C#
Unity插件开发全攻略:从零起步教你用C++扩展游戏功能,解锁Unity新玩法的详细步骤与实战技巧大公开
【8月更文挑战第31天】Unity 是一款功能强大的游戏开发引擎,支持多平台发布并拥有丰富的插件生态系统。本文介绍 Unity 插件开发基础,帮助读者从零开始编写自定义插件以扩展其功能。插件通常用 C++ 编写,通过 Mono C# 运行时调用,需在不同平台上编译。文中详细讲解了开发环境搭建、简单插件编写及在 Unity 中调用的方法,包括创建 C# 封装脚本和处理跨平台问题,助力开发者提升游戏开发效率。
1981 0

热门文章

最新文章