การสื่อสารแบบเอนทิตีทำงานอย่างไร


115

ฉันมีสองกรณีผู้ใช้:

  1. จะentity_Aส่งtake-damageข้อความถึงentity_Bอย่างไร
  2. HP จะentity_Aค้นหาด้วยวิธีentity_Bใด

นี่คือสิ่งที่ฉันได้พบ:

  • คิวข้อความ
    1. entity_Aสร้างtake-damageข้อความและโพสต์ไปentity_Bที่คิวข้อความของ
    2. entity_Aสร้างข้อความและโพสต์ไปยัง query-hp ในการกลับมาสร้างข้อความและโพสต์ไปยังentity_Bentity_Bresponse-hpentity_A
  • เผยแพร่ / สมัครสมาชิก
    1. entity_Bสมัครรับtake-damageข้อความ (อาจเป็นไปได้ว่ามีการกรองบางอย่างเพื่อให้ส่งเฉพาะข้อความที่เกี่ยวข้องเท่านั้น) entity_Aผลิตข้อความที่อ้างอิงtake-damageentity_B
    2. entity_Aสมัครรับupdate-hpข้อความ (อาจถูกกรอง) ทุกเฟรมentity_Bออกอากาศupdate-hpข้อความ
  • สัญญาณ / สล็อต
    1. ???
    2. entity_Aเชื่อมตupdate-hpสล็อตentity_B's update-hpสัญญาณ

มีอะไรที่ดีกว่านี้ไหม? ฉันมีความเข้าใจที่ถูกต้องหรือไม่ว่าโครงร่างการสื่อสารเหล่านี้จะผูกเข้ากับระบบเอนทิตีของเอ็นจิ้นเกมได้อย่างไร

คำตอบ:


67

คำถามที่ดี! ก่อนที่ฉันจะไปถึงคำถามเฉพาะที่คุณถามฉันจะพูดว่า: อย่าประมาทพลังแห่งความเรียบง่าย Tenpn ถูกต้อง โปรดทราบว่าสิ่งที่คุณพยายามทำด้วยวิธีการเหล่านี้คือการหาหนทางที่สวยงามในการเลื่อนการเรียกฟังก์ชั่นหรือแยกผู้โทรออกจากผู้โทร ฉันสามารถแนะนำ coroutines เป็นวิธีที่ใช้งานง่ายอย่างน่าประหลาดใจเพื่อบรรเทาปัญหาเหล่านั้น แต่นั่นเป็นเรื่องเล็กน้อย บางครั้งคุณก็ควรโทรหาฟังก์ชั่นและใช้ชีวิตด้วยความจริงที่ว่าเอนทิตี้ A เชื่อมโยงโดยตรงกับเอนทิตีบีดู YAGNI

ที่กล่าวว่าฉันเคยใช้และมีความสุขกับรูปแบบสัญญาณ / สล็อตรวมกับการส่งข้อความแบบง่าย ฉันใช้มันใน C ++ และ Lua สำหรับชื่อ iPhone ที่ค่อนข้างประสบความสำเร็จและมีตารางงานที่แน่นมาก

สำหรับกรณีสัญญาณ / สล็อตถ้าฉันต้องการให้เอนทิตี้ A ทำบางสิ่งบางอย่างเพื่อตอบสนองต่อเอนทิตี B ที่ทำ (เช่นปลดล็อกประตูเมื่อมีอะไรบางอย่างตาย) ฉันอาจมีเอนทิตี้ A สมัครสมาชิกโดยตรงกับเหตุการณ์การตายของเอนทิตี้ B หรือเอนทิตี A อาจสมัครสมาชิกกลุ่มแต่ละกลุ่มเพิ่มจำนวนตัวนับในแต่ละเหตุการณ์ที่ถูกไล่ออกและปลดล็อคประตูหลังจากที่ N ของพวกเขาเสียชีวิต นอกจากนี้ "กลุ่มเอนทิตี" และ "N ของพวกเขา" โดยทั่วไปจะถูกกำหนดไว้ในข้อมูลระดับ (นอกเหนือจากนี้นี่เป็นพื้นที่หนึ่งที่ coroutines สามารถส่องแสงได้จริง ๆ เช่น WaitForMultiple ("Dying", entA, entB, entC); door.Unlock ();)

