9

主题

17

回帖

881

积分

优秀创作者

积分
881

夏日·闪闪发光勋章

发表于  2023-6-19 15:36:12 | 显示全部楼层 |阅读模式 3656 6
本帖最后由 无名拉二胡#7884 于 2023-6-21 10:32 编辑

首先介绍下帧回调事件是什么
y3地图的运行分为渲染帧和机制帧,机制帧即所有功能运行的时间间隔,默认是一秒30次,而渲染帧是所有画面渲染的时间间隔,一般高于60人眼才会觉得流畅舒服,30会让人有卡顿感
因此就需要咱们在特定情况下使用渲染帧而不是机制帧。y3为了保护新手,目前没有在ECA开放渲染帧的接口,因为渲染看每个人电脑的配置,大家渲染的帧数是有差异的哈,比如你用的4090还配了144高刷显示器,你肯定比我渲染的快多了
所以一些动作,比如ui动画,一些特效的移动等可以考虑用渲染帧来操作(必须不影响同步,不影响伤害事件的)

y3的帧回调依赖开局的OnTick函数,但是他只会在初始化前执行一次,不方便添加事件,因此可以考虑用table和模拟事件id来做个事件管理
思路就是 每帧回调,即每次OnTick执行的时候,遍历一遍表格,执行里面的function,如果不想再用这个function了,就在table里去掉它


FreshEvents={EventList={},indexes={},N=0} --帧回调事件的总表
   
    L8FEventTab={}--帧回调事件的参数表
    L8FFucEvent="1" --正在运行的事件名称,不指定则默认字符串数字
   
    L8FEventId=0  --帧回调事件id
   
   
  
   
   -------Restart主要用于需要调用的关闭的$Add的为不需要关闭的------------------------------------------------------------
   
    function FreshEvents:Add(funcname) --给每帧绘制添加function$返回function事件的名称或自动序号
   
        FreshEvents.N=FreshEvents.N+1
        L8FEventId=L8FEventId+1
        local Eventname=tostring(L8FEventId) --事件id只会无限增加$永远不重复
        FreshEvents.indexes[Eventname]=FreshEvents.N --事件id的序号
        
        FreshEvents.EventList[FreshEvents.N]={func=funcname,index=Eventname}--事件信息存储
        
        --通过变量名检索事件
        
        return(Eventname)--返回每帧绘制事件的名称
    end
   
    function FreshEvents:Restart(funcname,Eventname) --按照指定id绑定每帧绘制事件并$重置事件(如果存在就重置$不存在则新建)
       --最好这个用非顺序排列字符串eventname$方便区分
        
        local index= FreshEvents.indexes[Eventname]
        if index==nil then
            FreshEvents.N=FreshEvents.N+1
            index=FreshEvents.N
        end
        FreshEvents.indexes[Eventname]=index --事件id的序号
        FreshEvents.EventList[index ]= {func=funcname,index=Eventname}--事件信息存储
        return(Eventname)
    end
   
    function FreshEvents:Bond(Eventname,tab) --给没帧绘制事件绑定一张表格
        L8FEventTab[Eventname]=Copytable(tab)
   
    end

    function FreshEvents:Clear() --清理掉所有废物事件
        local NewEventList={}
        local NewEventListN=0
        FreshEvents.indexes={} --删除原索引检索序列
        for _,v in pairs(FreshEvents.EventList) do
            if v.delete==nil then --如果没有被标记删除
                NewEventListN=NewEventListN+1  --数量加1
                NewEventList[NewEventListN]= Copytable(v)--复制表格
               
               
                FreshEvents.indexes[v.index]=NewEventListN --存储检索id序列
            else
                L8FEventTab[v.index]=nil --删除事件对应的表格
            end
        end
        FreshEvents.EventList=NewEventList --重建表格
        FreshEvents.N=NewEventListN --次数刷新
      
     
    end
    function FreshEvents:Delete(Eventname) --计时器结束后删除名称为Eventname的事件
        Eventname=Eventname or L8FFucEvent
       local index=FreshEvents.indexes[Eventname] --获取序号
       if index~=nil then
        FreshEvents.EventList[index].delete=true --标记删除
        
       end
      
   
    end

    FreshLoop=function() --新lua计时器$不再挂载事件$而是挂载函数
      
        for _,v in pairs(FreshEvents.EventList) do --逐个运行时事件
            if v~=nil then --逐一考虑挂载事件$如果事件没有被删除
                local func=v.func --事件的函数
                L8FFucEvent=v.index --正在执行的事件名称
               
                func() --执行函数
                end
        FreshEvents:Clear() --清理掉循环结束或者手动结束的Event
        end
    end
