วิธีที่ดีที่สุดในการจัดโครงสร้าง / จัดการตัวละคร 'ในเกม' หลายร้อยตัว


10

ฉันสร้างเกม RTS ง่ายๆซึ่งมีตัวละครนับร้อยเช่น Crusader Kings 2 ใน Unity สำหรับการจัดเก็บตัวเลือกที่ง่ายที่สุดคือการใช้วัตถุที่เขียนได้ แต่นั่นไม่ใช่ทางออกที่ดีเพราะคุณไม่สามารถสร้างวัตถุใหม่ได้ในขณะทำงาน

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

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


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


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

1
ตัวอย่างเช่นเมื่อคุณพูดถึง "1000s ของตัวละคร" ผู้คนมีความคิดของ 1000s ของแบบจำลอง 3 มิติหรือสไปรต์บนหน้าจอในเวลาเดียวกัน - ดังนั้นในเอกภาพ 1000s GameObjectsของ ใน CK2 จำนวนตัวละครสูงสุดที่ฉันเห็นในเวลาเดียวกันคือตอนที่ฉันดูศาลของฉันและเห็นผู้คน 10-15 คนที่นั่น (ฉันไม่ได้เล่นมากนัก) เช่นกันกองทัพที่มีทหาร 3000 นายเป็นเพียงคนเดียวที่GameObjectแสดงหมายเลข "3000"
Raphael Schmitz

1
@ R.Schmitz ใช่ฉันควรทำให้ส่วนนั้นชัดเจนตัวละครทุกตัวไม่มี gameobject แนบกับพวกเขา เมื่อใดก็ตามที่จำเป็นเช่นการย้ายตัวละครจากจุดหนึ่งไปยังอีกจุดหนึ่ง เอนทิตีแยกต่างหากจะถูกสร้างขึ้นซึ่งมีข้อมูลทั้งหมดของตัวละครที่มีลอจิกไอ
paul p

คำตอบ:


24

มีสามสิ่งที่คุณควรพิจารณา:

  1. มันไม่จริงทำให้เกิดปัญหาประสิทธิภาพการทำงาน? 1000s นั้นก็จริงไม่มาก คอมพิวเตอร์สมัยใหม่นั้นเร็วมากและสามารถจัดการกับสิ่งต่างๆมากมาย ตรวจสอบว่าการประมวลผลอักขระใช้เวลานานเท่าใดและดูว่าจริง ๆ แล้วมันจะทำให้เกิดปัญหาก่อนที่จะกังวลมากเกินไปเกี่ยวกับมัน

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

  3. พิจารณาการออกแบบเชิงข้อมูล แทนที่จะมีวัตถุ 1,000 ตัวและเรียกใช้ฟังก์ชั่นเดียวกันสำหรับแต่ละรายการให้มีอาร์เรย์ของข้อมูลสำหรับ 1,000 ตัวอักษรและมีหนึ่งฟังก์ชันวนรอบมากกว่า 1,000 ตัวเพื่ออัพเดตแต่ละครั้ง การเพิ่มประสิทธิภาพประเภทนี้สามารถปรับปรุงประสิทธิภาพได้อย่างมาก


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

1
ด้วยการลดจำนวนตัวอักษรอัปเดตที่ได้รับนอกหน้าจอคุณสามารถเพิ่มเวลาในการประมวลผลได้อย่างมาก คุณหมายถึงการลดลงไหม
Tejas Kale

1
@TejasKale: ใช่ถูกแก้ไข
Jack Aidley

2
หนึ่งพันตัวละครไม่มากนัก แต่เมื่อแต่ละคนต่างก็ตรวจสอบอย่างต่อเนื่องเพื่อดูว่าพวกเขาสามารถตัดต่อตัวละครอื่น ๆได้หรือไม่มันเริ่มมีผลกระทบอย่างมากต่อประสิทธิภาพโดยรวม ...
อยากรู้อยากเห็น

1
ดีที่สุดเสมอที่จะตรวจสอบจริง ๆ แต่โดยทั่วไปมันเป็นข้อสันนิษฐานการทำงานที่ปลอดภัยที่ชาวโรมันจะต้องการที่จะตอนซึ่งกันและกัน;)
อยากรู้อยากเห็น dannii

11

ในสถานการณ์นี้ฉันขอแนะนำให้ใช้องค์ประกอบ :

หลักการที่คลาสควรใช้เพื่อให้เกิดพฤติกรรม polymorphic และการนำโค้ดกลับมาใช้ใหม่โดยการจัดองค์ประกอบ (โดยมีอินสแตนซ์ของคลาสอื่นที่ใช้ฟังก์ชันที่ต้องการ)


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

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