แต่นั่นอาจทำให้เกิดความยุ่งยากเมื่อพูดถึงปฏิกิริยาที่แนบคู่กับรหัส C ++ หรือเหตุการณ์เกมชั่วคราวโดยเนื้อแท้: สร้างความเสียหาย, โหลดอาวุธ, แก้จุดบกพร่อง, ตอบกลับ AI ที่อิงตามตำแหน่งของผู้เล่น นี่คือที่การส่งข้อความสามารถเติมช่องว่าง มันบอกอะไรทำนองนี้ "บอกทุกหน่วยงานในพื้นที่นี้ให้ได้รับความเสียหายภายใน 3 วินาที" หรือ "เมื่อใดก็ตามที่คุณทำฟิสิกส์ให้เสร็จเพื่อให้รู้ว่าใครเป็นคนยิงฉันบอกให้พวกเขาเรียกใช้ฟังก์ชันสคริปต์นี้" เป็นการยากที่จะทราบวิธีการทำเช่นนั้นโดยใช้การเผยแพร่ / สมัครสมาชิกหรือสัญญาณ / สล็อต

สิ่งนี้สามารถ overkill ได้ง่าย (เทียบกับตัวอย่างของ tenpn) นอกจากนี้ยังสามารถขยายตัวได้อย่างไม่มีประสิทธิภาพหากคุณมีการดำเนินการมากมาย แต่ถึงแม้จะมีข้อเสีย แต่วิธี "ข้อความและกิจกรรม" นี้เข้ากันได้ดีกับโค้ดเกมที่เขียนสคริปต์ (เช่นใน Lua) รหัสสคริปต์สามารถกำหนดและตอบสนองต่อข้อความและเหตุการณ์ของตนเองโดยไม่ต้องใช้รหัส C ++ ในการดูแลเลย และโค้ดสคริปต์สามารถส่งข้อความที่เรียกรหัส C ++ เช่นระดับการเปลี่ยนแปลงการเล่นเสียงหรือแม้แต่ปล่อยให้อาวุธตั้งค่าความเสียหายที่ข้อความ TakeDamage ส่งมอบได้อย่างง่ายดาย มันช่วยฉันได้สักระยะเพราะฉันไม่ต้องโง่ไปกับ luabind และให้ฉันเก็บรหัส luabind ทั้งหมดไว้ในที่เดียวเพราะมันมีไม่มาก เมื่อประกอบเข้าด้วยกันอย่างถูกต้อง

นอกจากนี้ประสบการณ์ของฉันกับกรณีการใช้งาน # 2 คือว่าคุณดีกว่าจัดการกับมันเป็นเหตุการณ์ในทิศทางอื่น แทนที่จะถามว่าสุขภาพของกิจการคืออะไรให้เริ่มเหตุการณ์ / ส่งข้อความเมื่อใดก็ตามที่สุขภาพมีการเปลี่ยนแปลงที่สำคัญ

ในแง่ของอินเทอร์เฟซ btw ฉันลงเอยด้วยคลาสที่สามเพื่อใช้ทั้งหมดนี้: EventHost, EventClient และ MessageClient EventHosts สร้างสล็อต, EventClients สมัครสมาชิก / เชื่อมต่อกับพวกเขาและ MessageClients เชื่อมโยงผู้ได้รับมอบหมายกับข้อความ โปรดทราบว่าเป้าหมายผู้รับมอบสิทธิ์ของ MessageClient ไม่จำเป็นต้องเป็นวัตถุเดียวกับเจ้าของสมาคม ในคำอื่น ๆ MessageClients สามารถมีอยู่เพียงเพื่อส่งต่อข้อความไปยังวัตถุอื่น FWIW คำอุปมาโฮสต์ / ไคลเอ็นต์นั้นไม่เหมาะสม Source / Sink อาจเป็นแนวคิดที่ดีกว่า

