找回密码
 点一下
查看: 7741|回复: 20

触发器执行研究 V1.1

[复制链接]
发表于 2006-4-14 01:38:08 | 显示全部楼层 |阅读模式
名称:触发器执行研究
作者:zyl910
版本:V1.1.0
日期:2006-4-14


内容
~~~~

一、触发器中代码执行次数限制

  我一直对loop循环次数限制的说法存在怀疑,所以先研究这个。

  先找来一个运算量很大的函数logE_core,进行循环计算,看看会在那个地方终止:

function Trig_Test1_run0_maxloop_Actions takes nothing returns nothing
    set udg_iCount = 0
    set udg_fTemp = 1.0
    loop
        exitwhen udg_iCount >= 10000
        call logE_core(udg_fTemp)
        set udg_fTemp = udg_fTemp + 1.0
        set udg_iCount = udg_iCount + 1
    endloop
endfunction


  调用TriggerExecute函数执行该触发器。
  执行后发现udg_iCount的值是78,表示该循环只执行了78次。


  知道这个循环只能执行78次,那么我们把它拆成两个执行70次的循环:

function Trig_Test1_run0_maxloop_Actions takes nothing returns nothing
    set udg_iCount = 0
    set udg_fTemp = 1.0
    loop
        exitwhen udg_iCount >= 70
        call logE_core(udg_fTemp)
        set udg_fTemp = udg_fTemp + 1.0
        set udg_iCount = udg_iCount + 1
    endloop
    loop
        exitwhen udg_iCount >= 140
        call logE_core(udg_fTemp)
        set udg_fTemp = udg_fTemp + 1.0
        set udg_iCount = udg_iCount + 1
    endloop
endfunction


  执行后发现udg_iCount的值仍是78。

  啊哈!我明白了。
  并不是loop有执行次数限制,而是触发器有代码执行次数限制。




二、TriggerSleepAction会重置代码执行次数

  将测试代码和测试触发器改成:

function Trig_Test1_run0_maxloop_Actions takes nothing returns nothing
    set udg_iCount = 0
    set udg_fTemp = 1.0
    loop
        exitwhen udg_iCount >= 70
        call logE_core(udg_fTemp)
        set udg_fTemp = udg_fTemp + 1.0
        set udg_iCount = udg_iCount + 1
    endloop
    call TriggerSleepAction(0)
    call BJDebugMsg("Next")
    loop
        exitwhen udg_iCount >= 140
        call logE_core(udg_fTemp)
        set udg_fTemp = udg_fTemp + 1.0
        set udg_iCount = udg_iCount + 1
    endloop
endfunction


//===========================================================================
function InitTrig_Test1_run0_maxloop takes nothing returns nothing
    set gg_trg_Test1_run0_maxloop = CreateTrigger(  )
    call DisableTrigger( gg_trg_Test1_run0_maxloop )
    call TriggerAddAction( gg_trg_Test1_run0_maxloop, function Trig_Test1_run0_maxloop_Actions )
endfunction

Test1 maxloop
    事件
        Player - 玩家 1 (红色) 选择 a unit
    环境
        (Triggering unit) 等于 血魔法师 0001 <gen>
    动作
        Selection - Clear selection for (Triggering player)
        Game - Display to (All players) the text: [Test 1] intloop
        -------- Begin --------
        Game - Display to (All players) the text: (Begin:  + (String(iCount)))
        Set trgTemp = Test1 run0 maxloop <gen>
        Custom script: call TriggerExecuteWait(udg_trgTemp)
        Game - Display to (All players) the text: (Count:  + (String(iCount)))
        -------- End --------
        Game - Display to (All players) the text:  


  执行结果为:

[Test 1] intloop
Begin: 0
Count: 70

Next
[Test 1] intloop
Begin: 108
Count: 70

Next


  以上是两次测试的结果,从第二次测试时Begin为108来看:当执行过TriggerSleepAction语句后会重置代码执行次数。




三、TriggerWaitOnSleeps、TriggerExecuteWait研究

  一直不理解TriggerWaitOnSleeps、TriggerExecuteWait这两个函数的作用。趁此机会研究一下。

  先调用IsTriggerWaitOnSleeps,发现触发器默认情况下返回false。

  将测试代码改成:

Test1 maxloop
    事件
        Player - 玩家 1 (红色) 选择 a unit
    环境
        (Triggering unit) 等于 血魔法师 0001 <gen>
    动作
        Selection - Clear selection for (Triggering player)
        Game - Display to (All players) the text: [Test 1] intloop
        -------- Begin --------
        Game - Display to (All players) the text: (Begin:  + (String(iCount)))
        Set trgTemp = Test1 run0 maxloop <gen>
        Custom script: call TriggerWaitOnSleeps(udg_trgTemp, true)
        Custom script: call TriggerExecuteWait(udg_trgTemp)
        Game - Display to (All players) the text: (Count:  + (String(iCount)))
        -------- End --------
        Game - Display to (All players) the text:  


  可是奇怪的是:无论怎么设置TriggerWaitOnSleeps,无论调用TriggerExecute还是TriggerExecuteWait,执行结果都是与先前一样的。
  百思不得其解,似乎这两个函数根本没用

  突然灵光一闪,也许TriggerWaitOnSleeps并不是对“TriggerExecuteWait调用的触发器”有效的,而是对“调用TriggerExecuteWait函数的触发器”有效。然后修改触发器:

Test1 maxloop
    事件
        Player - 玩家 1 (红色) 选择 a unit
    环境
        (Triggering unit) 等于 血魔法师 0001 <gen>
    动作
        Selection - Clear selection for (Triggering player)
        Game - Display to (All players) the text: [Test 1] intloop
        -------- Begin --------
        Game - Display to (All players) the text: (Begin:  + (String(iCount)))
        Set trgTemp = (This trigger)
        Custom script: call TriggerWaitOnSleeps(udg_trgTemp, true)
        Set trgTemp = Test1 run0 maxloop <gen>
        Custom script: call TriggerExecuteWait(udg_trgTemp)
        Game - Display to (All players) the text: (Count:  + (String(iCount)))
        -------- End --------
        Game - Display to (All players) the text:  

  测试结果为:
[Test 1] intloop
Begin: 0
Count: 70

Next
[Test 1] intloop
Begin: 108
Next
Count: 108

  啊哈!TriggerExecuteWait终于有效果了。看来必须为TriggerExecuteWait的调用者触发器设置TriggerWaitOnSleeps,而不是被调用者。
  注意第一次的执行结果仍是老样子,表示TriggerWaitOnSleeps对于已执行的触发器无效。



四、当TriggerWaitOnSleeps设置为false时,TriggerExecute在其执行的触发器中遇到TriggerSleepAction、TriggerExecute、TriggerExecuteWait就立即返回

  又编写了一个测试触发器:

Test2 GUIExec
    事件
        Player - 玩家 1 (红色) 选择 a unit
    环境
        (Triggering unit) 等于 大魔法师 0002 <gen>
    动作
        Selection - Clear selection for (Triggering player)
        Game - Display to (All players) the text: [Test 2] GUIrun
        -------- Begin --------
        Set trgTemp = Test1 run0 maxloop <gen>
        Custom script: call TriggerWaitOnSleeps(udg_trgTemp, false)
        Trigger - Run Test1 maxloop <gen> (ignoring conditions)
        -------- End --------
        Game - Display to (All players) the text: End


  测试结果为:
[Test 2] GUIrun
[Test 1] intloop
Begin: 0
Count: 70

End Test2
Next
[Test 2] GUIrun
[Test 1] intloop
Begin: 108
End Test2
Next
Count: 108


  对于没有TriggerWaitOnSleeps设置值为false的触发器,TriggerExecute在其执行的触发器中遇到TriggerExecute、TriggerExecuteWait就立即返回(TriggerSleepAction就更不要说了)



五、当TriggerWaitOnSleeps设置为true,TriggerExecute在其执行的触发器中遇到TriggerSleepAction、TriggerExecute、TriggerExecuteWait会等待该函数执行完毕后再返回

  将当TriggerWaitOnSleeps设置为true试试。

  测试结果为:
[Test 2] GUIrun
[Test 1] intloop
Begin: 0
Count: 70

End Test2
Next
[Test 2] GUIrun
[Test 1] intloop
Begin: 108
Next
End Test2
Count: 108


  看起来似乎与上面那个差不多。
  错!End Test2现在排在Next的后面,表示等待了那些函数,但是并没有等待触发器结束。



六、TriggerExecuteWait本身不会重置代码执行次数,只有等待过Sleep的触发器才会重置代码执行次数

  新建一个测试触发器Test_run_None:

function Trig_Test_run_None_Actions takes nothing returns nothing
    call BJDebugMsg("Begin None")
    call TriggerSleepAction(0)
    call BJDebugMsg("End None")
endfunction

//===========================================================================
function InitTrig_Test_run_None takes nothing returns nothing
    set gg_trg_Test_run_None = CreateTrigger(  )
    call DisableTrigger( gg_trg_Test_run_None )
    call TriggerAddAction( gg_trg_Test_run_None, function Trig_Test_run_None_Actions )
endfunction


  然后把测试代码改成:

function Trig_Test1_run0_maxloop_Actions takes nothing returns nothing
    set udg_iCount = 0
    set udg_fTemp = 1.0
    loop
        exitwhen udg_iCount >= 70
        call logE_core(udg_fTemp)
        set udg_fTemp = udg_fTemp + 1.0
        set udg_iCount = udg_iCount + 1
    endloop
    //call TriggerSleepAction(0)
    call TriggerExecute(gg_trg_Test_run_None) // 测试时会改动这行代码
    call BJDebugMsg("Next")
    loop
        exitwhen udg_iCount >= 140
        call logE_core(udg_fTemp)
        set udg_fTemp = udg_fTemp + 1.0
        set udg_iCount = udg_iCount + 1
    endloop
endfunction

//===========================================================================
function InitTrig_Test1_run0_maxloop takes nothing returns nothing
    set gg_trg_Test1_run0_maxloop = CreateTrigger(  )
    call DisableTrigger( gg_trg_Test1_run0_maxloop )
    call TriggerAddAction( gg_trg_Test1_run0_maxloop, function Trig_Test1_run0_maxloop_Actions )
endfunction



Test1 maxloop
    事件
        Player - 玩家 1 (红色) 选择 a unit
    环境
        (Triggering unit) 等于 血魔法师 0001 <gen>
    动作
        Selection - Clear selection for (Triggering player)
        Game - Display to (All players) the text: [Test 1] intloop
        -------- Begin --------
        Game - Display to (All players) the text: (Begin:  + (String(iCount)))
        Set trgTemp = (This trigger)
        Custom script: call TriggerWaitOnSleeps(udg_trgTemp, true)
        Set trgTemp = Test1 run0 maxloop <gen>
        Custom script: call TriggerWaitOnSleeps(udg_trgTemp, true) // 测试时会改动这行代码
        Custom script: call TriggerExecuteWait(udg_trgTemp)
        Game - Display to (All players) the text: (Count:  + (String(iCount)))
        -------- End --------
        Game - Display to (All players) the text:  


  WaitOnSleeps=false、TriggerExecute 的测试结果:

[Test 1] intloop  // main.WaitOnSleeps=false, sub.WaitOnSleeps=false
Begin: 0
Begin None
Next
Count: 78

End None
[Test 1] intloop  // main.WaitOnSleeps=true, sub.WaitOnSleeps=false
Begin: 78
Begin None
Next
Count: 78

End None



  WaitOnSleeps=true、TriggerExecute 的测试结果:

[Test 1] intloop  // main.WaitOnSleeps=false, sub.WaitOnSleeps=true
Begin: 0
Begin None
Next
Count: 78

End None
[Test 1] intloop  // main.WaitOnSleeps=true, sub.WaitOnSleeps=true
Begin: 78
Begin None
Next
Count: 78

End None



  WaitOnSleeps=false、TriggerExecuteWait 的测试结果:

[Test 1] intloop  // main.WaitOnSleeps=false, sub.WaitOnSleeps=false
Begin: 0
Begin None
Next
Count: 78

End None
[Test 1] intloop  // main.WaitOnSleeps=true, sub.WaitOnSleeps=false
Begin: 78
Begin None
Next
End None
Count: 78



  WaitOnSleeps=true、TriggerExecuteWait 的测试结果:

[Test 1] intloop  // main.WaitOnSleeps=false, sub.WaitOnSleeps=true
Begin: 0
Begin None
Count: 70

End None
Next
[Test 1] intloop  // main.WaitOnSleeps=true, sub.WaitOnSleeps=true
Begin: 108
Begin None
End None
Next
Count: 108




  可看出:TriggerExecuteWait本身不会重置代码执行次数,只有等待过Sleep的触发器才会重置代码执行次数






更新
~~~~
[2006-4-14] V1.1
1.修正若干笔误
2.新增测试:
TriggerExecuteWait本身不会重置代码执行次数,只有等待过Sleep的触发器才会重置代码执行次数