Stime=0
Sdelta=0
function OnTick(deltaTime)
    Stime=Stime+deltaTime
    Sdelta=Sdelta+deltaTime
    if Sdelta>0.012 then --防止帧数过高炸裂
        FreshLoop()
        Sdelta=0
    end
end
   







9

主题

17

回帖

881

积分

优秀创作者

积分
881

夏日·闪闪发光勋章

发表于  2023-6-19 15:37:58 | 显示全部楼层
本帖最后由 无名拉二胡#7884 于 2023-6-19 15:40 编辑


   用法:
比如我要做一个ui的跳跃动画
local t0=Stime --记录本地开始时间

    FreshEvents:Restart(
    function()
        local t=(Stime-t0)/CD--逝去时间
      
        local x=offset1.x*t+offset0.x*(1-t)
        local y=offset1.y*t+offset0.y*(1-t)
        local z=offset1.z*t+offset0.z*(1-t)
       --移动ui到x,y,z
        if t>1 then
            FreshEvents:Delete() --到期删除ui
            if endfunc~=nil then
            endfunc()
            end
        end
    end,"事件名称")

9

主题

17

回帖

881

积分

优秀创作者

积分
881

夏日·闪闪发光勋章

发表于  2023-6-21 10:30:27 | 显示全部楼层
FreshEvents={EventList={},indexes={},N=0} --帧回调事件的总表
   
    L8FEventTab={}--帧回调事件的参数表
    L8FFucEvent="1" --正在运行的事件名称,不指定则默认字符串数字
   
    L8FEventId=0  --帧回调事件id
   
   
  
   
   -------Restart主要用于需要调用的关闭的$Add的为不需要关闭的------------------------------------------------------------
   
    function FreshEvents:Add(funcname) --给每帧绘制添加function$返回function事件的名称或自动序号
   
        FreshEvents.N=FreshEvents.N+1
        L8FEventId=L8FEventId+1
        local Eventname=tostring(L8FEventId) --事件id只会无限增加$永远不重复
        FreshEvents.indexes[Eventname]=FreshEvents.N --事件id的序号
        
        FreshEvents.EventList[FreshEvents.N]={func=funcname,index=Eventname}--事件信息存储
        
        --通过变量名检索事件
        
        return(Eventname)--返回每帧绘制事件的名称
    end
   
    function FreshEvents:Restart(funcname,Eventname) --按照指定id绑定每帧绘制事件并$重置事件(如果存在就重置$不存在则新建)
       --最好这个用非顺序排列字符串eventname$方便区分
        
        local index= FreshEvents.indexes[Eventname]
        if index==nil then
            FreshEvents.N=FreshEvents.N+1
            index=FreshEvents.N
        end
        FreshEvents.indexes[Eventname]=index --事件id的序号
        FreshEvents.EventList[index ]= {func=funcname,index=Eventname}--事件信息存储
        return(Eventname)
    end
   
    function FreshEvents:Bond(Eventname,tab) --给没帧绘制事件绑定一张表格
        L8FEventTab[Eventname]=Copytable(tab)
   
    end
   
   
   
    function FreshEvents:Clear() --清理掉所有废物事件
        local NewEventList={}
        local NewEventListN=0
        FreshEvents.indexes={} --删除原索引检索序列
        for _,v in pairs(FreshEvents.EventList) do
            if v.delete==nil then --如果没有被标记删除
                NewEventListN=NewEventListN+1  --数量加1
                NewEventList[NewEventListN]= Copytable(v)--复制表格
               
               
                FreshEvents.indexes[v.index]=NewEventListN --存储检索id序列
            else
                L8FEventTab[v.index]=nil --删除事件对应的表格
            end
        end
        FreshEvents.EventList=NewEventList --重建表格
        FreshEvents.N=NewEventListN --次数刷新
      
     
    end
    function FreshEventselete(Eventname) --计时器结束后删除名称为Eventname的事件
        Eventname=Eventname or L8FFucEvent
       local index=FreshEvents.indexes[Eventname] --获取序号
       if index~=nil then
        FreshEvents.EventList[index].delete=true --标记删除
        
       end
      
   
    end
   

    FreshLoop=function() --新lua计时器$不再挂载事件$而是挂载函数
      
        for _,v in pairs(FreshEvents.EventList) do --逐个运行时事件
            if v~=nil then --逐一考虑挂载事件$如果事件没有被删除
                local func=v.func --事件的函数
                L8FFucEvent=v.index --正在执行的事件名称
               
                func() --执行函数
            
                end
      
        FreshEvents:Clear() --清理掉循环结束或者手动结束的Event
        end
    end

   