ขอโทษฉันเดินไปที่นั่น มันเป็นคำตอบแรกของฉัน :) ฉันหวังว่ามันจะสมเหตุสมผล


ขอบคุณสำหรับคำตอบ. ข้อมูลเชิงลึกที่ยอดเยี่ยม เหตุผลที่ฉันออกแบบข้อความให้ผ่านเพราะ Lua ฉันต้องการที่จะสร้างอาวุธใหม่โดยไม่ต้องใช้รหัส C ++ ใหม่ ดังนั้นความคิดของคุณจึงตอบคำถามที่ยังไม่ได้ถามของฉัน
deft_code

สำหรับ coroutines ฉันก็เป็นผู้เชื่อที่ดีใน coroutines แต่ฉันไม่เคยเล่นกับพวกเขาใน C ++ ฉันมีความหวังที่คลุมเครือในการใช้ coroutines ในรหัส lua เพื่อจัดการการบล็อคการโทร (เช่นรอการตาย) มันคุ้มค่ากับความพยายามหรือไม่? ฉันกลัวว่าฉันอาจจะตาบอดด้วยความปรารถนาอันแรงกล้าของฉันที่มีต่อ coroutines ใน c ++
deft_code

สุดท้ายเกม iphone คืออะไร ฉันสามารถรับข้อมูลเพิ่มเติมเกี่ยวกับระบบเอนทิตีที่คุณใช้หรือไม่
deft_code

2
ระบบกิจการส่วนใหญ่ใน C ++ ยกตัวอย่างเช่นมีคลาส Imp ที่จัดการกับพฤติกรรมของ Imp Lua สามารถเปลี่ยนพารามิเตอร์ของ Imp ได้ที่วางไข่หรือผ่านข้อความ เป้าหมายของ Lua คือการจัดตารางให้แน่นและการดีบักรหัส Lua นั้นใช้เวลานานมาก เราใช้ Lua กับระดับสคริปต์ (เอนทิตีที่ไปไหนเหตุการณ์ที่เกิดขึ้นเมื่อคุณกดทริกเกอร์) ดังนั้นใน Lua เราจะพูดอย่าง SpawnEnt ("Imp") โดยที่ Imp เป็นสมาคมโรงงานที่ลงทะเบียนด้วยตนเอง มันจะวางไข่ในแหล่งรวมของหน่วยงานทั่วโลก ดีและเรียบง่าย เราใช้จำนวนมากของ smart_ptr และ weak_ptr
BRaffle

1
ดังนั้น BananaRaffle: คุณจะบอกว่านี่เป็นบทสรุปที่ถูกต้องสำหรับคำตอบของคุณ: "โซลูชันทั้ง 3 ข้อที่คุณโพสต์มีการใช้เช่นเดียวกับคนอื่น ๆ อย่ามองหาโซลูชันที่สมบูรณ์แบบเพียงแค่ใช้สิ่งที่คุณต้องการ ."
Ipsquiggle

76
// in entity_a's code:
entity_b->takeDamage();

คุณถามว่าเกม comercial ทำอย่างไร ;)


8
โหวตลง? อย่างจริงจังนั่นเป็นวิธีปกติ ระบบ Entity นั้นยอดเยี่ยม แต่พวกเขาไม่ได้ช่วยให้เหตุการณ์สำคัญเร็วขึ้น
tenpn

ฉันสร้างเกม Flash อย่างมืออาชีพและนี่คือวิธีที่ฉันทำ คุณเรียกว่าศัตรู. ความเสียหาย (10) จากนั้นค้นหาข้อมูลใด ๆ ที่คุณต้องการจากผู้ได้รับสาธารณะ
เลน