การแก้ปัญหาคือการแบ่งส่วนต่าง ๆ ของคุณCharacterออกเป็นคลาสย่อยซึ่งCharacterเป็นเจ้าของตัวอย่าง ตัวอย่างเช่น:

  • CharacterInfo อาจเป็นโครงสร้างข้อมูลอย่างง่ายที่มีชื่อวันเดือนปีเกิดวันตายและฝ่าย

  • Equipmentอาจมีรายการทั้งหมดที่ตัวละครของคุณมีหรือสินทรัพย์หมุนเวียน มันอาจมีตรรกะที่จัดการสิ่งเหล่านี้ในฟังก์ชั่น

  • CharacterAIหรือCharacterControllerอาจมีข้อมูลทั้งหมดที่จำเป็นเกี่ยวกับเป้าหมายปัจจุบันของตัวละครฟังก์ชั่นยูทิลิตี้ของพวกเขา ฯลฯ และมันอาจมีตรรกะการอัพเดทจริงที่ประสานการตัดสินใจ / การมีปฏิสัมพันธ์ระหว่างแต่ละส่วน

เมื่อคุณแยกตัวละครแล้วคุณไม่จำเป็นต้องตรวจสอบสถานะ Alive / Dead ในการวนซ้ำการอัพเดตอีกต่อไป

แต่คุณก็จะทำให้การAliveCharacterObjectที่มีCharacterController, CharacterEquipmentและCharacterInfoสคริปต์ที่แนบมา ในการ "ฆ่า" ตัวละครคุณเพียงถอดชิ้นส่วนที่ไม่เกี่ยวข้องอีกต่อไป (เช่นCharacterController) - ตอนนี้มันจะไม่เสียหน่วยความจำหรือเวลาในการประมวลผล

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


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


8

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

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

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

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

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

โดยวิธีการที่ฉันชอบ CKII และวิธีการเลียนแบบโลกที่มีตัวละคร AI ควบคุมที่ไม่ซ้ำกันหลายพันดังนั้นฉันรอคอยที่จะเล่นของคุณในประเภท


สวัสดีขอขอบคุณสำหรับการตอบกลับ การคำนวณทั้งหมดทำโดย GameObject Manager เดียว ฉันกำหนดวัตถุของเกมให้กับนักแสดงบุคคลเฉพาะเมื่อจำเป็นเท่านั้น (เช่นการแสดง Army of Character ย้ายจากตำแหน่งหนึ่งไปยังตำแหน่งอื่น)
paul p

1
Like "all living characters in a specific location" or "all living or dead ancestors of a specific character". It might be beneficial to create some more secondary data-structures optimized for these kinds of queries.จากประสบการณ์ของฉันกับการดัดแปลง CK2 นี่ใกล้เคียงกับวิธีที่ CK2 จัดการกับข้อมูล CK2 ดูเหมือนว่าจะใช้ดัชนีที่เป็นดัชนีฐานข้อมูลพื้นฐานซึ่งทำให้การค้นหาตัวอักษรสำหรับสถานการณ์เฉพาะได้เร็วขึ้น แทนที่จะมีรายชื่อตัวละครดูเหมือนว่าจะมีฐานข้อมูลภายในของตัวละครพร้อมกับข้อเสียและผลประโยชน์ทั้งหมดที่เกี่ยวข้อง
Morfildur

1

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

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


มันเป็น RTS เราควรสมมติว่าในเวลาใดก็ตามมีหน่วยจำนวนมากอยู่บนหน้าจอจริง
Tom

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

1

ชี้แจงคำถาม

ฉันสร้างเกม RTS ง่ายๆซึ่งมีตัวละครนับร้อยเช่น Crusader Kings 2 ใน Unity

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

Characterคลาสที่ไม่มีฟังก์ชันการทำงาน

ดังนั้นฉันจึงสร้างคลาส C # ที่เรียกว่า "ตัวละคร" ซึ่งมีข้อมูลทั้งหมด

