โครงการอ้างอิงพืช

*เนื้อหานี้แปลโดยใช้ AI (เวอร์ชัน Beta) และอาจมีข้อผิดพลาด หากต้องการดูหน้านี้เป็นภาษาอังกฤษ ให้คลิกที่นี่

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

Plant project banner

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

รับไฟล์

  1. นําทางไปยังหน้าประสบการณ์ โรงงาน
  2. คลิกปุ่ม และ แก้ไขใน Studio

ใช้กรณี

พืช ครอบคลุมกรณีการใช้งานต่อไปนี้:

  • การอยู่รอดของข้อมูลเซสชันและข้อมูลผู้เล่น
  • การจัดการมุมมอง UI
  • เครือข่ายไคลเอนต์-เซิร์ฟเวอร์
  • ประสบการณ์ผู้ใช้ครั้งแรก (FTUE)
  • การซื้อเงินแข็งและเงินอ่อน

นอกจากนี้โครงการนี้แก้ปัญหาชุดที่แคบกว่าที่สามารถใช้กับประสบการณ์จํานวนมากรวมถึง:

  • การปรับแต่งพื้นที่ในสถานที่ที่เกี่ยวข้องกับผู้เล่น
  • การจัดการความเร็วในการเคลื่อนที่ของตัวละครผู้เล่น
  • สร้างวัตถุที่ติดตามตัวอักษรไปรอบๆ
  • ตรวจสอบว่าตัวละครอยู่ในส่วนใดของโลก

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

โครงสร้างโครงการ

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

โมเดลข้อมูล

ตารางต่อไปนี้อธิบายถึงบริการคอนเทนเนอร์ในตัวอย่างของโมเดลข้อมูลที่อยู่ใน

บริการประเภทของตัวอย่าง
Workspace

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

นอกจากนี้ยังมีรูปแบบฟาร์มว่างเปล่า Folder ซึ่งจะถูกเพิ่มในระหว่างการทำงานของผู้เล่น

Lighting

เอฟเฟกต์บรรยากาศและแสง

ReplicatedFirst

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

  • ในโฟลเดอร์ ตัวอย่าง มีหน้าจอโหลด GUI:
  • ในโฟลเดอร์ ที่เก็บแหล่ง มีรหัสหน้าจอการโหลดและรหัสที่จำเป็นในการรอให้ส่วนที่เหลือของเกมโหลดThe start``Class.LocalScript เป็นจุดเข้าสำหรับโค้ดด้านลูกค้าทั้งหมดในโครงการ
ReplicatedStorage

ให้บริการเป็นภาชนะเก็บข้อมูลสำหรับทุกตัวอย่างที่ต้องการการเข้าถึงทั้งในไคลเอนต์และเซิร์ฟเวอร์:

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

มี Script ให้บริการเป็นจุดเข้าสำหรับโค้ดด้านเซิร์ฟเวอร์ทั้งหมดในโครงการ

ServerStorage

ให้บริการเป็นภาชนะเก็บข้อมูลสำหรับทุกตัวอย่างที่ไม่จำเป็นต้องส่งไปยังไคลเอนต์:

  • ในโฟลเดอร์ ตัวอย่าง มีรูปแบบ ฟาร์ม สำเนาของสิ่งนี้จะถูกวางใน Workspace เมื่อผู้เล่นเข้าร่วมเกมที่จะถูกเลียนแบบไปยังผู้เล่นทั้งหมด:
  • ในโฟลเดอร์ ที่เก็บทรัพยากร มีโค้ดทั้งหมดที่เป็นเอกลักษณ์สำหรับเซิร์ฟเวอร์
SoundService

มีวัตถุ Sound ที่ใช้สําหรับเอฟเฟกต์เสียงในเกมภายใต้ SoundService วัตถุเหล่านี้ Sound ไม่มีตำแหน่งและไม่ถูกจำลองในพื้นที่ 3D

จุดเข้า

