มันสมเหตุสมผลหรือไม่ที่จะสร้างแอปพลิเคชั่น (ไม่ใช่เกม) โดยใช้สถาปัตยกรรมส่วนประกอบ - เอนทิตี้ของระบบ?


24

ฉันรู้ว่าเมื่อสร้างแอปพลิเคชั่น (ดั้งเดิมหรือเว็บ) เช่นใน Apple AppStore หรือ Google Play app store นั้นเป็นเรื่องธรรมดามากที่จะใช้สถาปัตยกรรม Model-View-Controller

อย่างไรก็ตามมันมีเหตุผลที่จะสร้างแอพพลิเคชั่นที่ใช้สถาปัตยกรรม Component-Entity-System ทั่วไปในเอ็นจิ้นเกมหรือไม่?


1
ตรวจสอบสถาปัตยกรรมของ Light Table: chris-granger.com/2013/01/24/the-ide-as-data
Hakan Deryal

คำตอบ:


39

อย่างไรก็ตามมันมีเหตุผลที่จะสร้างแอพพลิเคชั่นที่ใช้สถาปัตยกรรม Component-Entity-System ทั่วไปในเอ็นจิ้นเกมหรือไม่?

สำหรับฉันอย่างแน่นอน ฉันทำงานใน visual FX และศึกษาระบบที่หลากหลายในสาขานี้สถาปัตยกรรมของพวกเขา (รวมถึง CAD / CAM), หิวสำหรับ SDK และเอกสารใด ๆ ที่จะให้ความรู้สึกถึงข้อดีข้อเสียของการตัดสินใจทางสถาปัตยกรรมที่ไม่มีที่สิ้นสุด สามารถทำได้แม้กระทั่งสิ่งที่บอบบางที่สุดก็ไม่ได้สร้างผลกระทบที่ลึกซึ้งเสมอไป

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

อีกแนวคิดที่คล้ายกันกับเอ็นจิ้นเกมที่ซับซ้อนอย่างน้อยก็คือความต้องการมุมมอง "ผู้ออกแบบ" ที่นักออกแบบสามารถออกแบบฉากได้อย่างยืดหยุ่นรวมถึงความสามารถในการเขียนโปรแกรมแบบเบาของตนเอง (สคริปต์และโหนด)

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

OOP แบบดั้งเดิม

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

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

การรวมอินเทอร์เฟซที่ละเอียดหลายอย่างเข้าด้วยกันเพื่อสร้างอินเทอร์เฟซที่สอดคล้องกันของวัตถุสามารถช่วยได้มากในการรักษาเสถียรภาพของรหัสลูกค้า แต่ก็ไม่ได้ช่วยในการรักษาเสถียรภาพของชนิดย่อยซึ่งบางครั้งอาจ คุณสามารถมีหนึ่งอินเทอร์เฟซที่ถูกใช้โดยส่วนหนึ่งของระบบของคุณเท่านั้นตัวอย่างเช่น แต่มีชนิดย่อยที่แตกต่างกันหลายพันชนิดที่นำอินเตอร์เฟสมา ในกรณีดังกล่าวการรักษาชนิดย่อยที่ซับซ้อน (ซับซ้อนเนื่องจากมีความรับผิดชอบอินเทอร์เฟซที่แตกต่างกันจำนวนมากเพื่อเติมเต็ม) สามารถกลายเป็นฝันร้ายมากกว่ารหัสที่ใช้พวกมันผ่านทางอินเตอร์เฟส OOP มีแนวโน้มที่จะถ่ายโอนความซับซ้อนไปยังระดับวัตถุในขณะที่ ECS ถ่ายโอนไปยังระดับไคลเอนต์ ("ระบบ") และอาจเหมาะเมื่อมีระบบน้อยมาก แต่ทั้งกลุ่มสอดคล้องของ "วัตถุ" ("เอนทิตี้")

ป้อนคำอธิบายรูปภาพที่นี่

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

นั่นคือสิ่งที่แนวทางแบบ ECS ของการสร้างบล็อกเลโก้เหล่านี้จะมีประโยชน์มาก นอกจากนี้เมื่อระบบมีการออกแบบที่หยาบกว่าวัตถุทั่วไปมันจะง่ายกว่าที่จะรักษาค่าคงที่แบบหยาบเหล่านั้นไว้ที่มุมมองที่มองด้วยตาของระบบ การโต้ตอบกับวัตถุเล็ก ๆ จำนวนมากกลายเป็นระบบขนาดใหญ่เพียงระบบเดียวที่มุ่งเน้นไปที่งานกว้าง ๆ แทนที่จะเป็นวัตถุเล็ก ๆ ที่เน้นงานเล็ก ๆ น้อย ๆ ด้วยกราฟการพึ่งพาซึ่งจะครอบคลุมกระดาษหนึ่งกิโลเมตร

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

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

ยุค 80 Brute Force Architecture