[2006-4-13] V1.0
V1.0 完成

[ 本帖最后由 zyl910 于 2006-4-14 11:31 编辑 ]
发表于 2006-4-14 04:25:53 | 显示全部楼层
呵呵 我曾经还以为是每个触发器的总循环有限制呢 所以经常把循环拆到好几个触发里 然后用run trigger执行就可以运算很大的数字了
但你的测试代码里是怎么知道这是代码的限制而不是一个触发允许的总循环次数限制呢?
回复

使用道具 举报

发表于 2006-4-14 04:49:58 | 显示全部楼层
刚测了一下 的确是代码限制 测试代码:(结果为73 说明不是每个触发的总循环次数限制)

  1. function Trig_Test1_run0_maxloop_Actions takes nothing returns nothing
  2.     set udg_iCount = 0
  3.     set udg_fTemp = 1.0
  4.     loop
  5.         exitwhen udg_iCount >= 70
  6.         call logE_core(udg_fTemp)
  7.         set udg_fTemp = udg_fTemp + 1.0
  8.         set udg_iCount = udg_iCount + 1
  9.         set udg_iCount = udg_iCount
  10.         set udg_iCount = udg_iCount
  11.         set udg_iCount = udg_iCount
  12.         set udg_iCount = udg_iCount
  13.         set udg_iCount = udg_iCount
  14.         set udg_iCount = udg_iCount
  15.         set udg_iCount = udg_iCount
  16.         set udg_iCount = udg_iCount
  17.         set udg_iCount = udg_iCount
  18.         set udg_iCount = udg_iCount
  19.         set udg_iCount = udg_iCount
  20.         set udg_iCount = udg_iCount
  21.         set udg_iCount = udg_iCount
  22.         set udg_iCount = udg_iCount
  23.         set udg_iCount = udg_iCount
  24.         set udg_iCount = udg_iCount
  25.         set udg_iCount = udg_iCount
  26.         set udg_iCount = udg_iCount
  27.         set udg_iCount = udg_iCount
  28.         set udg_iCount = udg_iCount
  29.         set udg_iCount = udg_iCount
  30.         set udg_iCount = udg_iCount
  31.         set udg_iCount = udg_iCount
  32.         set udg_iCount = udg_iCount
  33.         set udg_iCount = udg_iCount
  34.         set udg_iCount = udg_iCount
  35.         set udg_iCount = udg_iCount
  36.         set udg_iCount = udg_iCount
  37.         set udg_iCount = udg_iCount
  38.         set udg_iCount = udg_iCount
  39.         set udg_iCount = udg_iCount
  40.         set udg_iCount = udg_iCount
  41.         set udg_iCount = udg_iCount
  42.         set udg_iCount = udg_iCount
  43.         set udg_iCount = udg_iCount
  44.         set udg_iCount = udg_iCount
  45.         set udg_iCount = udg_iCount
  46.         set udg_iCount = udg_iCount
  47.         set udg_iCount = udg_iCount
  48.         set udg_iCount = udg_iCount
  49.         set udg_iCount = udg_iCount
  50.         set udg_iCount = udg_iCount
  51.         set udg_iCount = udg_iCount
  52.         set udg_iCount = udg_iCount
  53.         set udg_iCount = udg_iCount
  54.         set udg_iCount = udg_iCount
  55.         set udg_iCount = udg_iCount
  56.         set udg_iCount = udg_iCount
  57.         set udg_iCount = udg_iCount
  58.         set udg_iCount = udg_iCount
  59.         set udg_iCount = udg_iCount
  60.         set udg_iCount = udg_iCount
  61.         set udg_iCount = udg_iCount
  62.         set udg_iCount = udg_iCount
  63.         set udg_iCount = udg_iCount
  64.         set udg_iCount = udg_iCount
  65.         set udg_iCount = udg_iCount
  66.         set udg_iCount = udg_iCount
  67.         set udg_iCount = udg_iCount
  68.         set udg_iCount = udg_iCount
  69.         set udg_iCount = udg_iCount
  70.         set udg_iCount = udg_iCount
  71.         set udg_iCount = udg_iCount
  72.         set udg_iCount = udg_iCount
  73.         set udg_iCount = udg_iCount
  74.         set udg_iCount = udg_iCount
  75.         set udg_iCount = udg_iCount
  76.         set udg_iCount = udg_iCount
  77.         set udg_iCount = udg_iCount
  78.         set udg_iCount = udg_iCount
  79.         set udg_iCount = udg_iCount
  80.         set udg_iCount = udg_iCount
  81.         set udg_iCount = udg_iCount
  82.         set udg_iCount = udg_iCount
  83.         set udg_iCount = udg_iCount
  84.         set udg_iCount = udg_iCount
  85.         set udg_iCount = udg_iCount
  86.         set udg_iCount = udg_iCount
  87.         set udg_iCount = udg_iCount
  88.         set udg_iCount = udg_iCount
  89.         set udg_iCount = udg_iCount
  90.         set udg_iCount = udg_iCount
  91.         set udg_iCount = udg_iCount
  92.         set udg_iCount = udg_iCount
  93.         set udg_iCount = udg_iCount
  94.         set udg_iCount = udg_iCount
  95.         set udg_iCount = udg_iCount
  96.         set udg_iCount = udg_iCount
  97.         set udg_iCount = udg_iCount
  98.         set udg_iCount = udg_iCount
  99.         set udg_iCount = udg_iCount
  100.         set udg_iCount = udg_iCount
  101.         set udg_iCount = udg_iCount
  102.         set udg_iCount = udg_iCount
  103.         set udg_iCount = udg_iCount
  104.         set udg_iCount = udg_iCount
  105.         set udg_iCount = udg_iCount
  106.         set udg_iCount = udg_iCount
  107.         set udg_iCount = udg_iCount
  108.         set udg_iCount = udg_iCount
  109.         set udg_iCount = udg_iCount
  110.         set udg_iCount = udg_iCount
  111.         set udg_iCount = udg_iCount
  112.         set udg_iCount = udg_iCount
  113.         set udg_iCount = udg_iCount
  114.         set udg_iCount = udg_iCount
  115.         set udg_iCount = udg_iCount
  116.         set udg_iCount = udg_iCount
  117.         set udg_iCount = udg_iCount
  118.         set udg_iCount = udg_iCount
  119.         set udg_iCount = udg_iCount
  120.         set udg_iCount = udg_iCount
  121.         set udg_iCount = udg_iCount
  122.         set udg_iCount = udg_iCount
  123.         set udg_iCount = udg_iCount
  124.         set udg_iCount = udg_iCount
  125.         set udg_iCount = udg_iCount
  126.         set udg_iCount = udg_iCount
  127.         set udg_iCount = udg_iCount
  128.         set udg_iCount = udg_iCount
  129.         set udg_iCount = udg_iCount
  130.         set udg_iCount = udg_iCount
  131.         set udg_iCount = udg_iCount
  132.         set udg_iCount = udg_iCount
  133.         set udg_iCount = udg_iCount
  134.         set udg_iCount = udg_iCount
  135.         set udg_iCount = udg_iCount
  136.         set udg_iCount = udg_iCount
  137.         set udg_iCount = udg_iCount
  138.         set udg_iCount = udg_iCount
  139.         set udg_iCount = udg_iCount
  140.         set udg_iCount = udg_iCount
  141.         set udg_iCount = udg_iCount
  142.         set udg_iCount = udg_iCount
  143.         set udg_iCount = udg_iCount
  144.         set udg_iCount = udg_iCount
  145.         set udg_iCount = udg_iCount
  146.         set udg_iCount = udg_iCount
  147.         set udg_iCount = udg_iCount
  148.         set udg_iCount = udg_iCount
  149.         set udg_iCount = udg_iCount
  150.         set udg_iCount = udg_iCount
  151.         set udg_iCount = udg_iCount
  152.         set udg_iCount = udg_iCount
  153.         set udg_iCount = udg_iCount
  154.         set udg_iCount = udg_iCount
  155.         set udg_iCount = udg_iCount
  156.         set udg_iCount = udg_iCount
  157.         set udg_iCount = udg_iCount
  158.         set udg_iCount = udg_iCount
  159.         set udg_iCount = udg_iCount
  160.         set udg_iCount = udg_iCount
  161.         set udg_iCount = udg_iCount
  162.         set udg_iCount = udg_iCount
  163.         set udg_iCount = udg_iCount
  164.         set udg_iCount = udg_iCount
  165.         set udg_iCount = udg_iCount
  166.         set udg_iCount = udg_iCount
  167.         set udg_iCount = udg_iCount
  168.         set udg_iCount = udg_iCount
  169.         set udg_iCount = udg_iCount
  170.         set udg_iCount = udg_iCount
  171.         set udg_iCount = udg_iCount
  172.         set udg_iCount = udg_iCount
  173.         set udg_iCount = udg_iCount
  174.         set udg_iCount = udg_iCount
  175.         set udg_iCount = udg_iCount
  176.         set udg_iCount = udg_iCount
  177.         set udg_iCount = udg_iCount
  178.         set udg_iCount = udg_iCount
  179.         set udg_iCount = udg_iCount
  180.         set udg_iCount = udg_iCount
  181.         set udg_iCount = udg_iCount
  182.         set udg_iCount = udg_iCount
  183.         set udg_iCount = udg_iCount
  184.         set udg_iCount = udg_iCount
  185.         set udg_iCount = udg_iCount
  186.         set udg_iCount = udg_iCount
  187.         set udg_iCount = udg_iCount
  188.         set udg_iCount = udg_iCount
  189.         set udg_iCount = udg_iCount
  190.         set udg_iCount = udg_iCount
  191.         set udg_iCount = udg_iCount
  192.         set udg_iCount = udg_iCount
  193.         set udg_iCount = udg_iCount
  194.         set udg_iCount = udg_iCount
  195.         set udg_iCount = udg_iCount
  196.         set udg_iCount = udg_iCount
  197.         set udg_iCount = udg_iCount
  198.         set udg_iCount = udg_iCount
  199.         set udg_iCount = udg_iCount
  200.         set udg_iCount = udg_iCount
  201.         set udg_iCount = udg_iCount
  202.         set udg_iCount = udg_iCount
  203.         set udg_iCount = udg_iCount
  204.         set udg_iCount = udg_iCount
  205.         set udg_iCount = udg_iCount
  206.         set udg_iCount = udg_iCount
  207.         set udg_iCount = udg_iCount
  208.         set udg_iCount = udg_iCount
  209.         set udg_iCount = udg_iCount
  210.         set udg_iCount = udg_iCount
  211.         set udg_iCount = udg_iCount
  212.         set udg_iCount = udg_iCount
  213.         set udg_iCount = udg_iCount
  214.         set udg_iCount = udg_iCount
  215.         set udg_iCount = udg_iCount
  216.         set udg_iCount = udg_iCount
  217.         set udg_iCount = udg_iCount
  218.         set udg_iCount = udg_iCount
  219.         set udg_iCount = udg_iCount
  220.         set udg_iCount = udg_iCount
  221.         set udg_iCount = udg_iCount
  222.         set udg_iCount = udg_iCount
  223.         set udg_iCount = udg_iCount
  224.         set udg_iCount = udg_iCount
  225.         set udg_iCount = udg_iCount
  226.         set udg_iCount = udg_iCount
  227.         set udg_iCount = udg_iCount
  228.         set udg_iCount = udg_iCount
  229.         set udg_iCount = udg_iCount
  230.     endloop
  231.     loop
  232.         exitwhen udg_iCount >= 140
  233.         call logE_core(udg_fTemp)
  234.         set udg_fTemp = udg_fTemp + 1.0
  235.         set udg_iCount = udg_iCount + 1
  236.     endloop
  237. endfunction