โครงการส่วนใหญ่จัดระเบียบโค้ดภายในรียูสาเบิล ModuleScripts เป็นเจ้าของ สามารถใช้ซ้ำได้ แต่ไม่ได้ดำเนินการเอง; พวกเขาต้องถูกนำเข้าโดย Script หรือ LocalScriptโครงการ Roblox จำนวนมากจะมีจํานวนมากของ Script และ LocalScript วัตถุ ซึ่งแต่ละอย่างเกี่ยวข้องกับพฤติกรรมหรือระบบเฉพาะในเกม สร้างจุดเข้าหลายจุด

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

รายการต่อไปนี้อธิบายถึงข้อแลกเปลี่ยนของทั้งสองวิธี:

  • เดียว Script และเดียว LocalScript ครอบคลุมรหัสเซิร์ฟเวอร์และไคลเอนต์ตามลําดับ
  • ควบคุมได้มากขึ้นเกี่ยวกับลำดับที่ระบบต่างๆ เริ่มต้นได้เพราะโค้ดทั้งหมดจะถูกเริ่มต้นจากสคริปต์เดียว
  • สามารถส่งวัตถุโดยอ้างอิงระหว่างระบบได้

สถาปัตยกรรมระดับสูงของระบบ

ระบบระดับสูงในโครงการมีรายละเอียดด้านล่างระบบบางระบบมีความซับซ้อนมากกว่าระบบอื่น ๆ Classๆ

Plant project systems architecture diagram

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

เซิร์ฟเวอร์

ระบบต่อไปนี้เกี่ยวข้องกับเซิร์ฟเวอร์

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

กำหนดโมเดลตัวละครผู้เล่นให้กับกลุ่มการชนกัน .:

  • กำหนดกลุ่มการชนกันเพื่อให้ตัวละครผู้เล่นไม่สามารถชนกับเกวียนพืชได้
เซิร์ฟเวอร์จัดการฟาร์ม
  • สร้างโมเดลฟาร์มของผู้เล่นใหม่จากข้อมูลผู้เล่นเมื่อพวกเขาเข้าร่วมเกม:
  • ลบโมเดลฟาร์มเมื่อผู้เล่นออก:
  • อัปเดตข้อมูลผู้เล่นเมื่อฟาร์มของผู้เล่นเปลี่ยนแปลง:
  • เปิดเผยวิธีการเข้าถึงคลาส ฟาร์ม ที่เกี่ยวข้องกับผู้เล่นที่กำหนด
คอนเทนเนอร์วัตถุผู้เล่น
  • สร้างวัตถุต่างๆ ที่เกี่ยวข้องกับอายุการใช้งานของผู้เล่นและให้วิธีการดึงข้อมูลเหล่านี้ออกมา
ผู้เล่นแท็ก
  • เพิ่มแท็ก CollectionService ให้กับวัตถุผู้เล่นและตัวละครทั้งหมด
เซิร์ฟเวอร์ FtueManager
  • ในระหว่าง FTUE ดำเนินการแต่ละขั้นตอนและรอให้สำเร็จ
ตัวสร้างตัวละคร
  • ฟื้นฟูตัวละครเมื่อพวกเขาตายโปรดทราบว่า Players.CharacterAutoLoads ถูกปิดใช้งานเพื่อหยุดการสร้างจนกว่าข้อมูลของผู้เล่นจะโหลดเสร็จแล้ว

ไคลเอนต์

ระบบต่อไปนี้เกี่ยวข้องกับไคลเอนต์

ระบบคําอธิบาย
เครือข่าย
  • รอให้เซิร์ฟเวอร์สร้างทุก RemoteEvent และ RemoteFunction ตัวอย่าง:
  • เปิดเผยวิธีการส่งและรับข้อความไปยังและจากเซิร์ฟเวอร์:
  • บังคับการตรวจสอบประเภทพารามิเตอร์ระหว่างการทำงาน:
  • ทำงาน pcall() บนฟังก์ชันระยะไกล