7
นี่เป็นวิธีที่เอ็นจิ้นเกมเชิงพาณิชย์ทำอย่างจริงจัง เขาไม่ได้ล้อเล่น Target.NotifyTakeDamage (DamageType, DamageAmount, DamageDealer และอื่น ๆ ) เป็นวิธีการที่ปกติ
AA Grapsas

3
เกมเชิงพาณิชย์สะกดคำว่า "ความเสียหาย" ด้วยหรือไม่ :-P
Ricket

15
ใช่พวกมันสร้างความเสียหายด้วยการสะกดผิด :)
LearnCocos2D

17

คำตอบที่จริงจังมากขึ้น:

ฉันเห็นกระดานดำใช้มาก Simple version ไม่มีอะไรมากไปกว่า struts ที่อัปเดตด้วยสิ่งต่าง ๆ เช่น HP ของเอนทิตีซึ่งเอนทิตีสามารถค้นหาได้

กระดานดำของคุณอาจเป็นมุมมองของโลกของเอนทิตีนี้ (ถามกระดานดำของ B ว่า HP คืออะไร) หรือมุมมองของเอนทิตีของโลก (A ค้นหากระดานดำเพื่อดูว่าเป้าหมายของ HP คืออะไร

หากคุณอัปเดตกระดานดำที่จุดซิงค์ในเฟรมคุณสามารถอ่านได้จากจุดใดจุดหนึ่งในภายหลังจากเธรดใด ๆ ซึ่งทำให้การทำมัลติเธรดเป็นเรื่องง่าย

กระดานดำขั้นสูงอาจมีลักษณะเหมือนแฮชเทเบิ้ลการจับคู่สตริงกับค่า นี่คือการบำรุงรักษามากขึ้น แต่เห็นได้ชัดว่ามีค่าใช้จ่ายในการทำงาน

กระดานดำเป็นการสื่อสารทางเดียวแบบดั้งเดิม - มันจะไม่จัดการกับความเสียหายที่ dishing


ฉันไม่เคยได้ยินรุ่นกระดานดำมาก่อน
deft_code

พวกเขายังดีสำหรับการลดการพึ่งพาแบบเดียวกับที่คิวเหตุการณ์หรือรูปแบบการเผยแพร่ / สมัครสมาชิก
tenpn

2
นี่ยังเป็น“ คำจำกัดความ” ที่เป็นที่ยอมรับว่าระบบ“ อุดมคติ” E / C / S“ ควรทำงานได้อย่างไร” ส่วนประกอบต่าง ๆ ประกอบเป็นกระดานดำ ระบบคือรหัสที่แสดงถึงมัน (หน่วยงานแน่นอนเป็นเพียงlong long intหรือคล้ายกันในระบบ ECS บริสุทธิ์)
BRPocock

6

ฉันได้ศึกษาปัญหานี้เล็กน้อยและฉันได้เห็นวิธีแก้ปัญหาที่ดี

โดยทั่วไปทุกอย่างเกี่ยวกับระบบย่อย มันคล้ายกับแนวคิดกระดานดำที่กล่าวถึงโดย tenpn

เอนทิตีทำจากส่วนประกอบ แต่เป็นเพียงถุงทรัพย์สิน ไม่มีการใช้พฤติกรรมในเอนทิตี้ของตัวเอง

สมมติว่าเอนทิตีมีองค์ประกอบสุขภาพและองค์ประกอบความเสียหาย

จากนั้นคุณมี MessageManager และระบบย่อยสามระบบ: ActionSystem, DamageSystem, HealthSystem เมื่อถึงจุดหนึ่ง ActionSystem จะทำการคำนวณบนโลกของเกมและสร้างกิจกรรม:

HIT, source=entity_A target=entity_B power=5

เหตุการณ์นี้ถูกเผยแพร่ไปยัง MessageManager เมื่อถึงจุดหนึ่ง MessageManager จะผ่านข้อความที่ค้างอยู่และพบว่า DamageSystem ได้สมัครรับข่าวสาร HIT ตอนนี้ MessageManager ส่งข้อความ HIT ไปที่ DamageSystem ระบบ DamageSystem จะผ่านรายการของหน่วยงานที่มีองค์ประกอบความเสียหายคำนวณคะแนนความเสียหายขึ้นอยู่กับพลังโจมตีหรือสถานะอื่นของหน่วยงานทั้งสองเป็นต้นและเผยแพร่เหตุการณ์

DAMAGE, source=entity_A target=entity_B amount=7

HealthSystem ได้สมัครรับข้อความ DAMAGE และเมื่อ MessageManager เผยแพร่ข้อความ DAMAGE ไปยัง HealthSystem ระบบ HealthSystem สามารถเข้าถึงเอนทิตีเอนทิตีทั้งสองและเอนทิตีเอนทิตีของคอมโพเนนต์สุขภาพของพวกเขาดังนั้น HealthSystem สามารถทำการคำนวณได้ ไปที่ MessageManager)

