หลายแหล่งที่มาของการเคลื่อนไหวในระบบเอนทิตี


9

ฉันค่อนข้างใหม่กับแนวคิดของระบบเอนทิตีที่ได้อ่านสิ่งต่าง ๆ (ส่วนใหญ่เป็นประโยชน์บล็อกที่ยอดเยี่ยมนี้และคำตอบนี้ )

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

นั่นคือฉันมีหน่วยงานของฉันซึ่งมีองค์ประกอบตำแหน่ง ฉันมีเหตุการณ์บางอย่างในเกมที่บอกเอนทิตีนี้ให้ย้ายระยะทางที่กำหนดในเวลาที่กำหนด

เหตุการณ์เหล่านี้สามารถเกิดขึ้นได้ตลอดเวลาและจะมีค่าแตกต่างกันสำหรับตำแหน่งและเวลา ผลก็คือพวกเขาจะรวมกัน

ในโซลูชัน OO แบบดั้งเดิมฉันมีMoveByคลาสบางประเภทที่มีระยะทาง / เวลาและอาเรย์ของผู้ที่อยู่ในคลาสอ็อบเจ็กต์เกมของฉัน แต่ละเฟรมฉันจะวนซ้ำทั้งหมดMoveByและนำไปใช้กับตำแหน่ง หาก a MoveByถึงเวลาสิ้นสุดแล้วให้ลบออกจากอาร์เรย์

ด้วยระบบเอนทิตี้ฉันสับสนนิดหน่อยว่าฉันควรทำซ้ำพฤติกรรมแบบนี้อย่างไร

หากมีเพียงหนึ่งในเหล่านี้ในแต่ละครั้งแทนที่จะสามารถรวมพวกเขาเข้าด้วยกันมันก็จะค่อนข้างตรงไปตรงมา (ฉันเชื่อ) และมีลักษณะเช่นนี้:

PositionComponent มี x, y

MoveByComponent มี x, y, time

Entityซึ่งมีทั้งPositionComponentและMoveByComponent

MoveBySystemที่รูปลักษณ์สำหรับนิติบุคคลที่มีทั้งส่วนประกอบเหล่านี้และเพิ่มมูลค่าของไปMoveByComponent PositionComponentเมื่อtimeถึงมันจะลบองค์ประกอบจากเอนทิตีนั้น

ฉันสับสนเล็กน้อยว่าฉันจะทำสิ่งเดียวกันได้อย่างไรด้วยการเคลื่อนไหวหลายอย่างด้วยกัน

ความคิดเริ่มต้นของฉันคือฉันจะมี:

PositionComponent, MoveByComponentเช่นเดียวกับข้างต้น

MoveByCollectionComponentซึ่งมีอาร์เรย์ของMoveByComponents

MoveByCollectionSystemที่มองหาเอนทิตีที่มีPositionComponentและ a MoveByCollectionComponent, วนซ้ำMoveByComponents ข้างในนั้น, ใช้ / ลบตามความจำเป็น

ฉันเดาว่านี่เป็นปัญหาทั่วไปมากขึ้นของการมีองค์ประกอบเดียวกันจำนวนมากและต้องการให้ระบบที่เกี่ยวข้องดำเนินการกับแต่ละองค์ประกอบ เอนทิตีของฉันมีส่วนประกอบอยู่ภายในแฮชของประเภทคอมโพเนนต์ -> ส่วนประกอบดังนั้นจึงมีองค์ประกอบของประเภทใดประเภทหนึ่งต่อเอนทิตีอย่างเคร่งครัดเท่านั้น

  1. นี่เป็นวิธีที่ถูกต้องหรือไม่

  2. เอนทิตีควรมีองค์ประกอบหนึ่งประเภทที่กำหนดตลอดเวลาหรือไม่?


1
ฟังดูคล้ายกับว่าMoveByฟังก์ชั่นเป็นเพียงแค่ความเร็ว? ดูเหมือนคุณจะอยู่ในเส้นทางที่ถูกต้อง สำหรับคำถามที่สองของคุณมีการใช้งานที่แตกต่างกันมากมายของระบบเอนทิตี / ส่วนประกอบ สิ่งที่อธิบายไว้ในคำตอบของฉันที่คุณเชื่อมโยงจะมีองค์ประกอบหนึ่งประเภทเท่านั้น
MichaelHouse

เรียงลำดับจาก, แต่ความแตกต่างที่ว่าความเร็วนี้ใช้ได้เฉพาะจากเวลาหนึ่งไปยังอีก, และหลายคนสามารถรวมกันในคราวเดียว. ฉันคิดว่าฉันแค่ต้องการความมั่นใจฉันเข้มงวด (เกือบเกือบ) OO สำหรับเกมของฉันในอดีต - ซึ่งหลายปีต่อมาในโครงการเดียวกันทำให้ความเร็วในการผลิตของเราหมดไป - และนี่เป็นดินแดนที่ไม่คุ้นเคย;) . คำตอบที่ดีในการโพสต์อื่น ๆ โดยวิธีช่วยล้างบางสิ่งบางอย่าง
Sticky