ดีเพราะตัวละครในเกมของคุณเป็นเพียงข้อมูล สิ่งที่คุณเห็นบนหน้าจอเป็นเพียงการแสดงข้อมูลนั้น Characterคลาสเหล่านี้เป็นหัวใจสำคัญของเกมและกำลังตกอยู่ในอันตรายจากการเป็น " เทพเจ้าวัตถุ " ดังนั้นฉันจะแนะนำมาตรการที่รุนแรงกับที่: ลบฟังก์ชั่นทั้งหมดจากชั้นเรียนเหล่านั้น วิธีการGetFullName()ที่รวมชื่อและนามสกุลเป็น OK แต่ไม่มีโค้ดที่ "ทำอะไรบางอย่าง" ใส่รหัสนั้นลงในคลาสเฉพาะที่ทำสิ่งเดียว เช่นคลาสที่BirtherมีเมธอดCharacter CreateCharacter(Character father, Character mother)จะดูสะอาดกว่าการใช้ฟังก์ชั่นนั้นในCharacterคลาส

อย่าเก็บข้อมูลไว้ในรหัส

สำหรับการจัดเก็บตัวเลือกที่ง่ายที่สุดคือการใช้วัตถุที่เขียนได้

ไม่เก็บไว้ในรูปแบบ JSON โดยใช้ JsonUtility ของ Unity ด้วยCharacterคลาสที่ไม่มีฟังก์ชั่นเหล่านั้นควรทำเรื่องเล็กน้อย ที่จะทำงานสำหรับการตั้งค่าเริ่มต้นของเกมเช่นเดียวกับการเก็บไว้ใน savegames อย่างไรก็ตามมันเป็นเรื่องน่าเบื่อที่ต้องทำดังนั้นฉันจึงให้ทางเลือกที่ง่ายที่สุดในสถานการณ์ของคุณ คุณสามารถใช้ XML หรือ YAML หรือรูปแบบใดก็ได้ตราบใดที่มนุษย์ยังสามารถอ่านได้เมื่อมันถูกเก็บไว้ในไฟล์ข้อความ CK2 ทำเช่นเดียวกันจริง ๆ แล้วเกมส่วนใหญ่ทำ นอกจากนี้ยังมีการตั้งค่าที่ยอดเยี่ยมสำหรับการอนุญาตให้ผู้อื่นดัดแปลงเกมของคุณ

คิดว่าเป็นนามธรรม

ฉันได้เพิ่มการตรวจสอบง่าย ๆ เพื่อให้แน่ใจว่าตัวละครนั้น "มีชีวิตอยู่" ในขณะที่กำลังประมวลผล [... ] แต่ฉันไม่สามารถลบ "ตัวละคร" ออกถ้าเขาตายเพราะฉันต้องการข้อมูลของเขาในขณะที่สร้างแผนภูมิต้นไม้

คนนี้พูดง่ายกว่าทำเพราะมักจะชนกับวิธีคิดตามธรรมชาติ คุณกำลังคิดอย่าง "เป็นธรรมชาติ" ของ "ตัวละคร" แต่ในแง่ของเกมของคุณดูเหมือนว่ามีอย่างน้อย 2 ชนิดที่แตกต่างกันของข้อมูลที่ "เป็นตัวละคร": ฉันจะเรียกมันและActingCharacter FamilyTreeEntryเป็นตัวละครที่ตายแล้วก็ไม่จำเป็นต้องได้รับการปรับปรุงและอาจจะต้องการน้อยมากทั้งข้อมูลที่ใช้งานมากกว่าFamilyTreeEntryActingCharacter


0

ฉันจะพูดจากประสบการณ์เพียงเล็กน้อยตั้งแต่การออกแบบ OO แบบแข็งไปจนถึงการออกแบบ Entity-Component-System (ECS)

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

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

  1. Entity : นี่คือสิ่งที่ผู้เล่นสัตว์ NPC, สิ่งที่ มันเป็นสิ่งที่ต้องการส่วนประกอบที่แนบมากับมัน
  2. ส่วนประกอบ : นี่คือคุณสมบัติหรือคุณสมบัติเช่น "ชื่อ" หรือ "อายุ" หรือ "ผู้ปกครอง" ในกรณีของคุณ
  3. ระบบนี้เป็นตรรกะที่อยู่เบื้องหลังส่วนประกอบหรือพฤติกรรม โดยทั่วไปคุณสร้างหนึ่งระบบต่อองค์ประกอบ แต่ไม่สามารถทำได้เสมอไป นอกจากนี้บางครั้งระบบจำเป็นต้องมีอิทธิพลต่อระบบอื่น ๆ

ดังนั้นที่นี่ฉันจะไปกับสิ่งนี้:

ก่อนอื่นสร้างIDสำหรับตัวละครของคุณ int, Guidสิ่งที่คุณชอบ นี่คือ "เอนทิตี"

