จุดประสงค์ของฉันคือการสร้างระบบไอเท็มแบบโมดูลาร์ / แบบทั่วไปที่สามารถจัดการสิ่งต่าง ๆ เช่น:
- รายการที่อัปเกรดได้ (+6 Katana)
- ตัวดัดแปลงทางสถิติ (ความชำนาญ +15)
- ตัวดัดแปลงไอเท็ม (โอกาส X% ที่จะทำความเสียหาย Y, โอกาสที่จะถูกแช่แข็ง)
- รายการที่ชาร์จใหม่ได้ (พนักงาน Magic กับประเพณี 30)
- Set Items (ติดตั้ง X 4 ชุดเพื่อเปิดใช้งานคุณสมบัติ Y)
- หายาก (ทั่วไป, ไม่ซ้ำใคร, ตำนาน)
- ทำให้ไม่ลงรอยกัน (แบ่งเป็นวัสดุหัตถกรรมบางอย่าง)
- Craftable (สามารถสร้างขึ้นด้วยวัสดุบางอย่าง)
- ใช้งานได้ (5 นาที% พลังโจมตี X, รักษา +15 hp)
* ฉันสามารถแก้ไขคุณสมบัติที่เป็นตัวหนาในการตั้งค่าต่อไปนี้
ตอนนี้ฉันพยายามเพิ่มตัวเลือกมากมายเพื่อสะท้อนสิ่งที่ฉันมีในใจ ฉันไม่ได้วางแผนที่จะเพิ่มคุณสมบัติเหล่านี้ทั้งหมดที่จำเป็น แต่ฉันต้องการที่จะสามารถใช้งานได้ตามที่เห็นสมควร สิ่งเหล่านี้ควรเข้ากันได้กับระบบสินค้าคงคลังและการเรียงลำดับข้อมูล
ฉันวางแผนที่จะไม่ใช้การสืบทอดเลย แต่เป็นวิธีการขับเคลื่อนเอนทิตีคอมโพเนนต์ / ข้อมูล ตอนแรกฉันนึกถึงระบบที่มี:
- BaseStat: คลาสทั่วไปที่เก็บสถานะ on-the-go (สามารถใช้สำหรับไอเท็มและสถิติของตัวละครได้เช่นกัน)
- รายการ: คลาสที่เก็บข้อมูลเช่นรายการชื่อรายการประเภทและสิ่งต่าง ๆ ที่เกี่ยวข้องกับ ui, actionName คำอธิบาย ฯลฯ
- IWeapon: ส่วนต่อประสานสำหรับอาวุธ อาวุธทุกชนิดจะมีคลาสของตัวเองโดยมีการใช้ IWeapon สิ่งนี้จะมีการโจมตีและการอ้างอิงถึงสถิติของตัวละคร เมื่อติดตั้งอาวุธมันคือข้อมูล (Item class 'stat) จะถูกฉีดเข้าไปในตัวละคร stat (ไม่ว่า BaseStat มันมีอะไรมันจะถูกเพิ่มเข้าไปในคลาสของตัวละครเป็นโบนัส Stat) ตัวอย่างเช่นเราต้องการสร้างดาบ สร้างคลาสไอเท็มด้วย json) ดังนั้น Sword จะเพิ่มการโจมตี 5 ครั้งให้กับสถิติตัวละคร ดังนั้นเราจึงมีBaseStatเป็น ("Attack", 5) (เราสามารถใช้ enum ได้เช่นกัน) สถิตินี้จะถูกเพิ่มลงในสถานะ "Attack" ของตัวละครเป็นBonusStat (ซึ่งจะเป็นคลาสที่แตกต่างกัน) เมื่อทำการติดตั้ง ดังนั้นคลาสที่ชื่อว่าSword จะใช้IWeaponจะถูกสร้างขึ้นเมื่อ 'สถานะที่ถูกสร้างขึ้นตัวละครคลาสไอเท็มเข้าสู่ดาบนี้และเมื่อโจมตีมันสามารถดึงสถิติการโจมตีทั้งหมดจากสถิติตัวละครและดาเมจความเสียหายในวิธีการโจมตี
- BonusStat: เป็นวิธีการเพิ่มสถิติเป็นโบนัสโดยไม่ต้องสัมผัส BaseStat
- IConsumable: ตรรกะเช่นเดียวกับ IWeapon การเพิ่มสถิติโดยตรงนั้นค่อนข้างง่าย (+15 hp) แต่ฉันไม่แน่ใจเกี่ยวกับการเพิ่มอาวุธชั่วคราวด้วยการตั้งค่านี้ (% x เพื่อโจมตีเป็นเวลา 5 นาที)
- IUpgradeable: สามารถดำเนินการได้ด้วยการตั้งค่านี้ ฉันคิดว่าUpgradeLevelเป็นสถิติพื้นฐานซึ่งเพิ่มขึ้นเมื่ออัพเกรดอาวุธ เมื่ออัปเกรดเราสามารถคำนวณBaseStatของอาวุธอีกครั้งเพื่อให้ตรงกับระดับการอัพเกรด
จนถึงจุดนี้ฉันเห็นว่าระบบนั้นค่อนข้างดี แต่สำหรับคุณสมบัติอื่น ๆ ฉันคิดว่าเราต้องการสิ่งอื่นเพราะตัวอย่างเช่นฉันไม่สามารถใช้คุณลักษณะ Craftable ในส่วนนี้ได้เพราะBaseStatของฉันจะไม่สามารถจัดการคุณลักษณะนี้ได้และนี่คือจุดที่ฉันติดอยู่ ฉันสามารถเพิ่มส่วนผสมทั้งหมดเป็นสถิติ แต่นั่นก็ไม่สมเหตุสมผล
เพื่อให้คุณมีส่วนร่วมได้ง่ายนี่คือคำถามที่คุณอาจช่วยได้:
- ฉันควรดำเนินการตั้งค่านี้ต่อไปเพื่อใช้คุณสมบัติอื่น ๆ หรือไม่ เป็นไปได้ไหมถ้าไม่มีมรดก?
- มีวิธีใดบ้างที่คุณคิดจะใช้คุณสมบัติเหล่านี้ทั้งหมดโดยไม่มีการสืบทอด?
- เกี่ยวกับตัวดัดแปลงไอเทมจะทำอย่างไรให้สำเร็จ? เพราะมันเป็นเรื่องธรรมดามากในธรรมชาติ
- สิ่งใดที่สามารถทำได้เพื่อลดขั้นตอนการสร้างสถาปัตยกรรมประเภทนี้คำแนะนำใด ๆ
- มีแหล่งที่ฉันสามารถขุดที่เกี่ยวข้องกับปัญหานี้หรือไม่
- ฉันพยายามหลีกเลี่ยงการสืบทอด แต่คุณคิดว่าสิ่งเหล่านี้จะได้รับการแก้ไข / ประสบความสำเร็จด้วยการสืบทอดได้อย่างง่ายดายในขณะที่รักษามันไว้ได้อย่างเป็นธรรม?
รู้สึกอิสระที่จะตอบคำถามเดียวเพราะฉันเก็บคำถามไว้อย่างกว้าง ๆ เพื่อที่ฉันจะได้รับความรู้จากด้านต่าง ๆ / ผู้คน
แก้ไข
ทำตามคำตอบของ @ jjimenezg93 ฉันได้สร้างระบบพื้นฐานใน C # สำหรับการทดสอบมันใช้งานได้! ดูว่าคุณสามารถเพิ่มอะไรลงไปได้ไหม:
public interface IItem
{
List<IAttribute> Components { get; set; }
void ReceiveMessage<T>(T message);
}
public interface IAttribute
{
IItem source { get; set; }
void ReceiveMessage<T>(T message);
}
จนถึงตอนนี้ IItem และ IAttribute เป็นอินเตอร์เฟสพื้นฐาน ไม่มีความจำเป็น (ที่ฉันสามารถนึกได้) ที่จะมีส่วนต่อประสานฐาน / คุณสมบัติสำหรับข้อความดังนั้นเราจะสร้างคลาสข้อความทดสอบโดยตรง ตอนนี้สำหรับชั้นเรียนทดสอบ:
public class TestItem : IItem
{
private List<IAttribute> _components = new List<IAttribute>();
public List<IAttribute> Components
{
get
{
return _components;
}
set
{
_components = value;
}
}
public void ReceiveMessage<T>(T message)
{
foreach (IAttribute attribute in Components)
{
attribute.ReceiveMessage(message);
}
}
}
public class TestAttribute : IAttribute
{
string _infoRequiredFromMessage;
public TestAttribute(IItem source)
{
_source = source;
}
private IItem _source;
public IItem source
{
get
{
return _source;
}
set
{
_source = value;
}
}
public void ReceiveMessage<T>(T message)
{
TestMessage convertedMessage = message as TestMessage;
if (convertedMessage != null)
{
convertedMessage.Execute();
_infoRequiredFromMessage = convertedMessage._particularInformationThatNeedsToBePassed;
Debug.Log("Message passed : " + _infoRequiredFromMessage);
}
}
}
public class TestMessage
{
private string _messageString;
private int _messageInt;
public string _particularInformationThatNeedsToBePassed;
public TestMessage(string messageString, int messageInt, string particularInformationThatNeedsToBePassed)
{
_messageString = messageString;
_messageInt = messageInt;
_particularInformationThatNeedsToBePassed = particularInformationThatNeedsToBePassed;
}
//messages should not have methods, so this is here for fun and testing.
public void Execute()
{
Debug.Log("Desired Execution Method: \nThis is test message : " + _messageString + "\nThis is test int : " + _messageInt);
}
}
นี่คือการตั้งค่าที่จำเป็น ตอนนี้เราสามารถใช้ระบบได้ (การติดตามสำหรับ Unity)
public class TestManager : MonoBehaviour
{
// Use this for initialization
void Start()
{
TestItem testItem = new TestItem();
TestAttribute testAttribute = new TestAttribute(testItem);
testItem.Components.Add(testAttribute);
TestMessage testMessage = new TestMessage("my test message", 1, "VERYIMPORTANTINFO");
testItem.ReceiveMessage(testMessage);
}
}
แนบสคริปต์ TestManager นี้ไปยังส่วนประกอบในฉากและคุณสามารถดูในการดีบักว่าข้อความถูกส่งผ่านสำเร็จ
เพื่ออธิบายสิ่งต่าง ๆ : ทุกรายการในเกมจะใช้อินเทอร์เฟซ IItem และทุกแอตทริบิวต์ (ชื่อไม่ควรทำให้คุณสับสนนั่นหมายถึงคุณลักษณะของไอเท็ม / ระบบเช่นอัปเกรดหรือไม่แยแส) จะใช้ IAttribute จากนั้นเรามีวิธีการประมวลผลข้อความ (ทำไมเราต้องการข้อความจะอธิบายในตัวอย่างเพิ่มเติม) ดังนั้นในบริบทคุณสามารถแนบแอททริบิวไปยังไอเท็มและปล่อยให้ส่วนที่เหลือทำเพื่อคุณ มีความยืดหยุ่นมากเพราะคุณสามารถเพิ่ม / ลบคุณสมบัติได้อย่างง่ายดาย ดังนั้นตัวอย่างที่หลอกจะไม่ลงรอยกัน เราจะมีคลาสที่เรียกว่า Disenchantable (IAttribute) และใน Disenchant method มันจะถามหา:
- รายการส่วนผสม (เมื่อไอเทมไม่แยแสไอเท็มใดควรมอบให้ผู้เล่น) หมายเหตุ: IItem ควรขยายให้มี ItemType, ItemID เป็นต้น
- int resultModifier (หากคุณใช้คุณสมบัติเพิ่มความสามารถในการลดระดับคุณสามารถส่งค่า int ที่นี่เพื่อเพิ่มส่วนผสมที่ได้รับเมื่อไม่ได้ใช้งาน)
- int failChance (หากกระบวนการที่ทำให้หมดกำลังใจมีโอกาสล้มเหลว)
เป็นต้น
ข้อมูลเหล่านี้จะถูกจัดเตรียมโดยคลาสที่เรียกว่า DisenchantManager มันจะได้รับไอเท็มและสร้างข้อความนี้ตามไอเท็ม (ส่วนประกอบของไอเท็มเมื่อไม่แยแส) และความก้าวหน้าของผู้เล่น เพื่อส่งผ่านข้อความนี้เราจะสร้างคลาส DisenchantMessage ซึ่งจะทำหน้าที่เป็นเนื้อหาสำหรับข้อความนี้ ดังนั้น DisenchantManager จะเติมข้อมูล DisenchantMessage และส่งไปที่ไอเท็ม รายการจะได้รับข้อความและส่งไปยังแอตทริบิวต์ที่แนบทั้งหมด เนื่องจากเมธอด ReceiveMessage ของคลาส Disenchantable จะค้นหา DisenchantMessage เฉพาะแอ็ตทริบิวต์ Disenchantable เท่านั้นที่จะได้รับข้อความนี้และดำเนินการกับมัน หวังว่านี่จะเป็นการล้างสิ่งต่าง ๆ ให้มากที่สุดสำหรับฉัน :)