ผู้เล่นข้อมูลลูกค้า
  • เก็บข้อมูลผู้เล่นท้องถิ่นในหน่วยความจํา:
  • เปิดเผยวิธีการและสัญญาณสำหรับการค้นหาและสมัครรับการเปลี่ยนแปลงในข้อมูลผู้เล่น
ลูกค้าตลาด
  • เปิดเผยวิธีการขอให้เซิร์ฟเวอร์ซื้อสินค้าสําหรับสกุลเงินนุ่ม
ผู้จัดการกระโดด LocalWalk
  • เปิดเผยวิธีการที่จะปรับเปลี่ยนวิธีการ WalkSpeed หรือ JumpHeight ของตัวละครผ่านตัวคูณเพื่อหลีกเลี่ยงความขัดแย้งเมื่อปรับเปลี่ยนค่าเหล่านี้จากหลายสถานที่
ไคลเอนต์ผู้จัดการฟาร์ม
  • ฟังสำหรับแท็กเฉพาะ CollectionService ที่ถูกใช้กับตัวอย่างและสร้าง "ส่วนประกอบ" ที่เพิ่มพฤติกรรมการเพิ่มแก่ตัวอย่างเหล่านี้ส่วน "ส่วนประกอบ" หมายถึงคลาสที่สร้างเมื่อแท็ก CollectionService ถูกเพิ่มลงในตัวอย่างและถูกทําลายเมื่อถูกลบ; ใช้สําหรับคําแนะนํา CTA ในฟาร์มและคลาสต่างๆ ที่ส่งสถานะฟาร์มไปยังผู้เล่น
การตั้งค่า UI
  • เริ่มต้นชั้น UI ทั้งหมด:
  • กำหนดให้ชั้นบางอย่างมองเห็นได้เฉพาะในส่วนทางกายภาพของโลกเกมเท่านั้น:
  • เชื่อมต่อเอฟเฟกต์กล้องพิเศษสำหรับเมื่อเปิดใช้งานเมนู
ไคลเอนต์ FtueManager
  • กำหนดขั้นตอน FTUE บนไคลเอนต์
การวิ่งตัวละคร
  • ใช้ LocalWalkJumpManager เพื่อเพิ่ม WalkSpeed เมื่อตัวละครผู้เล่นอยู่นอกฟาร์มของพวกเขา

การสื่อสารระหว่างไคลเอนต์-เซิร์ฟเวอร์

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

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

  • การเลียนแบบผ่านระบบข้อมูลผู้เล่น
  • การเลียนแบบผ่าน คุณลักษณะ .
  • การเลียนแบบผ่านแท็ก .
  • การส่งข้อความ โดยตรง ผ่านโมดูล เครือข่าย

การเลียนแบบผ่านระบบข้อมูลผู้เล่น

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

ตัวอย่างเช่น แทนที่จะยิง bespoke UpdateCoins``Class.RemoteEvent เพื่อบอกลูกค้าว่ามีเหรียญกี่อัน คุณสามารถโทรไปที่สิ่งต่อไปนี้และให้ลูกค้าสมัครรับผ่านเหตุการณ์ PlayerDataClient.updated


PlayerDataServer:setValue(player, "coins", 5)

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

  • ขั้นตอน FTUE ปัจจุบัน
  • คลังไอเท็ม
  • จํานวนเหรียญที่ผู้เล่นมี
  • สถานะฟาร์มของผู้เล่น

การเลียนแบบผ่านคุณสมบัติ

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

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

คุณยังสามารถอ่านคุณสมบัติโดยตรงจากโมเดลข้อมูลได้จากไคลเอนต์หรือเซิร์ฟเวอร์โดยตรงด้วยวิธี GetAttribute() และสมัครรับการเปลี่ยนแปลงด้วยวิธี GetAttributeChangedSignal()ในโครงการ โรงงาน วิธีนี้จะถูกใช้เพื่อ, ในหมู่สิ่งอื่น ๆ, สําหรับการสําเนาสถานะปัจจุบันของพืชให้กับลูกค้า