สถาปัตยกรรมแรกที่ฉันทำงานในอุตสาหกรรม VFX มีมรดกที่ยาวนานซึ่งผ่านมานับสิบปีตั้งแต่ฉันเข้าร่วม บริษัท มันคือเดรัจฉานบังคับ C ดิบเข้ารหัสตลอดทาง (ไม่เอียงบน C, ฉันรัก C แต่วิธีที่มันถูกใช้ที่นี่เป็นน้ำมันดิบจริงๆ) ชิ้นส่วนขนาดเล็กและขนาดใหญ่คล้ายการขึ้นต่อกันเช่นนี้

ป้อนคำอธิบายรูปภาพที่นี่

และนี่คือไดอะแกรมที่ง่ายขึ้นอย่างมากของชิ้นส่วนเล็ก ๆ ของระบบ ลูกค้าแต่ละรายในแผนภาพ ("การเรนเดอร์", "ฟิสิกส์", "โมชั่น") จะได้รับวัตถุ "ทั่วไป" ซึ่งพวกเขาจะตรวจสอบฟิลด์ประเภทเช่น:

void transform(struct Object* obj, const float mat[16])
{
    switch (obj->type)
    {
        case camera:
            // cast to camera and do something with camera fields
            break;
        case light:
            // cast to light and do something with light fields
            break;
        ...
    }
}

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

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

ข้อดีบางประการ:

  • เอ่อ ... ไม่ได้มีประสบการณ์ด้านวิศวกรรมเลยฉันเดา? ระบบนี้ไม่ต้องการความรู้ใด ๆ เกี่ยวกับแนวคิดพื้นฐานเช่น polymorphism มันเป็นพลังที่ไร้เดียงสาดังนั้นฉันจึงเดาว่าแม้แต่ผู้เริ่มต้นอาจจะเข้าใจโค้ดบางส่วนได้แม้ว่ามืออาชีพที่ดีบั๊กสามารถรักษามันได้

ข้อเสียบางอย่าง:

  • การบำรุงรักษาฝันร้าย ทีมการตลาดของเรารู้สึกว่าจำเป็นที่จะต้องอวดว่าเราแก้ไขข้อผิดพลาดที่ไม่ซ้ำกันกว่า 2,000 รายการในรอบ 3 ปีเดียว สำหรับฉันนั่นเป็นสิ่งที่น่าอายเกี่ยวกับที่เรามีข้อบกพร่องมากมายตั้งแต่แรกและกระบวนการนั้นอาจจะยังคงแก้ไขเพียงประมาณ 10% ของข้อผิดพลาดทั้งหมดซึ่งเติบโตขึ้นเป็นจำนวนมากตลอดเวลา
  • เกี่ยวกับวิธีการที่ยืดหยุ่นที่สุด

สถาปัตยกรรมยุค 90 COM

อุตสาหกรรม VFX ส่วนใหญ่ใช้สถาปัตยกรรมรูปแบบนี้จากสิ่งที่ฉันได้รวบรวมอ่านเอกสารเกี่ยวกับการตัดสินใจในการออกแบบของพวกเขาและดูที่ชุดพัฒนาซอฟต์แวร์ของพวกเขา

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

ป้อนคำอธิบายรูปภาพที่นี่

ด้วยวิธีการเช่นนี้transformฟังก์ชันแบบอะนาล็อกด้านบนจะคล้ายกับแบบฟอร์มนี้:

void transform(Object obj, const Matrix& mat)
{
    // Wrapper that performs an interface query to see if the 
    // object implements the IMotion interface.
    MotionRef motion(obj);

    // If the object supported the IMotion interface:
    if (motion.valid())
    {
        // Transform the item through the IMotion interface.
        motion->transform(mat);
        ...
    }
}

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

ข้อดีบางประการ:

  • มีความยืดหยุ่น / ยืด / บำรุงรักษาได้ดีกว่าสารละลายเดรสแรงก่อนหน้านี้อย่างมาก
  • ส่งเสริมความสอดคล้องที่แข็งแกร่งกับหลักการมากมายของ SOLID โดยการทำให้ทุกส่วนต่อประสานเป็นนามธรรมอย่างสมบูรณ์