复制代码

[ 本帖最后由 illlusion 于 2006-4-14 04:51 编辑 ]
回复

使用道具 举报

发表于 2006-4-14 06:36:23 | 显示全部楼层
没看明白,loop没加时间等待,电脑会判断的,特别是调用同一个函数时,就像logE_core里面有loop循环连续调用会发生loop错误,udg_iCount当然为<=78,TriggerExecuteWait,在运倒错误就返回,不知道是不是,你在它下面看udg_iCount的值是错误的,如果loop还在运行你就看不倒(加上时间等待后)。
回复

使用道具 举报

发表于 2006-4-14 07:44:49 | 显示全部楼层
在loop里用等待才会发生错误  它的等待是放在loop结束以后的 所以没有问题
回复

使用道具 举报

 楼主| 发表于 2006-4-14 11:27:40 | 显示全部楼层

触发器执行研究 V1.1

今天测试了TriggerExecuteWait相互等待,发现结果很诡异

六、TriggerExecuteWait本身不会重置代码执行次数,只有等待过Sleep的触发器才会重置代码执行次数
回复

使用道具 举报

发表于 2006-4-14 11:58:22 | 显示全部楼层
根据这段说明
TriggerExecuteWait
Runs the given trigger in a special mode which affects all other triggers that have the \"wait on sleep\" property set. When this trigger sleeps (via TriggerSleepAction), all other triggers that have \"wait on sleep\" turned on will wait until this trigger stops sleeping and resumes execution before they also resume execution.