ในเอ็นจิ้นเกมดังกล่าวรูปแบบของข้อความเป็นเพียงการเชื่อมต่อระหว่างส่วนประกอบและระบบย่อยทั้งหมด ระบบย่อยและเอนทิตีมีความเป็นอิสระอย่างสมบูรณ์และไม่รู้จักซึ่งกันและกัน

ฉันไม่รู้ว่าเอ็นจิ้นเกมจริงบางตัวได้นำความคิดนี้ไปใช้หรือไม่ แต่ดูเหมือนว่าจะค่อนข้างแข็งและสะอาดและฉันหวังว่าสักวันหนึ่งที่จะนำไปใช้กับตัวฉันเองสำหรับเอ็นจิ้นเกมระดับงานอดิเรกของฉัน


นี่เป็นคำตอบที่ดีกว่า IMO คำตอบที่ยอมรับได้ แยก, บำรุงรักษาและขยายได้ (และยังไม่ใช่ภัยพิบัติการมีเพศสัมพันธ์เหมือนคำตอบตลกของentity_b->takeDamage();)
Danny Yaroslavski

4

ทำไมไม่มีคิวข้อความร่วมกัน:

messageQueue.push_back(shared_ptr<Event>(new DamageEvent(entityB, 10, entityA)));

ด้วย:

DamageEvent(Entity* toDamage, uint amount, Entity* damageDealer);

และในตอนท้ายของการวนรอบเกม / การจัดการเหตุการณ์:

while(!messageQueue.empty())
{
    Event e = messageQueue.front();
    messageQueue.pop_front();
    e.Execute();
}

ฉันคิดว่านี่เป็นรูปแบบคำสั่ง และExecute()เป็นเสมือนจริงบริสุทธิ์Eventซึ่งอนุพันธ์กำหนดและทำสิ่งต่าง ๆ ดังนั้นที่นี่:

DamageEvent::Execute() 
{
    toDamage->takeDamage(amount); // Or of course, you could now have entityA get points, or a recognition of damage, or anything.
}

3

หากเกมของคุณเป็นผู้เล่นคนเดียวให้ใช้วิธีการของวัตถุเป้าหมาย (ตามคำแนะนำจาก tenpn)

หากคุณเป็น (หรือต้องการสนับสนุน) มัลติเพลเยอร์ (มัลติผู้เล่นจะต้องแน่นอน) ให้ใช้คิวคำสั่ง

  • เมื่อ A สร้างดาเมจให้กับ B บนไคลเอนต์ 1 เพียงแค่เข้าคิวเหตุการณ์ดาเมจ
  • ซิงโครไนซ์คิวคำสั่งผ่านเครือข่าย
  • จัดการกับคำสั่งที่จัดคิวทั้งสองด้าน

