Mã: scope Arrows initializer Ar globals private integer idSpell = 'A001' private integer idDummy = 'h000' endglobals private struct data unit hero unit dummy location castloc real angle integer tick timer t endstruct private function Conditions takes nothing returns boolean return GetSpellAbilityId() == idSpell endfunction private function Knockback takes nothing returns nothing local timer t = GetExpiredTimer() local data d = GetTimerData(t) local group g = CreateGroup() local unit temp local location loc local boolean check if d.tick < 150 then set loc = PolarProjectionBJ(d.castloc,50*d.tick,d.angle) call SetUnitPositionLoc(d.dummy,loc) call GroupEnumUnitsInRangeOfLoc(g,loc,100,null) set temp =FirstOfGroup(g) loop exitwhen temp == null if IsUnitEnemy(temp , GetOwningPlayer(d.dummy)) then call SetUnitPositionLoc(temp,loc) call UnitDamageTargetBJ(d.dummy,temp,10, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL ) call GroupRemoveUnit(g,temp) set temp = FirstOfGroup(g) endif call GroupRemoveUnit(g,temp) set temp = FirstOfGroup(g) endloop call DestroyGroup(g) set temp = null call RemoveLocation(loc) else call RemoveUnit(d.dummy) call ReleaseTimer(d.t) call d.destroy() endif call DestroyGroup(g) set t = null set d.tick = d.tick + 1 set t = null endfunction private function Actions takes nothing returns nothing local data d = data.create() local unit hero = GetSpellAbilityUnit() local location targloc = GetSpellTargetLoc() local location castloc = GetUnitLoc(hero) local real angle = AngleBetweenPoints(castloc,targloc) set d.hero = hero set d.castloc = castloc set d.angle = angle set d.dummy = CreateUnitAtLoc(GetOwningPlayer(hero),idDummy,castloc,angle) set d.tick = 1 set d.t = NewTimer() call SetTimerData(d.t,d) call TimerStart(d.t,0.02,true,function Knockback ) [B] call RemoveLocation(targloc) call RemoveLocation(castloc) set hero = null set targloc = null set castloc = null[/B] endfunction //=========================================================================== private function Ar takes nothing returns nothing local trigger t = CreateTrigger( ) call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT ) call TriggerAddCondition( t, Condition( function Conditions ) ) call TriggerAddAction( t, function Actions ) set t=null endfunction endscope Cái này chạy trên 1 System TimerUtils ... Mình có thắc mắc ở cái chỗ in đậm này.. Bây giờ nếu mình không có nó thì Spell cast bình thường và không có vấn đề gì xảy ra , Unit Dummy có vị trí xuất phát ở castloc sẽ chạy ra từ đúng vị trí. Nhưng nếu mình đặt cái lệnh để xóa leak thì khi cast spell , Unit Dummy lại có vị trí bắt đầu từ giữa bản đồ.. không hiểu vì sao lại như vậy nữa.. ai có thể giải thích dùm mình được không .. không xóa cái này Leak là 100% +_+ ---------- Post added at 21:18 ---------- Previous post was at 21:16 ---------- hix.. in đậm mà nhìn nó chả có gì.. em Quote lại cái đoạn mà em nói tới ở trên
Thật ra bạn nên hiểu, leak là những vùng nhớ chứa dữ liệu/thông tin mà CPU sẽ phải xử lí, nếu xài xong không xóa, mặc dù dữ liệu đó ta không cần dùng/xài nữa nhưng CPU vẫn sẽ phải xử lí nó, leak càng nhiều nên CPU càng xử lí những thứ thừa thải, làm nặng/lag máy. Trường hợp trên là trường hợp bạn chưa dùng xong dữ liệu của 1 vùng nhớ mà đã vội xóa nó đi, dẫn đến tình trạng khi bạn xử lí phần timer, nó có hiểu dữ liệu là gì đâu. Rõ hơn là khi bạn location castloc = GetUnitLoc(hero) thì sẽ có 1 vùng nhớ chứa dữ liệu về cái điểm cast point đó, và castloc là 1 biến trỏ về vùng nhớ đó Sau đó bạn set d.castloc = castloc thì biến d.castloc củng chỉ là 1 biến trỏ về vùng nhớ đó Khi bắt đầu timer, thì bạn ngay lập tức call RemoveLocation(castloc), tức là bạn vừa hủy dữ liệu tại vùng nhớ mà biến castloc trỏ tới, trong khi đó biến d.castloc đang còn trỏ đến vùng nhớ đó mà dữ liệu bạn đã xóa đi...nên dẫn đến tình trạng như trên (xem như d.castloc = null, í chỉ vùng nhớ đó không còn dữ liệu gì cả) Hi vọng là bạn hiểu sâu hơn về vấn đề đó :)
Nhưng lạ ở chỗ là khi mình đảo ngược vị trí của nó thì cái Code này lại hoạt động. là như vậy nè.. Nếu như bạn nói mình không cần phải khai báo lệnh xóa nó đi thì nếu chiu đó được cast nhìu lần nhiều con nó có gây lag không .. vì cái này mình không biết nên đặt Xóa leak chỗ nào cho đúng.. Bạn nói rõ hơn cách khắc phục đoạn code trên được không ???
Chài, set castloc = null, tức là castloc giờ không còn trỏ tới vùng nhớ nào nữa rồi (cụ thể là vùng nhớ chưa dữ liệu GetUnitLoc(hero)), sau đó bạn lại ra lệnh hủy vùng nhớ mà nó trỏ tới ? -> Bất lôgic không ? Bạn làm như thế là làm cho nó leak hơn ấy chứ, rất may thay trước đó bạn đã set d.castloc = castloc, tức là biến d.castloc cũng trỏ tới vùng nhớ này, bên timer bạn dùng nó nên mới chạy được đấy, nhưng khi chạy xong bạn lại không xóa vùng nhớ nó đi tức là RemoveLocation(d.castloc) -> leak đây Vậy nếu như bạn hỏi cách xóa leak đó ra sao thì câu trả lời là chỉ cần thêm vào RemoveLocation(d.castloc) khi timer chạy xong
Oh`.. thế mà không hiểu nổi.. thanks bạn nha.. giờ đã hiểu được phần đó rồi hihi.. Như vậy khi khai báo xong, nếu phần biến nào còn dùng cho Timer thì phải giữ lại chưa xóa vội.. sau khi timer chạy xong thì xóa ở cái function có timer chạy .. như vậy phải không..