Tujuan saya adalah untuk membuat sistem item modular / generik mungkin yang dapat menangani hal-hal seperti:
- Barang yang Dapat Diupgrade (+6 Katana)
- Stat Modifiers (+15 dexterity)
- Item Modifiers (% X kemungkinan untuk melakukan kerusakan Y, kesempatan untuk membekukan)
- Item yang Dapat Diisi Ulang (Staf ajaib dengan 30 penggunaan)
- Set Items (Equip 4 piece of X set untuk mengaktifkan fitur Y)
- Kelangkaan (umum, unik, legendaris)
- Disenchantable (pecah menjadi beberapa bahan kerajinan)
- Craftable (bisa dibuat dengan bahan tertentu)
- Konsumsi (daya serangan 5 menit% X, sembuhkan +15 hp)
* Saya dapat menyelesaikan fitur-fitur yang berani dalam pengaturan berikut.
Sekarang saya mencoba menambahkan banyak opsi kepada kami untuk mencerminkan apa yang ada dalam pikiran saya. Saya tidak berencana untuk menambahkan semua fitur ini yang diperlukan, tetapi saya ingin dapat mengimplementasikannya sesuai keinginan saya. Ini juga harus kompatibel dengan sistem inventaris dan serialisasi data.
Saya berencana untuk tidak menggunakan warisan sama sekali tetapi pendekatan entitas-komponen / data didorong. Awalnya saya memikirkan sebuah sistem yang memiliki:
- BaseStat: kelas generik yang menyimpan statistik saat bepergian (dapat digunakan untuk item dan statistik karakter juga)
- Item: kelas yang menyimpan data seperti daftar, nama, jenis barang dan hal-hal yang terkait dengan ui, actionName, deskripsi, dll.
- IWeapon: antarmuka untuk senjata. Setiap senjata akan memiliki kelasnya sendiri dengan IWeapon diimplementasikan. Ini akan memiliki Attack dan referensi ke statistik karakter. Ketika senjata dilengkapi, datanya (Item class 'stat) akan disuntikkan ke dalam stat karakter (apa pun BaseStat yang dimilikinya, itu akan ditambahkan ke kelas karakter sebagai bonus Stat) Jadi misalnya, kami ingin menghasilkan pedang (berpikir untuk menghasilkan kelas item dengan json) sehingga pedang akan menambah 5 serangan ke statistik karakter. Jadi kita memiliki BaseStat sebagai ("Serangan", 5) (kita juga bisa menggunakan enum). Stat ini akan ditambahkan ke stat "Serangan" karakter sebagai BonusStat (yang akan menjadi kelas yang berbeda) setelah melengkapi itu. Jadi kelas bernama Sword mengimplementasikan IWeapon akan dibuat saat ituKelas Barang dibuat. Jadi kita bisa menyuntikkan statistik karakter ke pedang ini dan ketika menyerang, ia dapat mengambil statistik Serangan total dari statistik karakter dan menimbulkan kerusakan dalam metode Serangan.
- BonusStat: adalah cara menambahkan statistik sebagai bonus tanpa menyentuh BaseStat.
- Dapat dikonsumsi: Logika yang sama dengan IWeapon. Menambahkan stat langsung cukup mudah (+15 hp) tapi saya tidak yakin tentang menambahkan senjata sementara dengan pengaturan ini (% x untuk menyerang selama 5 menit).
- IUpgradeable: Ini dapat diimplementasikan dengan pengaturan ini. Saya berpikir UpgradeLevel sebagai stat dasar, yang ditingkatkan setelah meningkatkan senjata. Ketika ditingkatkan, kita dapat menghitung ulang BaseStat senjata untuk mencocokkan tingkat Upgrade nya.
Sampai titik ini, saya dapat melihat bahwa sistem itu cukup baik. Tetapi untuk fitur lain, saya pikir kita perlu sesuatu yang lain, karena misalnya saya tidak dapat mengimplementasikan fitur Craftable ke ini karena BaseStat saya tidak akan dapat menangani fitur ini dan ini adalah di mana saya terjebak. Saya bisa menambahkan semua bahan sebagai Stat tetapi itu tidak masuk akal.
Agar mudah bagi Anda untuk berkontribusi ini, berikut adalah beberapa pertanyaan yang dapat Anda bantu:
- Haruskah saya melanjutkan pengaturan ini untuk mengimplementasikan fitur lain? Apakah mungkin tanpa warisan?
- Apakah ada cara yang dapat Anda pikirkan, untuk mengimplementasikan semua fitur ini tanpa warisan?
- Tentang Item Modifiers, bagaimana seseorang bisa mencapai itu? Karena sifatnya yang sangat generik.
- Apa yang bisa dilakukan untuk mempermudah proses membangun arsitektur semacam ini, rekomendasi apa saja?
- Apakah ada sumber yang bisa saya gali yang terkait dengan masalah ini?
- Saya benar-benar mencoba untuk menghindari warisan, tetapi apakah Anda pikir ini akan diselesaikan / dicapai dengan warisan dengan mudah sambil menjaganya agar tetap dipertahankan?
Jangan ragu untuk menjawab hanya satu pertanyaan karena saya menyimpan pertanyaan yang sangat luas sehingga saya bisa mendapatkan pengetahuan dari berbagai aspek / orang.
EDIT
Mengikuti jawaban @ jjimenezg93, saya membuat sistem yang sangat mendasar dalam C # untuk pengujian, itu berhasil! Lihat apakah Anda dapat menambahkan apa pun ke dalamnya:
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);
}
Sejauh ini, IItem dan IAttribute adalah antarmuka dasar. Tidak perlu (yang dapat saya pikirkan) untuk memiliki antarmuka dasar / atribut untuk pesan, jadi kami akan langsung membuat kelas pesan uji. Sekarang untuk kelas tes:
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);
}
}
Ini adalah pengaturan yang diperlukan. Sekarang kita dapat menggunakan sistem (Berikut adalah untuk Persatuan).
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);
}
}
Lampirkan skrip TestManager ini ke komponen dalam adegan dan Anda dapat melihat di debug bahwa pesan berhasil diteruskan.
Untuk menjelaskan hal-hal: Setiap item dalam game akan menerapkan antarmuka IItem dan setiap Atribut (nama tidak boleh membingungkan Anda, itu berarti fitur / sistem item. Seperti yang Dapat Diperbaharui, atau disenchantable) akan menerapkan IAttribute. Kemudian kita memiliki metode untuk memproses pesan (mengapa kita membutuhkan pesan akan dijelaskan dalam contoh lebih lanjut). Jadi dalam konteksnya, Anda dapat melampirkan atribut ke suatu item dan membiarkan sisanya melakukan untuk Anda. Yang sangat fleksibel, karena Anda dapat menambah / menghapus atribut dengan mudah. Jadi contoh-pseudo akan Disenchantable. Kami akan memiliki kelas yang disebut Disenchantable (IAttribute) dan dalam metode Disenchant, ia akan meminta:
- Daftar bahan-bahan (ketika item dibubarkan, item apa yang harus diberikan kepada pemain) catatan: IItem harus diperluas untuk memiliki ItemType, ItemID dll.
- int resultModifier (jika Anda menerapkan semacam boost fitur disenchant, Anda dapat melewatkan int di sini untuk meningkatkan bahan yang diterima saat disenchanted)
- int failureChance (jika proses disenchant memiliki peluang kegagalan)
dll.
Informasi ini akan disediakan oleh kelas yang disebut DisenchantManager, ia akan menerima item dan membentuk pesan ini sesuai dengan item (bahan dari item ketika disenchanted) dan perkembangan pemain (resultModifier and failureChance). Untuk meneruskan pesan ini, kami akan membuat kelas DisenchantMessage, yang akan bertindak sebagai badan untuk pesan ini. Jadi DisenchantManager akan mengisi DisenchantMessage dan mengirimkannya ke item. Item akan menerima pesan dan meneruskannya ke semua Attribut yang dilampirkan. Karena metode ReceiveMessage kelas Disenchantable akan mencari DisenchantMessage, hanya atribut Disenchantable yang akan menerima pesan ini dan menindaklanjutinya. Semoga ini mengosongkan hal-hal seperti yang terjadi pada saya :).