การเลียนแบบผ่านแท็ก

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

ตัวอย่างเช่น แท็ก CanPlant ถูกใช้บนเซิร์ฟเวอร์เพื่อสื่อสารกับไคลเอนต์ว่าหม้อที่กำหนดให้สามารถรับพืชได้

ส่งข้อความโดยตรงผ่านโมดูลเครือข่าย

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

พืช ใช้การโทรเครือข่ายโดยตรงสำหรับคำขอของลูกค้าหลากหลายรวมถึง:

  • รดน้ำต้นไม้
  • ปลูกเมล็ด
  • ไอเท็ม

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

คลาสและซิงเลตอน

คลาสในโครงการ พืช สามารถสร้างและทำลายได้เหมือนตัวอย่างบน Robloxคําสั่งของคลาสได้รับแรงบันดาลใจจากวิธีการ Lua ที่ไอดิโอมาตรฐานสําหรับการเขียนโปรแกรมแบบเป้าหมาย กับการเปลี่ยนแปลงหลายอย่างเพื่อเปิดใช้งานการตรวจสอบประเภทอย่างเคร่งครัด โดยมีการเปลี่ยนแปลงหลายอย่างเพื่อเปิดใช้งานการตรวจสอบประเภทอย่างเคร่งครัด

การสร้างทันที

หลายคลาสในโครงการมีความสัมพันธ์กับหนึ่งหรือมากกว่า Instancesวัตถุของคลาสที่กำหนดได้ถูกสร้างโดยใช้วิธี new() ในการสร้างตัวอย่างที่สอดคล้องกับวิธีที่ตัวอย่างถูกสร้างใน Roblox โดยใช้ Instance.new()

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

ตัวอย่างที่ตรงกัน

ตามที่ระบุไว้ข้างต้น หลายคลาสในโครงการนี้มีการแทนที่โมเดลข้อมูล ตัวอย่างที่ตรงกับคลาสและถูกควบคุมโดยมัน

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

การรวม

แม้ว่าการมรดกจะเป็นไปได้ใน Luau โดยใช้ metatables แต่โครงการเลือกที่จะอนุญาตให้คลาสสามารถขยายตัวกันผ่าน composition เมื่อรวมชั้นผ่านการสร้างขึ้น วัตถุ "ลูก" จะถูกสร้างขึ้นในวิธี new() ของคลาสและรวมอยู่ในฐานะสมาชิกภายใต้ self

สำหรับตัวอย่างนี้ในการดำเนินการดูที่คลาส CloseButton ซึ่งห่อหุ้มคลาส Button

ทำความสะอาด

คล้ายกับวิธีที่ Instance สามารถถูกทําลายได้ด้วยวิธี Destroy() คลาสที่สามารถสร้างได้ก็สามารถถูกทําลายได้เช่นกันวิธีการทำลายสำหรับคลาสโครงการคือ ด้วยตัวอักษรเล็ก สำหรับความสอดคล้องของคลาสในโค้ดทั้งหมดรวมถึงการแยกแยะระหว่างคลาสโครงการและ Roblox ตัวอย่าง นอกจากนี้ยังใช้เพื่อแยกแยะระหว่างคลาสในโค้ดของโครงการและ Roblox ตัวอย่าง

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

ซิงเลตอน

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

ซิงเลตันแตกต่างจากคลาสที่ไม่เสถียรโดยความจริงที่ว่าพวกเขาไม่มีวิธี new() เมธอดแทนที่จะส่งวัตถุพร้อมกับวิธีการและสถานะของมันกลับโดยตรงผ่าน ModuleScriptเนื่องจากไม่มีการสร้างสิงเลตอน จึงไม่มีการใช้สัญลักษณ์ self และวิธีการจะถูกเรียกแทนด้วยจุลภาค ( . ) แทนที่จะใช้จุลภาค ( : )