Stime=0
Sdelta=0


function OnTick(deltaTime)
    Stime=Stime+deltaTime
    Sdelta=Sdelta+deltaTime
    if Sdelta>0.012 then --防止帧数过高炸裂
        FreshLoop()
        Sdelta=0
    end
end
   





9

主题

17

回帖

881

积分

优秀创作者

积分
881

夏日·闪闪发光勋章

发表于  2023-6-21 10:31:02 | 显示全部楼层
FreshEvents={EventList={},indexes={},N=0} --帧回调事件的总表
   
    L8FEventTab={}--帧回调事件的参数表
    L8FFucEvent="1" --正在运行的事件名称,不指定则默认字符串数字
   
    L8FEventId=0  --帧回调事件id
   
   
  
   
   -------Restart主要用于需要调用的关闭的$Add的为不需要关闭的------------------------------------------------------------
   
    function FreshEvents:Add(funcname) --给每帧绘制添加function$返回function事件的名称或自动序号
   
        FreshEvents.N=FreshEvents.N+1
        L8FEventId=L8FEventId+1
        local Eventname=tostring(L8FEventId) --事件id只会无限增加$永远不重复
        FreshEvents.indexes[Eventname]=FreshEvents.N --事件id的序号
        
        FreshEvents.EventList[FreshEvents.N]={func=funcname,index=Eventname}--事件信息存储
        
        --通过变量名检索事件
        
        return(Eventname)--返回每帧绘制事件的名称
    end
   
    function FreshEvents:Restart(funcname,Eventname) --按照指定id绑定每帧绘制事件并$重置事件(如果存在就重置$不存在则新建)
       --最好这个用非顺序排列字符串eventname$方便区分
        
        local index= FreshEvents.indexes[Eventname]
        if index==nil then
            FreshEvents.N=FreshEvents.N+1
            index=FreshEvents.N
        end
        FreshEvents.indexes[Eventname]=index --事件id的序号
        FreshEvents.EventList[index ]= {func=funcname,index=Eventname}--事件信息存储
        return(Eventname)
    end
   
    function FreshEvents:Bond(Eventname,tab) --给没帧绘制事件绑定一张表格
        L8FEventTab[Eventname]=Copytable(tab)
   
    end
   
   
   
    function FreshEvents:Clear() --清理掉所有废物事件
        local NewEventList={}
        local NewEventListN=0
        FreshEvents.indexes={} --删除原索引检索序列
        for _,v in pairs(FreshEvents.EventList) do
            if v.delete==nil then --如果没有被标记删除
                NewEventListN=NewEventListN+1  --数量加1
                NewEventList[NewEventListN]= Copytable(v)--复制表格
               
               
                FreshEvents.indexes[v.index]=NewEventListN --存储检索id序列
            else
                L8FEventTab[v.index]=nil --删除事件对应的表格
            end
        end
        FreshEvents.EventList=NewEventList --重建表格
        FreshEvents.N=NewEventListN --次数刷新
      
     
    end
    function FreshEventselete(Eventname) --计时器结束后删除名称为Eventname的事件
        Eventname=Eventname or L8FFucEvent
       local index=FreshEvents.indexes[Eventname] --获取序号
       if index~=nil then
        FreshEvents.EventList[index].delete=true --标记删除
        
       end
      
   
    end
   

    FreshLoop=function() --新lua计时器$不再挂载事件$而是挂载函数
      
        for _,v in pairs(FreshEvents.EventList) do --逐个运行时事件
            if v~=nil then --逐一考虑挂载事件$如果事件没有被删除
                local func=v.func --事件的函数
                L8FFucEvent=v.index --正在执行的事件名称
               
                func() --执行函数
            
                end
      
        FreshEvents:Clear() --清理掉循环结束或者手动结束的Event
        end
    end

   
Stime=0
Sdelta=0


function OnTick(deltaTime)
    Stime=Stime+deltaTime
    Sdelta=Sdelta+deltaTime
    if Sdelta>0.012 then --防止帧数过高炸裂
        FreshLoop()
        Sdelta=0
    end
end
   

发表于  2023-6-25 12:42:22 | 显示全部楼层
太强了,必须给个点赞

53

主题

102

回帖

2369

积分

精英创作者

积分
2369

夏日·活跃之王勋章

发表于  2023-6-25 15:38:13 | 显示全部楼层
66666666666666666666

0

主题

19

回帖

146

积分

普通创作者

积分
146
发表于  2023-7-11 18:06:38 | 显示全部楼层
厉害了,开发游戏的时候从来没注意过帧数的问题