ฉันจะหลีกเลี่ยงคลาสผู้เล่นยักษ์ได้อย่างไร


46

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


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

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

17
@ChrisMcFarland ไม่แนะนำให้สำรองข้อมูลแนะนำให้ใช้รหัสรุ่น XD
GameDeveloper

1
@ChrisMcFarland ฉันเห็นด้วยกับ GameDeveloper มีการควบคุมเวอร์ชันเช่น Git, svn, TFS, ... ทำให้การพัฒนาง่ายขึ้นมากเนื่องจากสามารถยกเลิกการเปลี่ยนแปลงขนาดใหญ่ได้ง่ายขึ้นและสามารถกู้คืนได้ง่ายจากสิ่งต่าง ๆ เช่นการลบโครงการของคุณฮาร์ดแวร์ล้มเหลวหรือไฟล์เสียหายโดยไม่ตั้งใจ
Nzall

3
@TylerH: ฉันไม่เห็นด้วยอย่างยิ่ง การสำรองข้อมูลไม่อนุญาตให้รวมการเปลี่ยนแปลงการสำรวจจำนวนมากเข้าด้วยกันและไม่เชื่อมโยงทุกที่ที่อยู่ใกล้กับข้อมูลเมตาที่เป็นประโยชน์มากกับชุดการแก้ไขและไม่เปิดใช้งานเวิร์กโฟลว์ที่มีนักพัฒนาหลายคนที่มีสติ คุณสามารถใช้การควบคุมเวอร์ชันเช่นระบบสำรองข้อมูล ณ จุดเวลาที่ทรงพลัง แต่นั่นก็ยังขาดศักยภาพของเครื่องมือเหล่านั้นมากมาย
Phoshi

คำตอบ:


67

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

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

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

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

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


ความคิดเห็นไม่ได้มีไว้สำหรับการอภิปรายเพิ่มเติม การสนทนานี้ได้รับการย้ายไปแชท
MichaelHouse

8
ในขณะที่ฉันเข้าใจความคิดเห็นเกี่ยวกับการย้ายที่ต้องย้ายอย่าย้ายสิ่งที่ท้าทายความถูกต้องของคำตอบ นั่นควรจะชัดเจนใช่ไหม
bug-a-lot

20

เกมไม่ได้มีลักษณะเฉพาะในเรื่องนี้ เทพคลาสเป็นรูปแบบต่อต้านทุกที่

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

อีกตัวอย่างหนึ่ง: ตัวละครของผู้เล่นอาจมีความสัมพันธ์กับ NPC ดังนั้นคุณอาจมีการclass Relationอ้างอิงทั้งPlayerวัตถุและNPCวัตถุ แต่เป็นของทั้งสอง


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

1
ผู้คนมักจะพูดว่าบางสิ่งเป็นเทพเจ้าหรือเทพเจ้าวัตถุเมื่อมีและจัดการคลาส / วัตถุอื่น ๆ ในเกม
Bálint

11

1) ผู้เล่น: สถาปัตยกรรมที่ใช้เครื่องรัฐ + ส่วนประกอบ

ส่วนประกอบปกติสำหรับ Player: HealthSystem, MovementSystem, InventorySystem, ActionSystem class HealthSystemผู้เรียนทุกคนชอบ

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

รัฐ: LootState, RunState, WalkState, AttackState, IDLEState

interface IStateทุกสืบทอดจากรัฐ IStateมีในกรณีของเรามี 4 วิธีสำหรับตัวอย่างLoot() Run() Walk() Attack()

นอกจากนี้เรายังมีclass InputControllerจุดที่เราตรวจสอบอินพุตของผู้ใช้ทุกคน