ข้อเสียบางอย่าง:

  • มากมายสำเร็จรูป ส่วนประกอบของเราต้องได้รับการเผยแพร่ผ่านรีจิสตรีเพื่อสร้างอินสแตนซ์ของวัตถุอินเทอร์เฟซที่รองรับนั้นจำเป็นต้องมีทั้งการสืบทอด ("การนำไปใช้" ใน Java) ส่วนต่อประสานและให้รหัสบางอย่างเพื่อระบุว่า
  • เลื่อนระดับตรรกะที่ซ้ำกันไปทั่วสถานที่อันเป็นผลมาจากอินเทอร์เฟซบริสุทธิ์ ตัวอย่างเช่นส่วนประกอบทั้งหมดที่นำมาใช้IMotionจะมีสถานะที่แน่นอนเหมือนกันและการใช้งานที่เหมือนกันแน่นอนสำหรับฟังก์ชั่นทั้งหมด เพื่อลดสิ่งนี้เราจะเริ่มรวบรวมคลาสพื้นฐานและฟังก์ชันผู้ช่วยทั่วทั้งระบบสำหรับสิ่งต่าง ๆ ที่มีแนวโน้มที่จะนำไปใช้ซ้ำซ้อนในลักษณะเดียวกันสำหรับอินเทอร์เฟซเดียวกันและอาจมีมรดกหลายอย่างเกิดขึ้นหลังฝากระโปรง ยุ่งภายใต้ประทุนแม้ว่ารหัสลูกค้าจะง่าย
  • การไม่มีประสิทธิภาพ: เซสชัน vtune มักแสดงให้เห็นว่าQueryInterfaceฟังก์ชั่นพื้นฐานมักจะแสดงเป็นฮอตสปอตกลางถึงบนและบางครั้งแม้แต่ฮอตสปอตอันดับ 1 เพื่อลดสิ่งนั้นเราจะทำสิ่งต่าง ๆ เช่นมีการเรนเดอร์ส่วนต่าง ๆ ของ codebase cache ซึ่งเป็นรายการของออบเจ็กต์ที่ทราบแล้วว่าให้การสนับสนุนIRenderableแต่นั่นเพิ่มความซับซ้อนและค่าบำรุงรักษาอย่างมาก ในทำนองเดียวกันนี่เป็นการวัดที่ยากขึ้น แต่เราสังเกตเห็นการชะลอตัวที่แน่นอนบางอย่างเมื่อเทียบกับการเข้ารหัสแบบ C ที่เราทำก่อนหน้านี้เมื่อทุกอินเทอร์เฟซเดียวต้องการการแจกจ่ายแบบไดนามิก สิ่งต่าง ๆ เช่นการคาดคะเนของสาขาและอุปสรรคการปรับให้เหมาะสมนั้นยากที่จะวัดนอกโค้ดเพียงเล็กน้อย แต่ผู้ใช้มักสังเกตเห็นการตอบสนองของอินเทอร์เฟซผู้ใช้และสิ่งต่าง ๆ เช่นแย่ลงโดยการเปรียบเทียบซอฟต์แวร์รุ่นก่อนหน้าและใหม่กว่า ด้านสำหรับพื้นที่ที่ความซับซ้อนของอัลกอริทึมไม่เปลี่ยนแปลงมีเพียงค่าคงที่เท่านั้น
  • ยังคงยากที่จะให้เหตุผลเกี่ยวกับความถูกต้องในระดับระบบที่กว้างขึ้น แม้ว่ามันจะง่ายกว่าวิธีการก่อนหน้านี้อย่างมีนัยสำคัญ แต่ก็ยังยากที่จะเข้าใจการโต้ตอบที่ซับซ้อนระหว่างวัตถุต่างๆในระบบนี้
  • เรามีปัญหาในการแก้ไขอินเตอร์เฟสให้ถูกต้อง แม้ว่าอาจจะมีเพียงสถานที่กว้าง ๆ แห่งเดียวในระบบที่ใช้อินเทอร์เฟซ แต่ความต้องการของผู้ใช้จะเปลี่ยนไปตามรุ่นและเราจะต้องทำการลดหลั่นการเปลี่ยนแปลงในคลาสทั้งหมดที่ใช้อินเทอร์เฟซเพื่อรองรับฟังก์ชั่นใหม่ อินเทอร์เฟซเช่นถ้ามีบางส่วนที่เป็นนามธรรมชั้นฐานที่รวมศูนย์ตรรกะใต้กระโปรง (บางคนจะปรากฏอยู่ตรงกลางของการเปลี่ยนแปลงเหล่านี้ลดหลั่นลงไปด้วยความหวังว่าจะไม่ทำอย่างนี้ซ้ำแล้วซ้ำอีก)

ป้อนคำอธิบายรูปภาพที่นี่

การตอบสนองในทางปฏิบัติ: องค์ประกอบ

หนึ่งในสิ่งที่เราสังเกตเห็นก่อนหน้านี้ (หรืออย่างน้อยฉันก็เป็น) ที่ก่อให้เกิดปัญหาก็คือIMotionอาจมีการใช้งานโดยคลาสที่แตกต่างกัน 100 คลาส แต่มีการใช้งานแบบเดียวกันและมีสถานะเกี่ยวข้อง ยิ่งไปกว่านั้นมันจะถูกใช้โดยระบบเพียงไม่กี่อย่างเช่นการเรนเดอร์การเคลื่อนไหวแบบ keyframed และฟิสิกส์

ดังนั้นในกรณีเช่นนี้เราอาจมีความสัมพันธ์แบบ 3 ต่อ 1 ระหว่างระบบโดยใช้ส่วนต่อประสานกับส่วนต่อประสานและความสัมพันธ์แบบ 100 ต่อ 1 ระหว่างชนิดย่อยที่ใช้ส่วนต่อประสานกับส่วนต่อประสาน

