It’s arduous to provide any sensible recommendation from a broad description of the issue, however I assume that your system turned complicated and now it’s arduous to work with it due to the next points:
- lessons turned interconnected
- lessons do a number of issues
- it’s unclear who ought to do what
- it’s unclear how you can work together between lessons
So I’m addressing theses issues right here.
You possibly can look into MV* UI patterns. In brief, they include View, Mannequin and a few intermediate class that is referred to as in a different way for every of them (Controller, ViewModel, Presenter and many others.), giving them the ultimate letter(s). You could not want the complete implementation, however it’s best to not less than cut up your View and your Mannequin.
The construction will be like that:
// Mannequin layer
class Stock {}
// class Gear {}
class Merchandise {}
class ArmorItem : Merchandise {}
class WeaponItem : Merchandise {}
// View layer
class InventoryView : MonoBeahviour{}
class EquipmentView : MonoBeahviour{}
class ArmorItemView : MonoBeahviour{}
class WeaponItemView : MonoBeahviour {}
Invetory
class is aware of its properties and the gadgets it incorporates, e.g.:
class Stock {
readonly Merchandise[] _items = new Merchandise[16];
public int SlotsCount => _items.Size;
public int ItemsCount => _items.The place(merchandise => merchandise != null).Rely();
public void AddItem(int slot, Merchandise merchandise) {}
public void RemoveItem(int slot, Merchandise merchandise) {}
}
it will probably additionally present more information: array of empty slots and many others. It could actually present serialization choices to serialize/deserialize all the info it incorporates. However what it does not know is it is visible illustration. This implies, dragging and many others, is completed individually.
Gear
is the same class with some stricter sort checking. Or it will probably merely does not exist. As an alternative there might be a bool _isEquipped
subject within the Merchandise
class, which might be sufficient.
Merchandise
class is the bottom class for gadgets. Ideally it solely incorporates knowledge and strategies to get and set this knowledge. It could know how you can serialize itself, however it’s in all probability finest to set off serialization from Stock
anyway.
InventoryView
represents the visible state of stock, e.g.
public class InventoryView : MonoBehaviour {
public Label _itemsCount;
public void SetInventory(Stock stock) {
_itemsCount.textual content = stock.ItemsCount;
}
}
this class is accountable for something visible – displaying the present state, animations, dragging, getting person interactions and many others. Ideally, it ought to solely work with Stock
solely, however also can work with Gear
or Objects
straight if wanted. This may enhance the complexity, so it’s best to separate every part as a lot as potential.
In full MV* patterns, the center layer is accountable for getting the mandatory knowledge from the mannequin and providing it to the View
. In different phrases, if Stock
wants a listing of merchandise names, handles tools itself and many others. It would solely work with e.g. InventoryController
that can present knowledge to it, whereas InventoryController
can have entry to Stock
, Gear
and all of the Objects
(by means of Stock strategies or by means of public checklist – does not matter). Why it’s good? As a result of View
incorporates the logic of the visuals and Mannequin
incorporates the logic of the applying. And Controller
does not comprise any logic besides the logic of gathering the info. This makes each class deal with one downside, which makes it simpler to grasp the code
EquipmentView
, ArmorItemView
, WeaponItemView
– are clearly associated to stock. InventoryView
can personal these lessons and work together with them. However it shouldn’t do their job. E.g. it will probably conceal an merchandise within the slot for dragging and spawn an intermediate one, but it surely shouldn’t animate every merchandise and many others.
In full MV* sample View
s can work together with each other through intermediate layer. So, a View
calls a way of its corresponding Controller
, this Controller
calls a way of one other Controller
and that Controller
invokes an occasion
to which its View
is subscribed.
Dragging instance
A person clicks on an merchandise within the stock and holds the clicking. That is recognized both by the ItemView
(wherein case it experiences it to the InventoryView
) or by InventoryView
itself. The ItemView
within the slot is hidden, and the one of many identical measurement and form is spawned above the InventoryView
. The person drags it to someplace and releases.InventoryView
checks the place the discharge occurred. If this was over EquipmentView
it will probably notify the EquipmentView
(whether it is applied) to deal with the case and reply again (so the merchandise within the stock will be eliminated or visually up to date). If that was over a listing slot, it strikes the ItemView
to the correct slot and calls RemoveSlot
and AddSlot
of Stock
with outdated and new slot ids respecively, if no motion is implied – it merely units the visuals again to the unique slot.
Swapping instance
Your case of stock slot and an merchandise in stock slot understanding of one another is not more than an implementation element. It is best to have this data solely in a single place and use it from there. Swapping the gadgets within the above process is not more than taking a slot variety of one slot and the opposite slot and easily swap gadgets. The gadgets shuold know nothing concerning the slot quantity, it is solely InventoryView
and Stock
doing their job of swapping the gadgets. If the info is serialized and/or despatched to server by the stock, slightly than by an merchandise. It actually depends upon the way you manage the system.
Server interplay
For example, we have to replace the state on server. Who does that? It relies upon. E.g. if a number of gamers can use stock collectively – than InventoryView
ought to ship RPCs, so the visuals are in sync. If not, solely Stock
wants requests when it’s up to date.
Who creates who
View
s in Unity are MonoBehaviour
s, nothing particular right here. The remaining will be applied in a different way. Choices are:
- every part will be
MonoBehaviour
s - a
Supervisor
that creates all of the lessons wanted for the stock - singletons, not less than for mannequin layer lessons
- dependency injection
Learn how to name again
C# occasions is probably the most default approach. If now we have a Mannequin
class and a View
class, the mannequin can expose its strategies to be referred to as by View
and C# occasions to which View
can subscribe. This manner, Mannequin
will know nothing about View
wherein case it merely cannot have any presentation logic in any respect. So, logic turns into free from visuals.
There are different methods to work together between lessons with out direct references, with reactive extensions (UniRx or R3) being arguably the perfect and Unity’s SendMessage
being arguably the worst. However all of them are based mostly on both of two concepts: both a subscription, like C# occasions, or that another person ought to deal with the interplay.