ตอนนี้กับตัวอย่างจริง: ในInputControllerเราตรวจสอบว่าเครื่องรีดผู้เล่นคนใดของแล้วถ้าเขายังกดWASD or arrows Shiftถ้าเขากดเพียงWASDแล้วที่เราเรียกว่า_currentPlayerState.Walk();เมื่อ happends นี้และเรามีcurrentPlayerStateให้เท่ากับWalkStateแล้วWalkState.Walk() เรามีส่วนประกอบทั้งหมดที่จำเป็นสำหรับรัฐนี้ - ในกรณีนี้MovementSystemเราจึงให้ย้ายผู้เล่นpublic void Walk() { _playerMovementSystem.Walk(); }- คุณเห็นสิ่งที่เรามีที่นี่? เรามีพฤติกรรมที่สองชั้นและเป็นสิ่งที่ดีมากสำหรับการบำรุงรักษารหัสและการแก้จุดบกพร่อง

ทีนี้สำหรับกรณีที่สอง: ถ้าเรากดWASD+ Shiftล่ะ? WalkStateแต่สถานะก่อนหน้านี้ของเราคือ ในกรณีนี้Run()จะถูกเรียกInputController(ไม่รวมกันนี้Run()ถูกเรียกเพราะเรามีWASD+ Shiftเช็คอินInputControllerไม่ใช่เพราะWalkState) เมื่อเราโทร_currentPlayerState.Run();ในWalkState- เรารู้ว่าเราต้องเปลี่ยน_currentPlayerStateไปRunStateและเราจะทำเช่นนั้นในRun()ของWalkStateและเรียกมันอีกครั้งภายในวิธีนี้ แต่ตอนนี้มีสถานะที่แตกต่างกันเพราะเราไม่ต้องการให้ดำเนินการสูญเสียกรอบนี้ _playerMovementSystem.Run();และตอนนี้ของหลักสูตรที่เราเรียกว่า

แต่จะเกิดอะไรขึ้นLootStateเมื่อผู้เล่นไม่สามารถเดินหรือวิ่งจนกว่าเขาจะปล่อยปุ่มได้? ในกรณีนี้เมื่อเราเริ่มปล้นสะดมตัวอย่างเช่นเมื่อEกดปุ่มเราเรียกว่า_currentPlayerState.Loot();เราสลับไปLootStateและตอนนี้เรียกมันจากที่นั่น ที่นั่นเรายกตัวอย่างเช่นวิธีการเรียก collsion เพื่อให้ได้ถ้ามีบางอย่างที่จะยกเค้าในช่วง และเราเรียก coroutine ที่เรามีภาพเคลื่อนไหวหรือที่เราเริ่มต้นและตรวจสอบว่าผู้เล่นยังคงกดปุ่มถ้าไม่ coroutine แตกถ้าใช่เราให้เขายกเค้าในตอนท้ายของ coroutine แต่ถ้าหากผู้เล่นกดWASD? - _currentPlayerState.Walk();ถูกเรียก แต่นี่คือสิ่งที่น่าสนใจเกี่ยวกับเครื่องจักรสถานะLootState.Walk()เรามีวิธีการที่ว่างเปล่าที่ไม่ทำอะไรเลยหรืออย่างที่ฉันจะทำในฐานะผู้เล่นบอกว่า: "เฮ้ชายฉันยังไม่ขโมยเลยคุณรอได้ไหม IDLEStateเมื่อเขาสิ้นสุดปล้นเราเปลี่ยนไป

นอกจากนี้คุณสามารถทำสคริปต์อื่นที่เรียกclass BaseState : IStateว่ามีการใช้วิธีการเริ่มต้นเหล่านี้ทั้งหมด แต่มีvirtualเพื่อให้คุณสามารถoverrideในclass LootState : BaseStateประเภทของคลาส


ระบบที่ใช้องค์ประกอบนั้นยอดเยี่ยมสิ่งเดียวที่ทำให้ฉันรำคาญใจคืออินสแตนซ์หลายตัว และใช้หน่วยความจำมากขึ้นและใช้งานได้กับตัวรวบรวมขยะ ตัวอย่างเช่นหากคุณมีศัตรู 1,000 รายการ พวกเขาทั้งหมดมี 4 องค์ประกอบ วัตถุ 4000 ชิ้นแทน 1,000 Mb ไม่ใช่เรื่องใหญ่มาก (ฉันยังไม่ได้ทดสอบประสิทธิภาพ) ถ้าเราพิจารณาส่วนประกอบทั้งหมดที่ gameobject มีอยู่


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

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

