แนวคิดแบบ ECS
เอนทิตี คอมโพเนนต์ และระบบ
แนวคิดแบบ ECS เป็นบทเรียน Learn Rust Coding ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Learn Rust Coding และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Learn Rust Coding มีบทเรียนทั้งหมด 4 บทเรียน
สิ่งที่ ECS แก้ปัญหา
Bevy สร้างขึ้นบนรูปแบบ Entity Component System (ECS) แทนที่จะใช้ลำดับชั้นการสืบทอดที่ซับซ้อน คุณประกอบพฤติกรรมจากส่วนข้อมูลขนาดเล็กที่เป็นอิสระต่อกัน
การออกแบบที่เน้นข้อมูลนี้ทำให้การจัดวางหน่วยความจำเหมาะกับแคช และเปิดให้เอนจินแบ่งงานทำงานขนานกันบนแกน CPU ได้แทบโดยไม่มีต้นทุนเพิ่ม
เอนทิตีเป็นเพียง ID
เอนทิตีไม่มีอะไรมากไปกว่าตัวระบุขนาดเล็ก — ดัชนีที่มีรุ่นกำกับ เอนทิตีไม่ครอบครองข้อมูลและไม่มีพฤติกรรมของตัวเอง
ลองนึกภาพว่าเป็นคีย์ในแถวฐานข้อมูล คอมโพเนนต์ที่แนบกับคีย์นั้นจะให้ความหมายแก่เอนทิตี เช่น "Player" หรือ "Bullet"
// An Entity is a tiny handle
struct Entity {
index: u32,
generation: u32,
}คอมโพเนนต์คือข้อมูลล้วน
คอมโพเนนต์คือโครงสร้าง Rust ธรรมดาที่อนุพันธ์ Component โดยเก็บสถานะไว้แต่ไม่มีตรรกะ
ควรทำให้แต่ละคอมโพเนนต์มีขนาดเล็กและมุ่งเน้นหน้าที่เดียว ตำแหน่ง ความเร็ว และค่าพลังชีวิตควรเป็นคอมโพเนนต์สามตัวแยกกัน แทนที่จะรวมเป็นโครงสร้างขนาดใหญ่เพียงตัวเดียว
use bevy::prelude::*;
#[derive(Component)]
struct Position { x: f32, y: f32 }
#[derive(Component)]
struct Velocity { x: f32, y: f32 }ระบบเก็บตรรกะ
ระบบคือฟังก์ชันธรรมดาที่ทำงานกับคอมโพเนนต์ ตรรกะเกมทั้งหมดของคุณจะอยู่ที่นี่
Bevy จะตรวจสอบพารามิเตอร์ของแต่ละระบบเพื่อดูว่าระบบเข้าถึงข้อมูลใด จากนั้นจัดตารางให้ระบบที่ไม่ขัดแย้งกันทำงานแบบขนาน
fn move_system(mut query: Query<(&mut Position, &Velocity)>) {
for (mut pos, vel) in &mut query {
pos.x += vel.x;
pos.y += vel.y;
}
}คิวรี: การขอข้อมูล
Query ใช้ระบุคำขอเอนทิตีที่มีชุดคอมโพเนนต์เฉพาะอย่างประกาศไว้ Bevy จะคืนเฉพาะเอนทิตีที่ตรงเงื่อนไข
คุณขอการเข้าถึงร่วมกันได้ด้วย &T หรือการเข้าถึงแบบเฉพาะด้วย &mut T ข้อมูลการยืมนี้เป็นตัวขับเคลื่อนตัวจัดตารางแบบขนาน
// Entities with BOTH Position and Velocity
fn report(query: Query<(&Position, &Velocity)>) {
for (pos, vel) in &query {
info!("at {},{} moving {},{}", pos.x, pos.y, vel.x, vel.y);
}
}การกรองคิวรี
พารามิเตอร์ชนิดที่สองของ Query คือตัวกรอง ใช้ With และ Without เพื่อจำกัดผลลัพธ์โดยไม่ยืมข้อมูลของคอมโพเนนต์นั้น
วิธีนี้เหมาะอย่างยิ่งกับคอมโพเนนต์แท็ก ซึ่งเป็นโครงสร้างว่างที่ใช้ระบุบทบาทของเอนทิตี
#[derive(Component)]
struct Player;
fn player_only(query: Query<&Position, With<Player>>) {
for pos in &query {
info!("player at {},{}", pos.x, pos.y);
}
}ทรัพยากร: สถานะส่วนกลาง
ข้อมูลบางอย่างมีเพียงชุดเดียวสำหรับทั้งเกม เช่น คะแนน เวลาที่ผ่านไป หรือการตั้งค่าเกม ข้อมูลเหล่านี้จะอยู่ในรูปทรัพยากรแทนคอมโพเนนต์
เข้าถึงทรัพยากรในระบบด้วย Res<T> สำหรับการอ่าน หรือ ResMut<T> สำหรับการเขียน
#[derive(Resource)]
struct Score(u32);
fn show_score(score: Res<Score>) {
info!("Score: {}", score.0);
}ตัวสร้างแอป
ทุกอย่างเชื่อมต่อกันภายใน App คุณเพิ่มปลั๊กอิน แทรกทรัพยากร และลงทะเบียนระบบเข้ากับกำหนดการ
DefaultPlugins จัดเตรียมระบบหน้าต่าง การเรนเดอร์ อินพุต และเวลาไว้ให้ คุณจึงมุ่งเน้นกับการเล่นเกมได้
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.insert_resource(Score(0))
.add_systems(Update, show_score)
.run();
}กำหนดการ: Startup กับ Update
ระบบทำงานอยู่ภายในกำหนดการ Startup ทำงานครั้งเดียวเมื่อแอปเริ่มต้น เหมาะสำหรับสร้างโลก
Update ทำงานทุกเฟรม และเป็นที่สำหรับการเคลื่อนที่ อินพุต และตรรกะต่าง ๆ Bevy ยังมี FixedUpdate สำหรับขั้นตอนฟิสิกส์ที่ให้ผลแน่นอน
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.add_systems(Update, move_system)
.run();เหตุใดการประกอบจึงชนะ
ต้องการศัตรูบินได้ที่ติดพิษใช่ไหม เพียงแนบคอมโพเนนต์ Flying และ Poisoned ไม่ต้องสร้างคลาสใหม่หรือสายการสืบทอด
พฤติกรรมเกิดขึ้นจากการที่ระบบต่าง ๆ ตรงกับชุดคอมโพเนนต์ใดบ้าง วิธีนี้ทำให้เพิ่มฟีเจอร์ได้ง่ายและปรับโครงสร้างได้โดยมีต้นทุนต่ำ
// Same systems, new combinations
commands.spawn((Position{x:0.0,y:0.0}, Velocity{x:1.0,y:0.0}, Flying, Poisoned));การทำงานขนานโดยไม่ต้องเสียค่าใช้จ่ายเพิ่ม
เนื่องจากแต่ละระบบประกาศการเข้าถึงข้อมูลของตน ตัวจัดตารางของ Bevy จึงทราบว่าระบบใดขัดแย้งกัน ระบบที่ไม่ขัดแย้งจะทำงานบนเธรดต่างกันโดยอัตโนมัติ
คุณเขียนโค้ดที่ดูเหมือนทำงานในเธรดเดียว แล้วเอนจินจะดึงการทำงานขนานจากประกาศการยืมของคุณ ไม่ต้องใช้ล็อกหรือจัดการเธรดเอง
ตรวจสอบความเข้าใจ
ทดสอบความเข้าใจของคุณเกี่ยวกับบทบาทของ ECS
สรุป: แนวคิด ECS
เอนทิตีคือ ID คอมโพเนนต์คือข้อมูล ระบบคือตรรกะ และทรัพยากรคือสถานะส่วนกลาง App เชื่อมโยงทั้งหมดเข้าด้วยกันผ่านกำหนดการ
เมื่อประกอบคอมโพเนนต์ขนาดเล็กและปล่อยให้ระบบค้นหาคอมโพเนนต์ที่ตรงกัน คุณจะได้เกมที่ยืดหยุ่น ทำงานขนาน และใช้แคชได้ดี ต่อไปเราจะสร้างเอนทิตีและทำให้เอนทิตีเคลื่อนที่
คำถามที่พบบ่อย
บทเรียน “แนวคิดแบบ ECS” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “แนวคิดแบบ ECS” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Learn Rust Coding ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Learn Rust Coding มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “แนวคิดแบบ ECS”
เอนทิตี คอมโพเนนต์ และระบบ คุณปฏิบัติ Learn Rust Coding ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Learn Rust Coding หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Learn Rust Coding บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน
บทเรียน “แนวคิดแบบ ECS” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Learn Rust Coding นี้ได้ไหม
ได้ บทเรียน Learn Rust Coding ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