ระบบต่อไปนี้เป็นพื้นฐานในการสร้างประสบการณ์การเล่นเกมที่เราต้องการสำหรับ The Mystery of Duvall Drive
เกมสเตตมาเนจเจอร์
The GameStateManager / GameStateClient เป็นระบบที่ซับซ้อนที่สุดในประสบการณ์เนื่องจากจัดการกับ:
- เริ่มผู้เล่นภายในล็อบบี้ เริ่มนับถอยหลังเพื่อส่งผู้เล่นไปยังพื้นที่เล่นเกมหลัก และเริ่มเรียกผู้เล่นไปยังเซิร์ฟเวอร์ที่จำกัด
- การโคลนห้องที่เสียหายและสตรีมแบบอัจฉริยะและการเคลื่อนย้ายผู้เล่นไปยังและจากตำแหน่ง CFrame ที่กำหนดเฉพาะ
- การหยิบและวางรัศมีการเซ็น
- ล็อคและปลดล็อคประตู
- กําลังเริ่มเทเลพอร์ตครั้งสุดท้ายไปยังล็อบบี้และเล่นฉากตัดต่อที่สมบูรณ์
เราจัดการมันเป็นเครื่องจักรสถานะง่าย (เทเลพอร์ต) และสถานะอยู่ใน DemoConfig (GameStates รายการ) บางสถานะจัดการกับการเคลื่อนไหวล็อบบี้/เซิร์ฟเ
GameStates เป็นส่วนใหญ่เป็นด้านเซิร์ฟเวอร์ แต่เมื่อลูกค้าต้องการทำอะไรบางอย่างเช่นแสดงความนับถอยหลังประวัติลูกษณะหรือปิดการแสดงผล UI เซิร์ฟเวอร์และลูกค
สถานะเกมการเทเลพอร์ต
มีกลุ่มของ 3 สมจริง
ในขณะที่การสตรีมกำลังจัดการไปยัง, InFlight รัน, เก็บ
ชุดคอลดาวน์, อินฟลายท์, และคอลดาวน์ที่คล้ายกันเกิดขึ้นเมื่อเราเทเลพอร์ตผู้เล่
สถานะเกมการจัดแสงและบรรยากาศ
เรารู้ว่าเราต้องก
ล็อคสถานะประตู
เ
ผู้จัดกิจกรรม
EventManager ช่วยให้เราสามารถดำเนินการ "การกระทํา" ได้ในระยะเวลาโดยใช้ keyFRAME เช่น:
- การใช้คุณสมบัติและคุณลักษณะของตัวอินสแตนซ์
- การประมวลผลสคริปต์
- เล่นเสียง
- การทำงานของกล้องสั่น
เราต้องการใช้เครื่องมือที่มี UI เชิงเส้น แต่สำหรับโดเมโนนี้ เราพิมพ์ชื่อคีย์และชื่อสกุลของคุณด้วยมือ ระบบ EventManager ประกอบด้วยสคริปต์หลายตัวและความเป็นอีเว้นท์/ฟังก์ชัน รวมถึง:
- EventManager - โลกิกทั่วไปสำหรับการสร้างและหยุดเหตุการณ์, เช่นเดียวกับการกระทําของเซิร์ฟเวอร์
- EventManagerClient - การกระทําข้างเครื่องคอมพิวเตอร์
- EventManagerModule - รหัสทั่วไปสำหรับทั้งสองด้านเซิร์ฟเวอร์และด้านลูกค้า
- EventManagerConfig - ไฟล์ขนาดเล็กที่มีการประกาศคำสั่งบางอย่าง
- EventManagerDemo - ที่ทุกอีเว้นท์จริงสำหรับดีโอเมโดจะถูกกำหนดในสคริปต์เฉพาะเกม
- EventManagerEvent , EventManagerFunc - ระบบเหตุการณ์รีโมทและสามารถใช้งานได้เพื่อดำเนินการและหยุดเหตุการณ์จากลูกค้าหรือเซิร์ฟเวอร์ นี่คือวิธีที่ระบบอื่นๆ สามารถกำหนด ใช้งาน และหยุดเหตุการ
แต่ละอีเวนต์มีชื่อ มีส่วนที่มีข้อมูลเกี่ยวกับคูลดาวน์ การใช้งานตามจุดเริ่มต้นหรือจุดสิ้นสุด ตัวแปรอีเวนต์ และส่วนที่มีตัวประกายตามเวลา สคริปต์ที่ลงทะเบียน และการเล่นเสี
การแปล
การแปลงช่วยให้สมบัติของคุณและค่าตัวละครสามารถเปลี่ยนได้อย่างราบรื่นระหว่างหนึ่งค่าเป็นอื
interpolants = {objectParam = "TextLabel",property = "TextTransparency",keys = {{value = 1},{time = .5, value = 0},{time = 2.25, value = 0},{time = 3, value = 1}}}
ในขณะที่เราสามารถระบุได้ว่าโปรไฟล์หรือคุณสมบัติของวัตถุใดที่เป็นของอะไรในตัวอย่างโค้ดต่อไปนี้เราต้องการที่จะสามารถใช้เหตุการณ์เดียวกันบน "กลุ่มของวัตถุ" ต่างๆ เพื่อให้สามารถ
object = workspace.SomeFolder.SomeModel
เพื่อประสบความสำเร็จในการทำเช่นนี้เราอนุญาตให้อ้างอิงโดยชื่อวัตถุและการส่งตัวอ้างชื่อในขณะที่เหตุการณ์เริ่มขึ้น เพื่
params = {["RootObject"] = workspace.Content.Interior.Foyer["Ritual-DemoVersion"],},interpolants = {objectName = "Wander",attribute = "TimeScale",keys = {{value = 0.2}}}
เราอนุญาตให้ตัวแปรในอีเวนต์ในส่วนตัวอีเวนต์ และสคริปต์ที่วิ่งในตอนเริ่มอีเวนต์สามารถเปล
params = {isEnabled = false},interpolants = {{objectName = "FocuserGlow",property = "Enabled",keys = {{valueParam = "isEnabled"}}}
ตัวแปรที่สามารถให้เราอ้างอิงไปยังวัตถุที่ไม่มีอยู่ในต้นของประสบการณ์ เช่นในตัวอย่างโค้ดต่อไปนี้โค้ดรุ่นที่วิ่งบนเหตุการณ์เริ่มจะสร้างวัตถุและตั้ง BlackScreenObject เข้าในตัวประกายเพื่อชี้ไปที่
{objectParam = "BlackScreenObject",property = "BackgroundTransparency",keys = {{value = 0},{time = 19, value = 0},{value = 1},}}
การดำเนินงานเหตุการณ์ ตัวอย่างเหตุการณ์ และการเชื่อมต่อกับ Triggers
เพื่อดำเนินการอีเวนต์ เราจะใช้เหตุการณ์ระยะไกลจากลูกค้าหรือฟังก์ชันจากเซิร์ฟเวอร์ ในตัวอย่างต่อไปนี้ เราผ่านค่าตัวอย่างบางอย่างให้กับ RootObject
local params = {RootObject = workspace.Content.Interior.Foyer["Ritual-DemoVersion"]["SealDropoff_" .. missionName],isEnabled = enabled}local eventId = eventManagerFunc:Invoke("Run", {eventName = "Ritual_Init_Dropoff", eventParams = params} )
เราสามารถหยุดดำเนินการกิจกรรมโดยการเรียกคุณสมบัติด้วย "หยุด":
eventManagerFunc:Invoke("Stop", {eventInstId = cooldownId} )
สารเคมีหรือการกระทําอื่น ๆ ที่เป็น "การแต่งหน้า" (ไม่เปลี่ยนแปลงการจําลองสําหรับผู้เล่นทุกคน) สามารถดําเนินการบนเครื่องของลูกค้าซึ่งอาจทําให้เกิ
เพื่อเชื่อมต่อเหตุการณ์ที่ดำเนินอยู่กับเวลาเปิด/ปิดของเหตุการณ์ เราใช้หน้าที่ช่วยเหลือ ConnectTriggerToEvent หรือ
ตัวแปรอีเวนต์
นอกเหนือจากตัวแปรงานที่กำหนดเองที่ผ่านมาจากสคริปต์, ข้อมูลอื่น ๆ ที่สามารถเป็นตัวเลือกเมื่อสร้างเหตุการณ์รวมถึงผู้เล่น, คืนเรียก (ที่จะเรี
อีเวนต์สามารถมีคูลดาวน์ที่กำหนดโดย minCooldownTime และ maxCooldownTime อย่างไรก็ตาม มินและมา
การเรียกสคริปต์
เราสามารถเรียก Scripts ใน keyframe ที่เฉพาะในส่วน สคริปต์ ได้ เช่น:
scripts = {{startTime = 2, scriptName = "EnablePlayerControls", params = {true}, onServer = false }}
ในตัวอย่างก่อนหน้านี้, EnablePlayerControls Script จะต้องลงทะเบียนกับโมดูลผู้จัดการอีเว้นท์, เช่น:
emModule.RegisterFunction("EnablePlayerControls", EnablePlayerControls)
ต้องมีการเรียก RegisterFunction ในสคริปต์ของลูกค้าสำหรับการเรียกใช้ฟังก์ชันในลูกค้า และในสคริปต์ของเซิร์ฟเวอร์สำหรับ onServer = true ตัวฟังก์ชันเองจะได้รับเหตุการณ์และตัวแปรที่ผ่านผ่าน แต่
local function EnablePlayerControls(eventInst, params)
เล่นเสียง
เรามีการสนับสนุนจำกัดสำหรับการเล่น ไม่มีตําแหน่งอาหรับ audio ใน keyframe ในส่วน เสียง โดยเฉพาะอย่างยิ่ง:
sounds = {{startTime = 2, name = "VisTech_ethereal_voices-001"},}
หมายเหตุว่าเหตุการณ์ที่สิ้นสุดลงจะเริ่มเมื่อเวลาอีเวนต์หมดอายุ แต่การดำเนินการของอีเมลอาจยังคงเล่นต่อไปหลังจากนี้
การทำงานของล้อเลนส์
เราสามารถจัดเตรียมการเคลื่อนไหวของกล้องในส่วน กล้อง Shakes ได้ดังนี้:
cameraShakes = {{startTime = 15, shake = "small", sustainDuration = 7, targets = emConfig.ShakeTargets.allPlayers, onServer = true},}
“เป้าหมาย” สามารถเริ่มได้เฉพาะผู้เล่นที่เริ่มเหตุการณ์ได้, ทั้งหมดของผู้เล่น, หรือ playersInRadius สำหรับผู้เล่นที่เริ่มต้น เราใช้สคริปต์ข
การจัดการภารกิจ
มี 7 ภารกิจทั้งหมด และเฉพาะ 6 ภารกิจเท่านั้นที่ใช้ตรา ส่วนใหญ่ภารกิจมีพารามิเตอร์ที่เหมือนกัน แต่บางภารกิจมีในสคริปท์ DemoConfig ด้วยชุดพารามิเตอร์ในแผนท
- MissionRoot : โฟลเดอร์ของเวอร์ชันทั้งหมดที่ไม่เสียหายของวัตถุ
- ประตู : ประตูล็อคจนกว่าผู้เล่นจะหยิบแผ่นตรา
- SealName / SolvedSealName : ชื่อซีลที่ไม่เสียหายและชื่อซีลที่เสียหาย
- SealPlaceName : สถานที่ที่จะวางตรา
- PlacedSealPlaceholderName : วัตถุ Placeholder ที่ตำแหน่งเพื่อวางตรา
- ชื่อตำแหน่งเทเลพอร์ต : ชื่อของโฟลเดอร์ที่มีเมชที่วางอยู่เพื่อการเทเลพอร์ตผู้เล่นและการหมุนเมื่อย้ายไปที่ห้องที่เสียหายและกลับไปที่พื้นที่ปกติ ชื่อเดียวกันใช้ในทั้งสองกรณี
- CorruptRoomName : ชื่อเรื่องของโฟลเดอร์ราก (สัมพันธ์กับ ServerStorage) สำหรับห้องที่เสียหาย ห้องที่เสียหายจะเรียกตัวเองว่า TempStorage.Cloned เมื่อเริ่มภารกิจและจะถูกทำลายเมื่อภารกิจสิ้นสุด
- MissionCompleteButtonName : ปุ่มเชิตในห้องที่เสียหายเพื่อเสร็จสิ้นภารกิจโดยทันที นี่คือสำหรับ วัตถุประสงค์ในการดีบั๊ก
- CheatKey : เช่นเดียวกับเช็คเหมือนตัวเลขหรือ CtrlShift[หมายเลข]
ส่วนหนึ่งของเหตุผลการทำงานบางส่วนอยู่ใน GameStateManager สคริปต์, เนื่องจากเหล็กและประตูให้การไหลเกมหลักสำหรับส่วนใหญ่
- ใช้กุญแจบนล็อค - ภารกิจแรกที่จะเปิดประตู ประเภทนี้กำหนดโดย LockName และ KeyName
- จับคู่รายการ - 4 รายการจับคู่. รุ่นนี้กำหนดโดย MatchItems
- แต่งตัวตุ๊กตาผู้ชายโดยใช้เสื้อผ้าหลายชั้นเสื้อผ้า - 1 ภารกิจในหลังคามีผู้เล่นสามรายการ ประเภทนี้ได้รับการจัดตั้งโดย DressItemsTagList
- คลิกที่รายการเพื่อเสร็จสิ้น - 1 พิมพ์ClickTargetName
แต่ละประเภทภารกิจมี StartMissionFunc และ CompleteMissionFunc ของตัวเอง กา
การจับคู่ระหว่างไอเท็มทำให้สามารถ "ใช้" (คลิกขณะที่กดค้าง) ไอเท็มที่มีแท็ก PuzzlePieceXX บนไอเท็มที่มีแ
การจับ
เราพัฒนาระบบจับที่เรียบง่ายเพื่อการจับตัววัตถุโดยการแนบตัววัตถุไว้ที่ขวาของตัวละคร การจับจะเริ
ในแต่ละเฟรมเราตรวจสอบว่าการโจมตีสัมพันธ์กันกำลังดำเนินอยู่หรือไม่ หากผู้เล่นอยู่ภายใน reachDist เราเริ่มเล่น ToolHoldAnim ตัวนี้ เมื่อผู้เล่นอยู่
สคริปต์ด้านเซิร์ฟเวอร์มี 2 หน้าที่สำคัญ:
- หยิบ - จัดการคำขอของลูกค้าเพื่อหยิบแบบ
- ปล่อย - จัดการคำขอปล่อยโมเดลที่จับได้
ข้อมูลเกี่ยวกับสิ่งที่ผู้เล่นแต่ละคนมีไว้ในแผนที่ playerInfos จะถูกเก็บไว้ในคลังข้อมูล หากเป็นเช่นนั้น - เราจะส่ง "EquipWorldFail" ไปยังลูกค้าและย
หากเก็บอนุญาตได้รับการอนุญาตให้ใช้สคริปต์สร้างสอง Class.Att
สำหรับการปล่อยตัวโมเดลที่จับได้ สคริปต์ของลูกค้าเชื่อมต่อกับปุ่ม GrabReleaseButton ใน HUD เครื่องมือใช้งาน ฟังก์