ความซับซ้อนและการบำรุงรักษานั้นก็จะถูกบิดเบือนอย่างมากในการดำเนินงานและการบำรุงรักษา 100 ชนิดย่อยแทน 3 IMotionระบบไคลเอนต์ที่ขึ้นอยู่กับ สิ่งนี้เปลี่ยนความยากลำบากในการบำรุงรักษาทั้งหมดของเราเป็นการบำรุงรักษา 100 ชนิดย่อยเหล่านี้ไม่ใช่ 3 แห่งที่ใช้อินเทอร์เฟซ การอัปเดต 3 ตำแหน่งในรหัสด้วยน้อยหรือไม่มี "ข้อต่อทางอ้อมที่ออกผล" (เป็นการอ้างอิงผ่านทางอินเทอร์เฟซไม่ใช่แบบพึ่งพาโดยตรง) ไม่ใช่เรื่องใหญ่: การอัปเดต 100 ชนิดย่อยด้วยการโหลดข้อมูล เรื่องใหญ่ *

* ฉันรู้ว่ามันแปลกและผิดที่จะสกรูกับคำจำกัดความของ "ข้อต่อที่ผิดปกติ" ในแง่นี้จากมุมมองของการนำไปใช้ฉันไม่พบวิธีที่ดีกว่าในการอธิบายความซับซ้อนในการบำรุงรักษาที่เกี่ยวข้องเมื่อทั้งสองอินเทอร์เฟซ ต้องเปลี่ยน

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

การเชื่อมต่อจึงกลายเป็นเหมือนวงกว้างที่Behaviorsเกี่ยวข้องกับเอนทิตี IMotionก็จะกลายเป็นMotion"องค์ประกอบ" (ฉันเปลี่ยนวิธีที่เรากำหนด "องค์ประกอบ" ออกจาก COM เป็นหนึ่งที่อยู่ใกล้กับคำนิยามปกติของชิ้นส่วนที่ทำขึ้นนิติบุคคล "สมบูรณ์")

แทนสิ่งนี้:

class IMotion
{
public:
    virtual ~IMotion() {}
    virtual void transform(const Matrix& mat) = 0;
    ...
};

เราพัฒนามันเป็นแบบนี้:

class Motion
{
public:
    void transform(const Matrix& mat)
    {
        ...
    }
    ...

private:
    Matrix transformation;
    ...
};

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

ดังนั้นเราจึงเริ่มพัฒนาการออกแบบนี้ กลายเป็นมากขึ้นเช่นQueryInterface QueryBehaviorยิ่งกว่านั้นมันเริ่มไร้ประโยชน์ที่จะใช้การสืบทอดที่นี่ เราใช้การแต่งเพลงแทน วัตถุกลายเป็นชุดของส่วนประกอบที่มีความสามารถในการสอบถามและฉีดที่รันไทม์

ป้อนคำอธิบายรูปภาพที่นี่

ข้อดีบางประการ:

  • เป็นเรื่องง่ายกว่าที่เราจะรักษาไว้ในกรณีของเรามากกว่าระบบ COM-style บริสุทธิ์ที่ผ่านมา ความประหลาดใจที่ไม่คาดคิดเช่นการเปลี่ยนแปลงข้อกำหนดหรือข้อร้องเรียนเวิร์กโฟลว์สามารถรองรับได้ง่ายขึ้นด้วยการใช้งานที่เป็นศูนย์กลางและเห็นได้ชัดเจนMotionเช่นและไม่แยกย้ายกันไปหลายร้อยชนิดย่อย
  • มอบความยืดหยุ่นในระดับใหม่ที่เราต้องการ ในระบบก่อนหน้าของเราเนื่องจากการสืบทอดโมเดลเป็นความสัมพันธ์แบบคงที่เราสามารถกำหนดเอนทิตีใหม่ได้อย่างมีประสิทธิภาพ ณ เวลารวบรวมใน C ++ เราไม่สามารถทำได้จากภาษาสคริปต์เช่นด้วยวิธีการจัดแต่งเราสามารถรวบรวมหน่วยงานใหม่ได้อย่างรวดเร็วในขณะทำงานด้วยการแนบส่วนประกอบเข้ากับรายการและเพิ่มเข้าไปในรายการ "เอนทิตี" กลายเป็นผืนผ้าใบว่างเปล่าซึ่งเราสามารถรวบรวมภาพของสิ่งที่เราต้องการได้ทันทีโดยระบบที่เกี่ยวข้องจะจดจำและประมวลผลเอนทิตีเหล่านี้โดยอัตโนมัติ