TriggerExecuteWait只是将传入的触发设置为一种特殊模式 在这种模式下如果用了sleep 则其他所有wait on sleep打开的触发也会一起等待 直到sleep的触发重新开始执行动作

由此可见等待动作最终还是要靠sleep来做 而TriggerExecuteWait只想当与一个设置 所以它本身不会让代码计数重置也是理所当然的了:)
回复

使用道具 举报

发表于 2006-4-14 15:15:08 | 显示全部楼层
英文看不懂...长.也看不懂...
回复

使用道具 举报

发表于 2006-4-14 18:18:44 | 显示全部楼层
貌似我以前测试过一个触发器中总共执行的语句数限制为20000
回复

使用道具 举报

发表于 2006-4-15 16:34:06 | 显示全部楼层
真正算起来,每种语句消耗的系统时间都不同吧,比较小的象set x=x+1,若以此作为标准,一个Trigger容纳大约是23000个,(机器不同,应该有影响的);但如果是单纯赋值,消耗的时间量我估算为其1/6.50.也就是大约15万个x=(整数常量或变量).
令:消耗的系统时间按基本符合线性叠加处理(和实际中的简单运行也基本相符).
所以我认为触发被迫终止的原因是实际中运行的时间超出预期而\"过期\",而每行代码消耗量都有可能不同(常见的如赋值,消耗是最少的,但如果表达式也是一大堆的话....而各种调用的函数消耗更是千差万别,而根据浑沌的基本假设,要确定最基础的单元消耗...貌似不可能吧..所以我放弃了.