ก่อนอื่นฉันจะบอกว่าสินค้าคงคลัง, การสร้าง, การเคลื่อนไหว, การสร้างควรเป็นส่วนประกอบเพราะมันไม่ใช่ความรับผิดชอบของผู้เล่นที่จะมีวิธีการเช่นAddItemToInventoryArray()- แม้ว่าผู้เล่นสามารถมีวิธีการเช่นPutItemToInventory()ที่จะเรียกวิธีการที่อธิบายไว้ก่อนหน้านี้ เพิ่มเงื่อนไขบางอย่างขึ้นอยู่กับชั้นที่แตกต่างกัน)

อีกตัวอย่างหนึ่งกับอาคาร ผู้เล่นสามารถโทรหาสิ่งที่ต้องการOpenBuildingWindow()แต่Buildingจะดูแลส่วนที่เหลือทั้งหมดและเมื่อผู้ใช้ตัดสินใจที่จะสร้างสิ่งปลูกสร้างที่เฉพาะเจาะจงเขาจะส่งข้อมูลที่จำเป็นทั้งหมดไปยังผู้เล่นBuild(BuildingInfo someBuildingInfo)และผู้เล่นจะเริ่มสร้างด้วยภาพเคลื่อนไหวที่จำเป็นทั้งหมด

หลักการของ SOLID - OOP S - ความรับผิดชอบเดี่ยว: สิ่งที่เราเห็นในตัวอย่างก่อนหน้านี้ ใช่แล้ว แต่มรดกอยู่ที่ไหน

ที่นี่: ควรมีการจัดการสุขภาพและคุณสมบัติอื่น ๆ ของผู้เล่นโดยเอนทิตี้อื่น? ผมคิดว่าไม่. ไม่มีผู้เล่นที่ไม่มีสุขภาพถ้ามีเราก็ไม่ได้รับมรดก ตัวอย่างเช่นเรามีIDamagable, LivingEntity, ,IGameActor ของหลักสูตรมีGameActorIDamagableTakeDamage()

class LivinEntity : IDamagable {

   private float _health; // For fields that are the same between Instances I would use Flyweight Pattern.

   public void TakeDamage() {
       ....
   }
}

class GameActor : LivingEntity, IGameActor {
    // Here goes state machine and other attached components needed.
}

class Player : GameActor {
   // Inventory, Building, Crafting.... components.
}

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

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


ฉันขอแนะนำให้ใช้บางสิ่งบางอย่างในระหว่าง และไม่ใช้องค์ประกอบมากเกินไป


ฉันขอแนะนำให้อ่านหนังสือเล่มนี้เกี่ยวกับรูปแบบการเขียนโปรแกรมเกม - ฟรีบนเว็บ


ฉันจะขุดในคืนนี้ในภายหลัง แต่ FYI ฉันไม่ได้ใช้ความเป็นเอกภาพดังนั้นฉันจะต้องปรับเปลี่ยนบางอย่างที่ใช้ได้
user441521

โอ้ฉันคิดว่าที่นี่เป็นแท็ก Unity โอ้ฉันไม่ดี สิ่งเดียวคือ MonoBehavior - เป็นเพียงคลาสพื้นฐานสำหรับอินสแตนซ์ทุกฉากในเอดิเตอร์ Unity สำหรับ Physics.OverlapSphere () - เป็นวิธีที่สร้างคอลเดอร์ทรงกลมระหว่างเฟรมและตรวจสอบสิ่งที่มันสัมผัส Coroutines เปรียบเสมือนการอัปเดตปลอมการโทรของพวกเขาสามารถลดลงเป็นจำนวนที่น้อยกว่า fps บนพีซีของผู้เล่น - ดีต่อประสิทธิภาพ Start () - เพียงวิธีการหนึ่งที่เรียกว่าเมื่อสร้างอินสแตนซ์ ทุกอย่างอื่นควรนำไปใช้ทุกที่อื่น ส่วนต่อไปฉันจะไม่ใช้อะไรกับ Unity sry หวังว่านี่จะมีบางสิ่งที่ชัดเจน
Candid Moon _Max_