การตรวจสอบประเภทที่เคร่งครัด

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

คําสั่งประเภทคลาส

วิธีที่กำหนดไว้ในการสร้างคลาสใน Lua คือ เอกสารได้ดี แต่ไม่เหมาะกับการพิมพ์ Luau ที่แข็งแกร่งใน Luau วิธีที่ง่ายที่สุดในการรับประเภทของคลาสคือวิธี typeof() :


type ClassType = typeof(Class.new())

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

เพื่อสนับสนุนการตรวจสอบประเภทที่เคร่งครัด โครงการ พืช ใช้การแก้ปัญหาที่แตกต่างจากภาษา Lua คลาสสัญญาณในหลายวิธี ซึ่งบางส่วนอาจรู้สึกไม่ชัดเจน:

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

--!เคร่งครัด
local MyClass = {}
MyClass.__index = MyClass
export type ClassType = typeof(setmetatable(
{} :: {
property: number,
},
MyClass
))
function MyClass.new(property: number): ClassType
local self = {
property = property,
}
setmetatable(self, MyClass)
return self
end
function MyClass.addOne(self: ClassType)
self.property += 1
end
return MyClass

ประเภทการโค้งหลังการป้องกันทางเหตุผล

ในเวลาของการเขียน, ประเภทของค่าจะไม่ถูกจำกัดหลังจากคําสั่งเงื่อนไขการป้องกันตัวอย่างเช่น หลังจากปฏิบัติตามยามด้านล่าง ประเภทของ optionalParameter จะไม่ถูกจำกัดเป็น number


--!เคร่งครัด
local function foo(optionalParameter: number?)
if not optionalParameter then
return
end
print(optionalParameter + 1)
end

เพื่อลดปัญหานี้ จะสร้างตัวแปรใหม่หลังจากผู้พิทักษ์เหล่านี้ด้วยประเภทที่ชัดเจน


--!เคร่งครัด
local function foo(optionalParameter: number?)
if not optionalParameter then
return
end
local parameter = optionalParameter :: number
print(parameter + 1)
end

ข้ามโครงสร้างชั้นของ DataModel

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

วิธีหนึ่งในการเผชิญความท้าทายนี้คือการโค้งถึง any แล้วปรับแต่ง ตัวอย่างเช่น:


local function enableVendor(vendor: Model)
local zonePart: BasePart = (vendor :: any).ZonePart
end

ปัญหาของวิธีนี้คือมันส่งผลต่อการอ่านได้ เนื่องจากมันส่งผลต่อการอ่านได้แทนที่โครงการใช้โมดูลทั่วไปชื่อว่า getInstance สำหรับการเดินทางผ่านชั้นวาระของโมเดลข้อมูลที่โยนไปยัง any ภายใน


local function enableVendor(vendor: Model)
local zonePart: BasePart = getInstance(vendor, "ZonePart")
end

เมื่อความเข้าใจของเครื่องประเภทเกี่ยวกับโมเดลข้อมูลพัฒนาขึ้น ก็เป็นไปได้ว่ารูปแบบเช่นนี้จะไม่จำเป็นอีกต่อไป

อินเทอร์เฟซผู้ใช้

โรงงาน รวมถึงอินเทอร์เฟซผู้ใช้ 2D ที่ซับซ้อนและง่ายหลากหลายซึ่งรวมถึงไอเทมหน้าจอแสดงข้อมูลที่ไม่สามารถโต้ตอบได้ (HUD) เลือกซื้อ

วิธีการ UI

คุณสามารถเปรียบเทียบ Roblox UI กับ HTML DOM ได้อย่างหลวมๆ เพราะเป็นลำดับของวัตถุที่อธิบายถึงสิ่งที่ผู้ใช้ควรเห็นวิธีการสร้างและอัปเดตอินเทอร์เฟซผู้ใช้ Roblox แบ่งออกเป็น 2 ประเภทใหญ่คือ บังคับ และ ประกาศ การปฏิบัติ