2
หากคุณจริงจังกับการหลีกเลี่ยงการโกง A ก็ไม่เป็นความลับ B สำหรับลูกค้าเลย ลูกค้าที่เป็นเจ้าของ A ส่งคำสั่ง "Attack B" ไปยังเซิร์ฟเวอร์ซึ่งทำสิ่งที่ tenpn พูด เซิร์ฟเวอร์จะซิงค์สถานะนั้นกับไคลเอ็นต์ที่เกี่ยวข้องทั้งหมด

@ โจ: ใช่ถ้ามีเซิร์ฟเวอร์ที่เป็นจุดที่ถูกต้องที่จะต้องพิจารณา แต่บางครั้งมันก็โอเคที่จะไว้วางใจลูกค้า (เช่นบนคอนโซล) เพื่อหลีกเลี่ยงการโหลดเซิร์ฟเวอร์จำนวนมาก
Andreas

2

ฉันจะบอกว่า: ใช้ไม่ได้ตราบใดที่คุณไม่ต้องการคำติชมแบบทันทีทันใดจากความเสียหาย

เอนทิตี / ส่วนประกอบที่รับความเสียหาย / อะไรก็ตามที่ควรผลักดันให้เหตุการณ์ไปสู่คิวเหตุการณ์ในท้องถิ่นหรือระบบในระดับที่เท่ากันซึ่งเก็บเหตุการณ์ความเสียหาย

ควรมีระบบการซ้อนทับที่สามารถเข้าถึงเอนทิตีทั้งสองที่ร้องขอกิจกรรมจากเอนทิตี a และส่งผ่านไปยังเอนทิตี b โดยการไม่สร้างระบบเหตุการณ์ทั่วไปที่ทุกสิ่งสามารถใช้จากที่ใดก็ได้เพื่อส่งเหตุการณ์ไปยังสิ่งใด ๆ ได้ตลอดเวลาคุณสร้างการไหลของข้อมูลที่ชัดเจนซึ่งจะทำให้โค้ดง่ายต่อการตรวจแก้จุดบกพร่องง่ายต่อการวัดประสิทธิภาพง่ายต่อการเข้าใจและอ่าน นำไปสู่ระบบการออกแบบที่ดีขึ้นโดยทั่วไป


1

เพียงโทรออก อย่าทำ request-hp ที่ folllowed โดย query-hp - ถ้าคุณทำตามโมเดลนั้นคุณจะอยู่ในโลกที่เจ็บปวด

คุณอาจต้องการดู Mono Continuations ด้วยเช่นกัน ฉันคิดว่ามันจะเหมาะสำหรับ NPC


1

แล้วจะเกิดอะไรขึ้นถ้าเรามีผู้เล่น A และ B ที่พยายามจะตีกันในรอบการอัพเดทเดียวกัน () สมมติว่า Update () สำหรับผู้เล่น A เกิดขึ้นก่อน Update () สำหรับผู้เล่น B ในรอบที่ 1 (หรือติ๊กหรืออะไรก็ตามที่คุณเรียก) มีสองสถานการณ์ที่ฉันนึกถึง:

  1. ประมวลผลทันทีผ่านข้อความ:

    • ผู้เล่น A. อัปเดต () เห็นผู้เล่นต้องการกด B ผู้เล่น B จะได้รับข้อความแจ้งความเสียหาย
    • ผู้เล่น B.HandleMessage () อัพเดท hitpoints สำหรับผู้เล่น B (เขาตาย)
    • ผู้เล่น B.Update () เห็นผู้เล่น B นั้นตายแล้ว .. เขาไม่สามารถโจมตีผู้เล่น A ได้

