hengmana   10-17-2012, 10:00 PM
#1
บทความทั้งหมดเขียนโดย วอราม่อน
ที่มา http://community.thaiware.com/index.php/...p__2075141

วิธีการแก้ไขเวลาสคริปต์ Error ตอนกด F12
หลายคนอาจเคยเป็นกันน้อ ตอนที่พอกด F12 ในเกมแล้วเออเร่อ ขึ้นว่า Stack Level too deep
[Image: 8651c371ce.jpg]
ปัญหานี้ปกติเกิดขึ้นจาก การลูปสคริปต์ไม่มีที่สิ้นสุด หรือการ alias ซ้ำโดยชื่อเมธอทใหม่ที่ใช้เป็นชื่อ method ที่มีอยู่แล้ว~

การลูปสคริปต์ไม่มีที่สิ้นสุด เช่น...
[shcode=rails]def test
test
end[/shcode]
แบบนี้มันจะรันตัวเองซ้ำไปเรื่อย ๆ ทำให้สคริปต์แฮงค์ในที่สุด

การ Alias ซ้ำ
[shcode=rails]def test
p 'test'
end

def test_two
p 'test 2'
end

alias test test_two[/shcode]
ซึ่งชื่อใหม่ที่ใช้ตอนประกาศในสคริปต์ด้านบน คือ test ซึ่งเป็นเมธอทที่มีอยู่แล้ว ทำให้สคริปต์แฮงค์นั่นเอง
แต่ปกติคงไม่มีใครทำผิดพลาดจนใช้ชื่อใหม่ในการ Alias ซ้ำกับเมธอทที่มีอยู่แล้ว -___-" เพราะปกติเค้าจะใช้ชื่อ Alias แบบเฉพาะตัวกัน เพื่อป้องกันการซ้ำกับที่สคริปต์เตอร์คนอื่น Alias
เช่น...
[shcode=rails]alias old_test test[/shcode]
แบบนี้ไม่ดี เพราะอาจมีสคริปต์เตอร์อีกคน Alias ใช้ชื่อ old_test เหมือนกันแล้วสคริปต์ขึ้น Stack level too deep ได้~
รูปแบบที่ดี ควรมี ชื่อสคริปต์เตอร์ + ชื่อสคริปต์ที่กำลังเขียน + คลาสที่ alias + เมธอทที่ alias
ซึ่งไม่จำเป็นต้องตามแบบนี้ แต่แบบนี้จะป้องกันการใช้ชื่อซ้ำได้ดีครับ~^^ เช่น...
[shcode=rails]def Game_System
alias wora_abs_gamsys_ini initialize
def initialize
# Do something...
wora_abs_gamsys_ini
end
end[/shcode]
ชื่อที่ผมใช้ alias คือ wora_abs_gamsys_ini
wora คือ ชื่อผม (woratana)
abs คือ สคริปต์ที่ผมเขียนอยู่ (Action Battle System)
gamsys คือ คลาสที่ alias (Game_System)
ini คือ เมธอทที่ alias (Initialize) บางคนก็ใช้ init ครับ แล้วแต่ถนัดเลย~^^


กลับเข้าหัวข้อ... ต่อให้ป้องกันดีแล้ว ทำไมยังมีปัญหา Stack Level too deep เกิดขึ้นอีก?
นั่นก็เพราะตอนที่เรา Alias โมดูล หรือคลาสที่เรามองไม่เห็น ตอนเรากด F12 เพื่อรันสคริปต์มันจะ Alias ทับส่วนที่เรา Alias ไปแล้วครับ~
ซึ่งการ Alias โมดูลมันก็ไม่เหมือนกับการ Alias ปกติด้วยครับ แทนที่เราจะใช้แบบนี้
[shcode=rails]module RPG[/shcode]
ต้องใช้เป็น...
[shcode=rails]class << RPG[/shcode]
ตัวอย่างการ Alias (สมมตินะฮะ)
[shcode=rails]class << Audio
alias wora_audiosys_audio_seplay se_play
def se_play(*args)
p args[0] # ปรินท์ชื่อไฟล์ SE
wora_audiosys_audio_seplay(*args)
end
end[/shcode]
ถ้าทำแบบในตัวอย่างนี้ ตอนเข้าเกมครั้งแรกจะปกติดี แต่ถ้ากด F12 แล้วจะแฮงค์ทันทีฮะ
วิธีแก้ คือ ตั้งเช็คว่า method ชื่อนี้ถูกประกาศไว้หรือยัง ดังนี้...
Quote:class << Audio
alias wora_audiosys_audio_seplay se_play unless method_defined?('wora_audiosys_audio_seplay')
def se_play(*args)
p args[0] # ปรินท์ชื่อไฟล์ SE
wora_audiosys_audio_seplay(*args)
end
end
ส่วนตัวหนาคือจุดที่ผมเพิ่มเข้าไปนั่นเองครับ
method_defined?(ชื่อเมธอท ต้องเป็น String นะ) จะคืนค่ามาว่าเมธอทชื่อนั้นถูกประกาศไปหรือยัง?

ทว่า... ถ้าเกิดกรณีที่ Alias เมธอทนอกคลาสหรือโมดูล เช่น~
[shcode=rails]alias wora_preload_loaddata load_data
def load_data(*args)
p args
wora_preload_loaddata(*args)
end[/shcode]

load_data นี่เป็นเมธอทที่อยู่ในคลาสไหนไม่รู้ - -" แต่ตอนเราเรียกใช้ แค่พิมพ์ load_data ไปธรรมดาครับ~

วิธีการ Alias คลาสประเภทนี้ไม่ให้แฮงค์ก็คือ...
เติม unless $@ เข้าไปหลังบรรทัดนั้นครับ เราใช้ method_defined? ไม่ได้เพราะมันอยู่นอกคลาส TwT

$@ ถ้าจำไม่ผิดมันคือ Error Position หรืออะไรประมาณนั้นน่ะครับ ยอมรับว่าไม่รู้เหมือนกันว่ามันคืออะไรกันแน่ แต่มันจะคืนค่า true แค่ตอนที่รันเกมครั้งแรกเท่านั้นครับผม~^^

------------------------------------------
จบล่ะ -___________-/ บทความครั้งนี้ออกจะเป็นสคริปต์ขั้นสูงไปนิด แต่หลาย ๆ ท่านที่เกมพอกด F12 แล้วค้างก็คงรู้กันแล้วนะฮะว่าปัญหามาจากอะไร
This post was last modified: 10-26-2012, 10:14 AM by hengmana.
Neoz Kaho   10-20-2012, 09:30 PM
#2
ภาพแรกเจ๊งนะฮะ ฝากแก้ด้วย

[Image: 7wDGQYA.png][Image: 76561197983021669.png]
  
Users browsing this thread: 1 Guest(s)
Powered By MyBB, © 2002-2024 MyBB Group.
Made with by Curves UI.