วิธีการข้อดีและข้อเสีย
บังคับ

ในการออกแบบแบบบังคับ UI จะได้รับการปฏิบัติเหมือนกับลำดับชั้นอินสแตนซ์อื่นๆ บน Robloxโครงสร้าง UI จะถูกสร้างก่อนที่จะรันใน Studio และเพิ่มลงในโมเดลข้อมูลโดยปกติโดยตรงใน StarterGuiจากนั้นในระหว่างการทำงานรหัสจะดัดแปลงชิ้นส่วนเฉพาะของ UI เพื่อสะท้อนสถานะที่ผู้สร้างต้องการ:

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

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

ความท้าทายอีกอย่างหนึ่งด้วยวิธีการที่มีความจำเป็นคือการที่ยากที่จะแยกส่วน UI ให้เป็นส่วนที่มีความหมายที่สามารถประกาศได้ครั้งเดียวและนำมาใช้ซ้ำได้เนื่องจากต้นไม้ UI ทั้งหมดถูกประกาศในเวลาแก้ไขจึงอาจมีลายทั่วไปซ้ำในหลายส่วนของโมเดลข้อมูลได้

ประกาศ

ในการอนุกรมแบบเรียกใช้ สถานะที่ต้องการของตัวอย่าง UI จะถูกประกาศอย่างชัดเจน และการดำเนินการที่มีประสิทธิภาพของสถานะนี้จะถูกแยกออกโดยไลบรารีเช่น Roact หรือ Fusion:

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

ข้อเสียหลักคือต้องประกาศต้นไม้ UI ทั้งหมดในรหัสห้องสมุดเช่น Roact และ Fusion มีสัญลักษณ์เพื่อทำให้ง่ายขึ้น แต่ก็ยังคงเป็นกระบวนการที่ใช้เวลานานและประสบการณ์การแก้ไขที่น้อยกว่าเมื่อสร้าง UI

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

สถาปัตยกรรมระดับสูง

Plant project UI architecture diagram

ชั้นและส่วนประกอบ

ใน พืช ทั้งหมด UI จะเป็น Layer หรือ Component

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

ดูการจัดการ

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

พืช เข้าใกล้ปัญหานี้ด้วยระบบ UIHandler ซึ่งจัดการเมื่อชั้น UI ควรหรือไม่ควรปรากฏให้เห็นชั้น UI ทั้งหมดในเกมจะถูกจัดหมวดหมู่เป็น HUD หรือ Menu และการมองเห็นของพวกเขาจะได้รับการจัดการโดยกฎต่อไปนี้:

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

วิธีนี้ใช้งานได้ง่ายเพราะช่วยให้สามารถนําทางเมนูด้วยประวัติได้หากเปิดเมนูหนึ่งจากเมนูอื่น การปิดเมนูใหม่จะแสดงเมนูเก่าอีกครั้ง

ชั้นส่วนตัวของ UI ลงทะเบียนตัวเองกับ UIHandler และได้รับสัญญาณที่จะยิงเมื่อเปลี่ยนวิสัยทัศน์ของมัน

อ่านต่อ

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

  • โมเดลไคลเอนต์-เซิร์ฟเวอร์ — ภาพรวมของโมเดลไคลเอนต์-เซิร์ฟเวอร์ใน Roblox
  • Luau — รายละเอียดเกี่ยวกับ Luau ภาษาสคริปต์ที่สร้างขึ้นโดย Roblox ที่มาจาก Lua 5.1
  • อีเวนต์ระยะไกลและการโทรกลับ — ทั้งหมดเกี่ยวกับอีเวนต์เครือข่ายระยะไกลและการโทรกลับสำหรับการสื่อสารข้ามเส้นแบ่งไคลเอนต์-เซิร์ฟเวอร์
  • UI — รายละเอียดเกี่ยวกับวัตถุอินเทอร์เฟซผู้ใช้และการออกแบบบน Roblox

ในหน้านี้