ประการที่สองเริ่มคิดเกี่ยวกับพฤติกรรมที่แตกต่างที่คุณเกิดขึ้น สิ่งต่างๆเช่น "Family Tree" - นั่นเป็นพฤติกรรม แทนการสร้างแบบจำลองที่เป็นคุณลักษณะในกิจการสร้างระบบที่ถือได้ว่าข้อมูลทั้งหมด ระบบสามารถตัดสินใจว่าจะทำอย่างไรกับมัน

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

คุณจะสร้างระบบ "Sprite" หรือ "Drawing" หรือ "Rendering" ระบบนี้จะมีความรับผิดชอบในการกำหนดสิ่งที่ตัวละครต้องแสดงด้วยและวิธีการแสดง จากนั้นเมื่อตัวละครตายให้ลบออก

นอกจากนี้ระบบ "AI" ที่สามารถบอกตัวละครว่าจะทำอย่างไรจะไปที่ไหน ฯลฯ สิ่งนี้ควรมีปฏิสัมพันธ์กับระบบอื่น ๆ อีกมากมายและการตัดสินใจขึ้นอยู่กับพวกเขา อีกครั้งตัวละครที่ตายแล้วอาจถูกลบออกจากระบบนี้เนื่องจากพวกเขาไม่ได้ทำอะไรอีกแล้ว

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

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

นอกจากนี้ยังช่วยให้คุณใช้ประโยชน์จากความคิดสร้างสรรค์มากขึ้น: คุณสามารถสร้างระบบ "Pathfinder" ที่สามารถจัดการการคำนวณเส้นทางจาก A-to-B และสามารถอัปเดตตามความจำเป็นช่วยให้ระบบการเคลื่อนไหวพูดว่า "ที่ไหนที่ฉันต้องการ ไปต่อไปเหรอ? ขณะนี้เราสามารถแยกข้อกังวลเหล่านี้ออกได้อย่างสมบูรณ์และเหตุผลเกี่ยวกับสิ่งเหล่านี้ได้อย่างมีประสิทธิภาพมากขึ้น การเคลื่อนไหวไม่จำเป็นต้องค้นหาเส้นทางมันแค่ต้องการพาคุณไปที่นั่น

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

แต่และฉันไม่สามารถเครียดได้พอตอนนี้Entityก็เป็นเพียงแค่IDรวมถึงไทล์วัตถุ ฯลฯ หากเอนทิตีไม่ได้เป็นของระบบจากนั้นระบบจะไม่ติดตาม ซึ่งหมายความว่าเราสามารถสร้างวัตถุ "ต้นไม้" ของเราเก็บไว้ในSpriteและMovementระบบ (ต้นไม้จะไม่ย้าย แต่มีองค์ประกอบ "ตำแหน่ง") และทำให้พวกเขาออกจากระบบอื่น ๆ เราไม่ต้องการรายการพิเศษสำหรับต้นไม้อีกต่อไปเนื่องจากการแสดงต้นไม้ไม่แตกต่างจากตัวละครนอกเหนือจากกระดาษ (ซึ่งSpriteระบบสามารถควบคุมได้หรือPaperdollระบบสามารถควบคุมได้) ตอนนี้เราNextPositionสามารถเขียนใหม่ได้เล็กน้อย: Vector2? NextPosition(int entity)และสามารถส่งคืนnullตำแหน่งสำหรับเอนทิตีที่ไม่สนใจ นอกจากนี้เรายังใช้สิ่งนี้กับเราNameSystem.GetName(int entity)มันจะส่งคืนnullต้นไม้และหิน


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


สวัสดีขอขอบคุณสำหรับการตอบกลับอย่างละเอียด ฉันใช้ One GameObject Manager ซึ่งมีการอ้างอิงถึงตัวละครในเกมอื่น ๆ ทั้งหมดเท่านั้น
paul p

การพัฒนาใน Unity หมุนรอบเอนทิตีที่เรียกGameObjectว่าไม่มาก แต่มีรายการของComponentคลาสที่ทำงานจริง มีการเปลี่ยนกระบวนทัศน์เกี่ยวกับวงเวียน ECS ทศวรรษที่ผ่านมาเนื่องจากการวางรหัสการแสดงในคลาสระบบแยกต่างหากนั้นสะอาดกว่า เมื่อเร็ว ๆ นี้ Unity ได้ติดตั้งระบบดังกล่าวด้วยเช่นกัน แต่GameObjectระบบของพวกเขาคือ ECS OP ที่มีอยู่แล้วโดยใช้ ECS
Raphael Schmitz

-1

เมื่อคุณทำสิ่งนี้ใน Unity วิธีที่ง่ายที่สุดคือ:

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

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

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

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