ข้อเสียบางอย่าง:

  • เรายังคงมีช่วงเวลาที่ยากลำบากในแผนกประสิทธิภาพและการบำรุงรักษาในพื้นที่สำคัญด้านประสิทธิภาพ แต่ละระบบจะยังคงต้องการที่จะแคชองค์ประกอบของเอนทิตีที่ให้พฤติกรรมเหล่านี้เพื่อหลีกเลี่ยงการวนซ้ำพวกเขาทั้งหมดและตรวจสอบสิ่งที่มีอยู่ แต่ละระบบที่ต้องการประสิทธิภาพจะทำสิ่งนี้แตกต่างกันเล็กน้อยและมีแนวโน้มที่จะมีชุดของข้อบกพร่องที่แตกต่างกันในการไม่สามารถอัปเดตรายการแคชนี้และอาจเป็นโครงสร้างข้อมูล (ถ้าการค้นหาบางรูปแบบเกี่ยวข้อง เหตุการณ์เปลี่ยนฉากที่ไม่ชัดเจนเช่น
  • ยังมีบางสิ่งที่น่าอึดอัดใจและซับซ้อนที่ฉันไม่สามารถจับนิ้วมือของฉันเกี่ยวกับวัตถุเล็ก ๆ น้อย ๆ ที่เป็นพฤติกรรมง่าย ๆ เหล่านี้ได้ เรายังคงวางเหตุการณ์จำนวนมากเพื่อจัดการกับการโต้ตอบระหว่างวัตถุ "พฤติกรรม" เหล่านี้ซึ่งบางครั้งจำเป็นและผลลัพธ์ก็คือรหัสที่มีการกระจายอำนาจอย่างมาก วัตถุเล็ก ๆ แต่ละชิ้นนั้นง่ายต่อการทดสอบความถูกต้องและถ่ายทีละตัวซึ่งมักจะถูกต้องสมบูรณ์แบบ แต่มันก็ยังรู้สึกเหมือนว่าเรากำลังพยายามรักษาระบบนิเวศขนาดใหญ่ที่ประกอบด้วยหมู่บ้านเล็ก ๆ และพยายามให้เหตุผลเกี่ยวกับสิ่งที่พวกเขาทำและรวมกันเพื่อทำทั้งหมด codebase ยุค 80 ของ C-style ให้ความรู้สึกเหมือนหนึ่งมหากาพย์ megalopolis ที่มีพลเมืองมากเกินไปซึ่งเป็นฝันร้ายของการบำรุงรักษาแน่นอน
  • การสูญเสียความยืดหยุ่นเมื่อขาดสิ่งที่เป็นนามธรรม แต่ในพื้นที่ที่เราไม่เคยพบเจอกับความต้องการที่แท้จริงของมันมันแทบจะเป็นข้อปฏิบัติที่ปฏิบัติได้จริง (อย่างน้อยก็เป็นทฤษฎีอย่างหนึ่ง)
  • การรักษาความเข้ากันได้ของ ABI นั้นยากเสมอและสิ่งนี้ทำให้มันยากขึ้นโดยต้องการข้อมูลที่มีเสถียรภาพและไม่ใช่แค่ส่วนต่อประสานที่เสถียรที่เกี่ยวข้องกับ "พฤติกรรม" อย่างไรก็ตามเราสามารถเพิ่มพฤติกรรมใหม่ ๆ ได้อย่างง่ายดายและลดค่าใช้จ่ายที่มีอยู่หากต้องการการเปลี่ยนแปลงสถานะและนั่นง่ายกว่าการทำ backflips ใต้ส่วนต่อประสานที่ระดับย่อยเพื่อจัดการข้อกังวลเกี่ยวกับเวอร์ชัน

ปรากฏการณ์หนึ่งที่เกิดขึ้นคือเนื่องจากเราสูญเสียสิ่งที่เป็นนามธรรมในองค์ประกอบพฤติกรรมเหล่านี้เราจึงมีสิ่งเหล่านี้มากขึ้น ตัวอย่างเช่นแทนที่จะเป็นIRenderableองค์ประกอบนามธรรมเราต้องการแนบวัตถุที่มีรูปธรรมMeshหรือPointSpritesส่วนประกอบ ระบบการเรนเดอร์จะรู้วิธีการเรนเดอร์MeshและPointSpritesส่วนประกอบและจะค้นหาเอนทิตีที่จัดเตรียมส่วนประกอบดังกล่าว ในเวลาอื่น ๆ ที่เรามี renderables อื่น ๆ เช่นSceneLabelที่เราค้นพบว่าเราจำเป็นย้อนหลังและอื่น ๆ ที่เราต้องการแนบSceneLabelในกรณีดังกล่าวไปยังหน่วยงานที่เกี่ยวข้อง (อาจจะนอกเหนือไปMesh) จากนั้นระบบจะใช้การเรนเดอร์เพื่อรับทราบวิธีการสร้างเอนทิตีที่ให้สิ่งเหล่านั้นและนั่นเป็นการเปลี่ยนแปลงที่ง่ายมาก

ในกรณีนี้เอนทิตีที่ประกอบด้วยส่วนประกอบสามารถใช้เป็นส่วนประกอบของเอนทิตีอื่นได้ เราจะสร้างสิ่งต่าง ๆ ขึ้นมาด้วยการเชื่อมต่อบล็อกเลโก้

ECS: ระบบและส่วนประกอบข้อมูลดิบ

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

สิ่งที่ฉันหายไปคือแนวคิดสำคัญหลายประการ:

  1. formalization ของ "ระบบ" เพื่อประมวลผล "ส่วนประกอบ"
  2. "ส่วนประกอบ" เป็นข้อมูลดิบมากกว่าวัตถุพฤติกรรมที่ประกอบเข้าด้วยกันเป็นวัตถุที่ใหญ่กว่า
  3. เอนทิตีเป็นอะไรมากไปกว่า ID ที่เข้มงวดที่เกี่ยวข้องกับคอลเลกชันของส่วนประกอบ

ในที่สุดฉันก็ออกจาก บริษัท นั้นและเริ่มทำงานกับ ECS ในฐานะอินดี้ (ยังคงทำงานอยู่ในขณะที่ระบายเงินออมของฉัน) และมันเป็นระบบที่ง่ายที่สุดในการจัดการโดยไกล

สิ่งที่ฉันสังเกตเห็นด้วยวิธีการของ ECS ก็คือมันช่วยแก้ไขปัญหาที่ฉันยังต้องดิ้นรนกับปัญหาข้างต้น สิ่งสำคัญที่สุดสำหรับฉันคือรู้สึกเหมือนว่าเรากำลังจัดการ "เมือง" ที่มีสุขภาพดีแทนที่จะเป็นหมู่บ้านเล็ก ๆ ที่มีปฏิสัมพันธ์ที่ซับซ้อน มันไม่ยากที่จะรักษาเหมือนเสาหิน "megalopolis" ซึ่งใหญ่เกินกว่าที่ประชากรจะจัดการได้อย่างมีประสิทธิภาพ แต่ก็ไม่วุ่นวายเหมือนโลกที่เต็มไปด้วยหมู่บ้านเล็ก ๆ ที่มีปฏิสัมพันธ์ซึ่งกันและกันซึ่งแค่คิดถึงเส้นทางการค้าใน ระหว่างพวกเขากลายเป็นกราฟฝันร้าย ECS กลั่นความซับซ้อนทั้งหมดที่มีต่อ "ระบบ" ขนาดใหญ่เช่นระบบการแสดงผลซึ่งเป็น "เมือง" ขนาดใหญ่ที่มีสุขภาพดี แต่ไม่ใช่ "megalopolis ที่มีประชากรมากเกินไป"

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

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

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

ข้อดีบางประการ:

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

ข้อเสียบางอย่าง:

  • ฉันยังคงมีเวลาที่ยากลำบากห่อหัวของฉันไปรอบ ๆ มันและมันไม่ใช่กระบวนทัศน์ที่เป็นผู้ใหญ่ที่สุดหรือเป็นที่ยอมรับแม้ในอุตสาหกรรมเกมที่ผู้คนโต้เถียงกันเกี่ยวกับความหมายและวิธีการทำสิ่งต่าง ๆ แน่นอนว่ามันไม่ใช่สิ่งที่ฉันจะทำได้กับทีมเก่าที่ฉันทำงานด้วยซึ่งประกอบด้วยสมาชิกที่ยึดติดกับแนวความคิดแบบ COM หรือแนวความคิด C สไตล์ 1980 ของ codebase ดั้งเดิม ที่ฉันสับสนบางครั้งก็เหมือนกับวิธีการสร้างแบบจำลองความสัมพันธ์ระหว่างองค์ประกอบแบบกราฟ แต่ฉันมักจะพบวิธีแก้ปัญหาที่ไม่น่ากลัวในภายหลังซึ่งฉันสามารถสร้างส่วนประกอบขึ้นอยู่กับอีกองค์ประกอบหนึ่งได้ ("การเคลื่อนไหวนี้ องค์ประกอบขึ้นอยู่กับอีกหนึ่งนี้เป็นผู้ปกครองและระบบจะใช้การบันทึกช่วยจำเพื่อหลีกเลี่ยงการทำซ้ำการคำนวณการเคลื่อนไหวซ้ำซ้ำเช่น ")
  • ABI ยังคงเป็นเรื่องยาก แต่จนถึงตอนนี้ฉันยังกล้าที่จะบอกว่ามันง่ายกว่าวิธีการอินเทอร์เฟซที่บริสุทธิ์ มันเป็นการเปลี่ยนความคิด: ความเสถียรของข้อมูลกลายเป็นจุดสนใจเพียงอย่างเดียวของ ABI แทนที่จะเป็นความเสถียรของอินเทอร์เฟซและในบางวิธีการบรรลุความเสถียรของข้อมูลได้ง่ายกว่าความเสถียรของอินเทอร์เฟซ (เช่นไม่มีการล่อลวง สิ่งนั้นเกิดขึ้นในการใช้งานระบบที่หยาบซึ่งไม่ทำลาย ABI)

ป้อนคำอธิบายรูปภาพที่นี่

อย่างไรก็ตามมันมีเหตุผลที่จะสร้างแอพพลิเคชั่นที่ใช้สถาปัตยกรรม Component-Entity-System ทั่วไปในเอ็นจิ้นเกมหรือไม่?

ดังนั้นต่อไปฉันจะบอกว่า "ใช่" แน่นอนด้วยตัวอย่าง VFX ส่วนตัวของฉันในการเป็นผู้สมัครที่แข็งแกร่ง แต่นั่นก็ยังคงคล้ายกับความต้องการของเกม

ฉันไม่ได้นำไปฝึกในพื้นที่ห่างไกลที่แยกออกจากความกังวลของเอ็นจิ้นเกม (VFX ค่อนข้างคล้ายกัน) แต่ดูเหมือนว่าสำหรับฉันแล้วพื้นที่ส่วนใหญ่เป็นผู้สมัครที่ดีสำหรับแนวทาง ECS อาจจะเป็นระบบ GUI ที่เหมาะสำหรับระบบเดียว แต่ฉันยังคงใช้วิธีการแบบ OOP มากกว่านั้น (แต่ไม่มีการสืบทอดแบบลึกซึ่งต่างจาก Qt เช่น)

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

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

ในกรณีเหล่านั้นความซับซ้อนของ codebase เริ่มรู้สึกเป็นสัดส่วนกับจำนวนของระบบแทนที่จะเป็นจำนวนชุดค่าผสมเนื่องจากแต่ละประเภทตอนนี้เป็นเพียงส่วนประกอบประกอบเอนทิตีซึ่งไม่มีอะไรมากไปกว่าข้อมูลดิบ ระบบ GUI นั้นเหมาะสมกับสเปคเหล่านี้โดยที่มันอาจมีวิดเจ็ตที่เป็นไปได้หลายร้อยชนิดรวมกันจากประเภทฐานหรืออินเตอร์เฟสอื่น ๆ แต่มีเพียงไม่กี่ระบบที่จะประมวลผล (ระบบเลย์เอาต์ระบบการเรนเดอร์ ฯลฯ ) หากระบบ GUI ใช้ ECS อาจเป็นเรื่องง่ายมากที่จะให้เหตุผลเกี่ยวกับความถูกต้องของระบบเมื่อฟังก์ชั่นทั้งหมดจัดทำโดยระบบเหล่านี้จำนวนหนึ่งแทนที่จะเป็นประเภทวัตถุหลายร้อยชนิดที่มีอินเทอร์เฟซที่สืบทอดมาหรือคลาสพื้นฐาน หากระบบ GUI ใช้ ECS วิดเจ็ตจะไม่มีฟังก์ชันการทำงานมีเพียงข้อมูลเท่านั้น มีเพียงไม่กี่ระบบที่ประมวลผลเอนทิตีวิดเจ็ตจะมีฟังก์ชัน วิธีจัดการเหตุการณ์วิดเจ็ตที่จะจัดการได้นั้นเกินกว่าฉัน แต่เพียงแค่อาศัยประสบการณ์ที่ จำกัด ของฉันจนถึงตอนนี้ฉันยังไม่พบกรณีที่ตรรกะชนิดนั้นไม่สามารถถ่ายโอนจากส่วนกลางไปยังระบบที่กำหนดในแบบที่ การเข้าใจถึงปัญหาย้อนหลังให้ผลลัพธ์ที่ยอดเยี่ยมกว่าที่ฉันเคยคาดไว้

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


1) โปรแกรม VFX ตัวอย่างของคุณทำอะไรจากมุมมองของผู้ใช้ 2) โครงการ ECS ที่คุณทำงานอยู่ตอนนี้ ♥ขอบคุณที่เขียนนี่! ♥
ฑิมภ์