สิ่งนี้ไม่ยุติธรรมผู้เล่น A และ B ควรตีกันผู้เล่น B เสียชีวิตก่อนที่จะกดปุ่ม A เพียงเพราะเอนทิตี / gameobject ได้รับการอัปเดต () ในภายหลัง

  1. การจัดคิวข้อความ

    • ผู้เล่น A. อัปเดต () เห็นผู้เล่นต้องการกด B ผู้เล่น B ได้รับข้อความแจ้งความเสียหายและเก็บไว้ในคิว
    • ผู้เล่น A.Update () ตรวจสอบคิวมันว่างเปล่า
    • ผู้เล่น B.Update () ตรวจสอบการเคลื่อนไหวก่อนเพื่อให้ผู้เล่น B ส่งข้อความไปยังผู้เล่น A ที่มีความเสียหายเช่นกัน
    • ผู้เล่น B.Update () จัดการข้อความในคิวประมวลผลความเสียหายจากผู้เล่น A
    • รอบใหม่ (2): ผู้เล่น A ต้องการดื่มยาเพื่อสุขภาพดังนั้นผู้เล่น A. อัปเดต () จะถูกเรียกและการเคลื่อนไหวถูกประมวลผล
    • ผู้เล่น A.Update () ตรวจสอบคิวข้อความและประมวลผลความเสียหายจากผู้เล่น B

อีกครั้งนี้ไม่ยุติธรรม .. ผู้เล่น A ควรจะได้รับ hitpoint ในเทิร์น / รอบ / เห็บเดียวกัน!


4
คุณไม่ได้ตอบคำถามจริงๆ แต่ฉันคิดว่าคำตอบของคุณจะทำให้เป็นคำถามที่ยอดเยี่ยม ทำไมไม่ไปข้างหน้าและถามวิธีแก้ปัญหาการจัดลำดับความสำคัญ "ไม่ยุติธรรม" เช่นนี้?
bummzack

ฉันสงสัยว่าเกมส่วนใหญ่สนใจเกี่ยวกับความไม่ยุติธรรมนี้เพราะพวกเขาอัปเดตบ่อยครั้งจนแทบไม่มีปัญหา วิธีแก้ไขปัญหาอย่างง่ายอย่างหนึ่งคือสลับระหว่างการวนไปข้างหน้าและข้างหลังผ่านรายการเอนทิตีเมื่อทำการอัพเดต
Kylotan

ผมใช้ 2 สายเพื่อให้ผมเรียก Update () pEntity->Flush( pMessages );ไปยังหน่วยงานทั้งหมดแล้วหลังจากที่วงผมย้ำอีกครั้งและเรียกสิ่งที่ต้องการ เมื่อ entity_A สร้างเหตุการณ์ใหม่มันจะไม่ถูกอ่านโดย entity_B ในเฟรมนั้น (มีโอกาสที่จะทานยาด้วย) จากนั้นทั้งคู่จะได้รับความเสียหายและหลังจากนั้นพวกเขาจะประมวลผลข้อความของการบำบัดยาที่จะเป็นคนสุดท้ายในคิว . ผู้เล่น B ยังคงตายต่อไปเนื่องจากข้อความ potion เป็นลำดับสุดท้ายในคิว: P แต่อาจเป็นประโยชน์สำหรับข้อความประเภทอื่นเช่นการล้างตัวชี้ไปยังเอนทิตีที่ตายแล้ว
Pablo Ariel

ฉันคิดว่าในระดับเฟรมการใช้งานเกมส่วนใหญ่นั้นไม่ยุติธรรมเลย เหมือน Kylotan พูด
v.oddou

ปัญหานี้แก้ไขได้ง่ายเมามัน เพียงใช้ความเสียหายต่อกันในเครื่องมือจัดการข้อความหรืออะไรก็ตาม คุณไม่ควรตั้งค่าสถานะผู้เล่นว่าตายภายในตัวจัดการข้อความ ใน "Update ()" คุณเพียง แต่ทำ "if (hp <= 0) die ();" (ที่จุดเริ่มต้นของ "อัปเดต ()" เป็นต้น) ด้วยวิธีนี้ทั้งสองสามารถฆ่ากันในเวลาเดียวกัน นอกจากนี้: บ่อยครั้งที่คุณไม่ได้สร้างความเสียหายแก่ผู้เล่นโดยตรง แต่ผ่านวัตถุกลางบางอย่างเช่นกระสุน
ธารา
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.