[ 本帖最后由 kook 于 2006-4-15 16:47 编辑 ]
回复

使用道具 举报

 楼主| 发表于 2006-4-15 16:37:52 | 显示全部楼层
不是按执行时间算的
是按执行的语句算的

因为每次中断的位置都一样
回复

使用道具 举报

发表于 2006-4-15 16:57:40 | 显示全部楼层
按时间(消耗的,无trigger sleep)..根据如下:
[jass]function Trig_looptest_Actions takes nothing returns nothing
//local  integer i
//local integer max=S2I(SubString(GetEventPlayerChatString(),8,16))
loop
exitwhen udg_count>100000
//set udg_x=udg_x
//set udg_x=udg_x
set udg_count=udg_count+1
endloop
//call DisplayTimedTextToPlayer(Player(0),0,0,10,\"循环次数\"+I2S(i))
call BJDebugMsg(\"循环次数\"+I2S(udg_count))
set udg_count=0
endfunction[/jass]
[jass]function Trig_displaytest_Actions takes nothing returns nothing
call DisplayTimedTextToPlayer(Player(0),0,0,10,\"循环次数\"+I2S(udg_count))
set udg_count=0
endfunction[/jass]
在loop之间只有set udg_count=udg_count+1时我统计得23076;加个set udg_x=udg_x后为20000个,再加个..得到17647个,它们非线性关系而是倒数呈线性关系.
而如果在loop间的是别的如 BJDebugMsg,只有797次而已.

[ 本帖最后由 kook 于 2006-4-15 17:01 编辑 ]
回复

使用道具 举报

发表于 2006-4-15 17:28:35 | 显示全部楼层
的确..在Trigger sleep以后会重置代码运行次数(可以这么说),通过每隔一段(当前系统时间耗尽之前)用次Trigger sleep,理论上Trigger 能容纳无数的代码(因为每段非同时性),不过..代价是越来越卡
回复

使用道具 举报

 楼主| 发表于 2006-4-15 17:29:15 | 显示全部楼层

没有经过精确的数学分析是会犯错误的

设a为常数开销,b为循环开销,max为总开销,列方程组:
a + b * 23076 = max  // #1
a + (b+1) * 20000 = max // #2
a + (b+2) * 17647 = max // #3


#2式 - #1式 :
b * 23076 = (b + 1) * 20000
b * 23076 = b * 20000 + 20000
b * 3076 = 20000
b = 20000 / 3076 = 6.5019505851755526657997399219766


#3式 - #2式 :
(b+1) * 20000 = (b+2) * 17647
b * 20000 + 20000 = b * 17647 + 35294
b * 2353 = 15294
b = 15294 / 2353 = 6.4997875053123671908202294942626


#3式 - #1式 :
b * 23076 = (b+2) * 17647
b * 23076 = b * 17647 + 35294
b * 5429 = 35294
b = 35294 / 5429 = 6.5010130779149014551482777675447


集中到一起看看:
6.5019505851755526657997399219766
6.4997875053123671908202294942626
6.5010130779149014551482777675447


可看出,的确是执行次数
回复

使用道具 举报

 楼主| 发表于 2006-4-15 17:34:05 | 显示全部楼层
Blizzard.j
[jass]
//====================================================================
function BJDebugMsg takes string msg returns nothing
    local integer i = 0
    loop
        call DisplayTimedTextToPlayer(Player(i),0,0,60,msg)
        set i = i + 1
        exitwhen i == bj_MAX_PLAYERS
    endloop
endfunction
[/jass]
回复

使用道具 举报

发表于 2006-4-15 18:14:13 | 显示全部楼层
没怎么看懂..特别是a,b所指的单位;
我认为还先从基本设定统一起:
\"执行次数\":执行像set x=1 和 call DisplayTimedTextToPlayer(....)都算是执行了一条/次语句吗?
如果把\"基本的最小单元的执行\"(假设如内存中的一次数据处理)作为执行次数的单位,那么从极限的无穷小微分上看就是我的\"执行时间\"的概念了.
回复

使用道具 举报

 楼主| 发表于 2006-4-15 18:16:43 | 显示全部楼层
我估计是是按语句的行数
碰到call语句会执行里面的代码,所以call语句中的代码也得算上去
回复

使用道具 举报

 楼主| 发表于 2006-4-15 18:20:11 | 显示全部楼层
原帖由 kook 于 2006-4-15 18:14 发表
没怎么看懂..特别是a,b所指的单位;


这个我也不知道,主要是因为现在的测试数据还不够多


应该这样列方程的:
a + b * 23076 = max  // #1
a + (b + c*1) * 20000 = max // #2
a + (b + c*2) * 17647 = max // #3

但是数据不全,所以最后放弃c参数了
回复

使用道具 举报

发表于 2006-4-15 18:29:26 | 显示全部楼层
那么这么说吧,
[jass]loop
exitwhen i>max
call DisplayTimedTextToPlayer(Player(0),0,0,30,\"循环次数\"+I2S(i))
set i=i+1
endloop[/jass]
将其中的 call DisplayTimedTextToPlayer换成别的一行什么,如set x=0,最后结果i会一样吗?

ps:顺便作了一下Trigger Sleep在循环中能容许的最小值,发现它是波动的比较奇怪..而且用来量度时间单位的timer又和游戏速度挂钩的.
[jass]local  integer i=1
local integer max =S2I(SubString(GetEventPlayerChatString(),8,16))
local timer count_t=CreateTimer()
call DisplayTimedTextToPlayer(Player(0),0,0,10,\"计时开始!\")
call TimerStart(count_t,240,false,null)
loop
exitwhen i>max
call TriggerSleepAction(0)
set i=i+1
endloop
call DisplayTimedTextToPlayer(Player(0),0,0,10,\"循环次数\"+I2S(i))
call DisplayTimedTextToPlayer(Player(0),0,0,60,\"总计停止时间\"+R2S(TimerGetElapsed(count_t)))

//call BJDebugMsg(\"循环次数\"+I2S(i))
set udg_count=0
call TriggerSleepAction(1)
call DestroyTimer(count_t)
set count_t=null[/jass]
总的说来,在\"快\"的速度下0.20-0.21\"游戏秒\";\"慢\"时0.12左右.在处理数据增加时还呈下降趋势.嗯

[ 本帖最后由 kook 于 2006-4-15 18:45 编辑 ]
回复

使用道具 举报

 楼主| 发表于 2006-4-15 18:34:56 | 显示全部楼层
应该不会
call调用中的代码也算的

但是DisplayTimedTextToPlayer是CJ函数,可能只算做一行
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 点一下

本版积分规则

Archiver|移动端|小黑屋|地精研究院

GMT+8, 2024-5-2 08:30 , Processed in 0.126419 second(s), 20 queries .

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表