1
คำอธิบายที่ละเอียดมาก - ขอบคุณ ฉันรู้สึกว่าฉันได้ข้อสรุปเดียวกันกับที่คุณได้รับเกี่ยวกับการที่ ECS ที่ใช้บังคับอยู่นอกเหนือเกม ในกรณีของฉัน GUI ที่ซับซ้อนโดยเฉพาะ มันรู้สึกแปลก ๆ อย่างมากในตอนแรกที่จะทำเช่นนั้นกับสิ่งที่มักทำ (ลำดับชั้นการสืบทอดที่ล้ำลึกโดยเฉพาะอย่างยิ่งในกรอบ UI) แต่ก็น่าประทับใจเมื่อเห็นผู้อื่นที่กำลังมองหาวิธีนี้มีประสิทธิภาพมากขึ้น
Danny Yaroslavski

1
ขอบคุณสำหรับบทความที่ดี ... สำหรับ GUI ที่ใช้ส่วนประกอบฉันอยากจะแนะนำให้ดู UGUI ของ Unity3d มันยืดหยุ่นและขยายได้อย่างเหลือเชื่อเมื่อเทียบกับ CocoaTouch
Ivan Mir

16

สถาปัตยกรรม Component-Entity-System สำหรับเอ็นจิ้นเกมทำงานสำหรับเกมเนื่องจากลักษณะของซอฟต์แวร์เกมและคุณลักษณะเฉพาะและข้อกำหนดด้านคุณภาพ ตัวอย่างเช่นหน่วยงานให้วิธีการที่อยู่และการทำงานกับสิ่งต่าง ๆ ในเกมซึ่งอาจแตกต่างกันอย่างมากในวัตถุประสงค์และการใช้งานของพวกเขา แต่จะต้องมีการแสดง, การปรับปรุงหรือต่อเนื่อง / deserialized ระบบในเครื่องแบบ โดยการรวมโมเดลส่วนประกอบเข้ากับสถาปัตยกรรมนี้คุณอนุญาตให้พวกเขาเก็บโครงสร้างหลักที่เรียบง่ายในขณะที่เพิ่มคุณสมบัติและฟังก์ชันการทำงานเพิ่มเติมได้ตามต้องการด้วยการเชื่อมต่อรหัสต่ำ มีระบบซอฟต์แวร์ที่แตกต่างกันจำนวนมากซึ่งสามารถได้รับประโยชน์จากคุณสมบัติของการออกแบบนี้เช่นแอปพลิเคชัน CAD, ตัวแปลงสัญญาณ A / V