ฉันทำสิ่งนี้: ฉันมี PlayerInputComponent และ AIInputComponent (หรือระบบ) ที่จะบอก MobileBehaviorComponent ว่าเมื่อคลิกที่แป้นพิมพ์หรือบน AI คิดว่ามือถือควรย้ายที่ใดที่หนึ่ง MobileBehaviorComponent จะเก็บไว้ที่ใดที่หนึ่ง และบางระบบจะเคลื่อนย้าย ความละเอียดของคุณมากเกินไปด้วยส่วนประกอบระดับสูงเช่นการแปลงแบบจำลองแสงทุกอย่างทำงานได้ดีเช่นกัน นอกจากนี้ฉันไม่จำเป็นต้องลบส่วนประกอบ - ฉันคิดว่ามันเหมือนกับสิ่งที่อธิบายถึงวัตถุของเกมดังนั้นมันจึงไม่สามารถหายไปได้
Kikaimaru

ตัวอย่าง MoveBy นี้เป็นเพียงตัวอย่างเท่านั้น คำถามเกี่ยวกับวิธีการรวมสิ่งต่างๆเข้าด้วยกันเช่นนั้น ถ้าฉันต้องการพูดโดยเฉพาะ 'ย้ายโดย x = 5 และ y = 6 ใน 5 วินาที' 'ย้ายโดย x = 10 y = 2 ใน 10 วินาที' ในเวลาเดียวกันนี่เป็นวิธีที่ฉันจะทำหรือไม่
Sticky

คุณหมายถึงอะไร "ผสมกัน"? ชอบเพิ่มความเร็ว? ดังนั้นถ้าคุณทบต้นmove x by 10 in 2 secondsและmove x by -10 in 2 secondsเอนทิตีจะหยุดนิ่งอย่างสมบูรณ์?
Tom Dalling

คำตอบ:


6

สำหรับสถานการณ์ของคุณโดยทั่วไปเราจะเพิ่มสามองค์ประกอบในวัตถุเกม:

  1. TransformComponent (ตำแหน่งการวางแนวขนาด)
  2. VelocityComponent (ความเร็วทิศทาง)
  3. ControllerComponent

เมื่อวัตถุในเกมต้องการฟังก์ชั่น AI บางประเภทเช่นการเคลื่อนที่ไปตามเส้นทางที่คุณอธิบายไว้เราได้กำหนด AIController ให้กับรายการส่วนประกอบ AIControllers ไม่มีอะไรมากไปกว่าเสื้อคลุมที่เดินตามต้นไม้พฤติกรรม แผนผังพฤติกรรมเป็นที่ที่เราออกแบบฟังก์ชันการทำงานจริงที่เราต้องการให้วัตถุเกมทำงานเช่น:

BehaviorTree* tree(new SequentialNode());
tree->addChild(new MoveToNode(x,y,z));
tree->addChild(new WaitNode(30));
tree->addChild(new MoveToNode(a,b,c));
tree->addChild(new WaitNode(30));
gameObject->addComponent(new AIController(tree));

ระบบย่อย AI จัดการ AIControllers และระบบย่อยจะทำเครื่องหมายที่ตัวควบคุมซึ่งจะทำตามขั้นตอนของแผนผังพฤติกรรม MoveToNode () ดูที่ตำแหน่ง / ทิศทางปัจจุบันคำนวณเวกเตอร์ทิศทางและความเร็วไปยังตำแหน่งที่คุณต้องการย้ายไปตามอาร์กิวเมนต์คอนสตรัคเตอร์ของมันและตั้งค่าในองค์ประกอบความเร็ว ระบบการเคลื่อนไหวมีหน้าที่ในการอ่านองค์ประกอบการเคลื่อนไหวที่มีค่าและการประยุกต์ฟิสิกส์จึงปรับปรุงตำแหน่ง / ทิศทางตาม

โค้ดด้านบนเพียงแค่ย้ายวัตถุเกมจากสถานที่วางไข่ไปยัง x, y, z ในพื้นที่โลกจากนั้นรออย่างน้อย 30 วินาทีจากนั้นย้ายวัตถุเกมไปยังตำแหน่ง a, b, c และรออีก 30 วินาที เมื่อการรอเสร็จสิ้นลำดับพฤติกรรมจะสิ้นสุดลงดังนั้นจึงเริ่มซ้ำตั้งแต่ต้น

สิ่งนี้ช่วยให้คุณสามารถกำหนดฟังก์ชั่น AI ที่คุณต้องการได้เองในระบบย่อย AI ได้อย่างง่ายดายโดยส่งผลกระทบต่อระบบย่อยเอนทิตีของคุณน้อยที่สุด นอกจากนี้ยังช่วยให้คุณสามารถเก็บรายการองค์ประกอบของระบบเอนทิตีของคุณแบบลีนโดยไม่ต้องมีรายละเอียดมากเกินไป