ฉันเคยใช้ Unity มาก่อนดังนั้นฉันจึงเข้าใจความคิดนี้ ฉันใช้ Lua ซึ่งมี coroutines เช่นกันดังนั้นสิ่งต่าง ๆ ควรแปลได้ค่อนข้างดี
user441521

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

@CandidMoon ใช่ดีกว่า
Pharap

4

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

ประการแรกความคิดของPlayerคลาสนั้นทำให้เข้าใจผิดในตอนแรก หลายคนมักจะคิดว่าตัวละครผู้เล่นตัวละคร npc และสัตว์ประหลาด / ศัตรูเป็นคลาสที่แตกต่างกันเมื่อในความเป็นจริงทุกคนมีเหมือนกันมาก: พวกเขาถูกวาดบนหน้าจอพวกเขาทั้งหมดย้ายไปรอบ ๆ พวกเขาอาจ ทั้งหมดมีสินค้าคงเหลือ ฯลฯ

วิธีคิดนี้นำไปสู่วิธีการที่ตัวละครผู้เล่นตัวละครที่ไม่ใช่ผู้เล่นและสัตว์ประหลาด / ศัตรูได้รับการปฏิบัติเหมือนเป็น ' Entitys' แทนที่จะได้รับการปฏิบัติที่แตกต่างกัน แม้ว่าโดยธรรมชาติแล้วพวกเขาจะต้องประพฤติตัวที่แตกต่าง - ตัวละครของผู้เล่นจะต้องมีการควบคุมผ่านทางอินพุทและเอ็นพีแอลต้องมีไอ

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

นอกจากนี้โดยการซับคลาสControllerเข้าInputControllerและAIControllerอนุญาตให้ผู้เล่นควบคุมสิ่งใดก็ได้Entityในห้องอย่างมีประสิทธิภาพ วิธีการนี้ยังช่วยในเรื่องของผู้เล่นหลายคนด้วยการมีคลาสRemoteControllerหรือNetworkControllerทำงานผ่านคำสั่งจากสตรีมเครือข่าย

ซึ่งอาจส่งผลให้ตรรกะจำนวนมากถูกสวมเป็นหนึ่งControllerถ้าคุณไม่ระวัง วิธีที่จะหลีกเลี่ยงที่จะมีControllerของที่มีองค์ประกอบของอื่น ๆControllers หรือทำให้การทำงานขึ้นอยู่กับคุณสมบัติต่างๆของController Controllerยกตัวอย่างเช่นAIControllerจะมีDecisionTreeแนบมากับมันและPlayerCharacterControllerอาจจะประกอบด้วยอื่น ๆControllers เช่นMovementControllerเป็นJumpController(มีเครื่องรัฐกับรัฐ OnGround, มากและจาก) InventoryUIControllerซึ่งเป็น ประโยชน์เพิ่มเติมของสิ่งนี้คือControllerสามารถเพิ่ม s ใหม่ได้เมื่อมีการเพิ่มฟีเจอร์ใหม่ - หากเกมเริ่มต้นโดยไม่มีระบบสินค้าคงคลังและมีการเพิ่มหนึ่งรายการตัวควบคุมสำหรับมันจะสามารถแก้ไขได้ในภายหลัง


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

@ user441521 เพิ่งรู้ว่ามีย่อหน้าพิเศษที่ฉันจะเพิ่ม แต่ฉันหายไปเมื่อเบราว์เซอร์ของฉันล้มเหลว ฉันจะเพิ่มทันที โดยพื้นฐานแล้วคุณสามารถมีตัวควบคุมที่แตกต่างกันสามารถเขียนลงในตัวควบคุมแบบรวมดังนั้นแต่ละตัวควบคุมจะจัดการสิ่งต่าง ๆ เช่น AggregateController.Controllers = {JumpController (keybinds), MoveController (keybinds), InventoryUIController (keybinds, uisystem)}
Pharap
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.