TL; DR - รูปแบบการออกแบบจะทำงานได้ดีก็ต่อเมื่อโดเมนปัญหานั้นเหมาะสมกับคุณลักษณะและข้อ จำกัด ที่กำหนดไว้ในการออกแบบเท่านั้น


8

หากโดเมนปัญหานั้นเหมาะสมกับมันอย่างแน่นอน

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

แก้ไข: งานของฉันเกี่ยวข้องกับการจัดหาการเชื่อมต่อกับฮาร์ดแวร์ที่เป็นกรรมสิทธิ์ (ใน C #) ขึ้นอยู่กับฮาร์ดแวร์ฟอร์ม - ฟอร์มคืออะไรมีการติดตั้งเฟิร์มแวร์ใดบ้างระดับการให้บริการที่ลูกค้าซื้อ ฯลฯ เราจำเป็นต้องจัดหาฟังก์ชั่นในระดับต่าง ๆ ให้กับอุปกรณ์ แม้แต่คุณสมบัติบางอย่างที่มีอินเตอร์เฟซเดียวกันก็มีการใช้งานที่แตกต่างกันขึ้นอยู่กับรุ่นของอุปกรณ์

รหัสฐานก่อนหน้านี้มีอินเตอร์เฟซที่กว้างมากซึ่งส่วนใหญ่ไม่ได้ใช้งาน บางตัวมีอินเทอร์เฟซแบบบางจำนวนมากซึ่งประกอบขึ้นแบบคงที่ในคลาส beasty หนึ่งคลาส บางอันใช้สตริง -> พจนานุกรมสตริงเพื่อสร้างแบบจำลอง (เรามีหลายแผนกที่ทุกคนคิดว่าสามารถทำได้ดีกว่า)

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

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

สำหรับสถานการณ์เช่นนี้ซึ่งองค์ประกอบของวัตถุและส่วนต่อประสานสามารถรวมส่วนย่อย (หลากหลาย) ของส่วนประกอบทั่วไปได้ดีมาก


1
สมมติว่าคุณได้รับอนุญาตคุณสามารถให้รายละเอียดเพิ่มเติมเกี่ยวกับงานปัจจุบันของคุณได้หรือไม่? ฉันอยากรู้ว่า CES มีความงดงามในสิ่งที่คุณกำลังสร้างอย่างไร
Andrew De Andrade

มีบทความบทความหรือบล็อกเกี่ยวกับประสบการณ์ของคุณบ้างไหม? นอกจากนี้ฉันต้องการมีรายละเอียดทางเทคนิคเพิ่มเติมเกี่ยวกับเรื่องนี้ :)
user1778770

@ user1778770 - ไม่เปิดเผยต่อสาธารณะไม่ คุณมีคำถามประเภทใด
Telastyn

ทีนี้มาเริ่มด้วยอะไรง่ายๆแนวคิดของคุณครอบคลุมสแต็กแอปพลิเคชั่นทั้งหมด (เช่นจากธุรกิจไปจนถึงส่วนหน้า) หรือไม่? หรือเพียงชั้นเดียวของเคสที่ใช้ครั้งเดียว?
user1778770

@ user1778770 - ในการติดตั้งของฉันมีเอนทิตี / ส่วนประกอบอยู่ในหนึ่งเลเยอร์ เอนทิตีที่แตกต่างกันอาจมีอยู่ในเลเยอร์ที่แตกต่างกัน แต่มักจะไม่ใช่ 1: 1 (หรือเลเยอร์อื่นไม่ให้ประโยชน์)
Telastyn
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.