1

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

ตัวอย่างเช่น: สร้างคลาสตัวควบคุมฐานด้วยเมธอด run () หรือถ้าคุณไม่ชอบชื่อที่เรียกว่า think (), update () หรือติ๊ก () จากนั้นคุณรับช่วงจากมันและสร้าง MoveController, NPCController, PlayerInputController (สำหรับเอนทิตีผู้เล่น), PhysicController; จากนั้นคุณใช้เมธอด run () ฉันจะใส่ MoveByComponent ของคุณไว้ใน MoveController ไม่ใช่ใน Entity

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

ในเกมที่กำลังพัฒนาของฉันฉันมี MoveController ที่ย้ายเอนทิตีตามเส้นทางหนึ่ง MoveController มีอยู่สำหรับ NPC แต่ละตัวและตัวละครของผู้เล่น บางครั้งมีการสร้างกล่องหรือหินที่ผู้เล่นสามารถผลัก PhysicController เพียงอินสแตนซ์เดียวเท่านั้นที่จะตรวจสอบตำแหน่งของเอนทิตีทั้งหมดที่กำหนดให้ถ้าบางเอนทิตีชนเอนทิตีที่ได้รับมอบหมายอีกตำแหน่งที่คำนวณผลลัพธ์ของทั้งสองจะถูกคำนวณ (จริง ๆ แล้วมันจะทำมากกว่านั้น NPCController คือ AI หนึ่งอินสแตนซ์ต่อ NPC มันจะตรวจสอบสถานการณ์ของ NPC และตัดสินใจว่าจะย้ายที่ใดจากนั้นผลักเส้นทางไปยัง MoveController ซึ่งจะย้าย NPC จริง คอนโทรลเลอร์มีลำดับความสำคัญดังนั้นฉันจึงสามารถกำหนดลำดับล่วงหน้าได้ล่วงหน้า PhysicController เป็นคนสุดท้ายที่จะดำเนินการ

ฉันสนับสนุนตัวควบคุม แต่ไม่ใช่ตัวเลือก "ถูกต้อง" เท่านั้น ตัวอย่างเช่นฉันจำอินเทอร์เฟซเอนทิตีในเอ็นจิ้น Cafu ที่มีเมธอด think () ในเอนทิตีเองผู้ใช้ของคลาสจะต้องสืบทอดจากเอนทิตีและใช้การคิด () ฉันจำคลาสที่ได้รับชื่อ CompanyBot (ที่มาพร้อมกับตัวอย่าง) เกม) ที่ทำการตรวจสอบการชนกันของข้อมูลในวิธีการนั้นเนื่องจากมันถูกเรียกว่า "คิด" เราสามารถสันนิษฐานได้ว่าโค้ด AI นั้นจะต้องอยู่ที่นั่นด้วย ในขณะที่เครื่องยนต์ NeoAxis (ครั้งล่าสุดที่ฉันดูเข้าไป) ให้ AI และฟิสิกส์แยกออกจากเอนทิตี

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


นั่นเป็นเพียงการออกแบบ OO ที่เรามีอยู่ในขณะนี้ กิจการที่มีอนุพันธ์ (ตัวละครสัตว์ประหลาด) เป็นต้นฉันเป็นผู้นำทีมของเราที่ทำงานเกี่ยวกับเกมนี้เต็มเวลาเป็นเวลาเกือบ 2 ปีและเมื่อทุกคนเปลี่ยนสิ่งต่าง ๆ ตามความประสงค์มันก็น่ากลัวและน่ากลัว codebase - และเริ่มใช้เวลานานในการรับฟีเจอร์ใหม่ที่ส่งมา ความคิด Entity ระบบน่าจะเป็นว่าสิ่งที่ฉันกำลังมองหาดังนั้นในขณะที่คำตอบคือไม่เกี่ยวข้องค่อนข้างคุณควรอ่านข้อมูลเกี่ยวกับการเชื่อมโยงที่ด้านบนของคำถามด้วยตัวเองดูว่าพวกเขาสามารถช่วยให้คุณออก :)
ปักหมุด

@ Sticky ฉันต้องยอมรับว่า Node System plus Entity ที่ทำจากส่วนประกอบเป็นวิธีที่ชาญฉลาดในการแสดงระบบที่ต้องการที่แตกต่างจากวิธีการควบคุมที่ฉันแนะนำซึ่งคล้ายกับรุ่นที่พัฒนาน้อยกว่า คุณไม่ต้องการคำตอบของฉันจริงๆ
Hatoru Hansou

ไม่ต้องห่วง. วิธี OO มีข้อดี แต่สิ่งที่น่าเกลียดรวดเร็ว
Sticky
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.