OK so I developed my own system that basically automatically unequips any weapons that need to be unequipped, when the player is swapping armor or systems out, but there is one minor issue that still exists, and it’s that if I was wielding a weapon and a shield side by side, say a normal sword and a wooden shield, and then I replace them with something… idk… 2-handed or right-handed, something that basically forces both previous items off the players’ hand, the shield visibly stays on the players’ hand, although it is no longer on his equipment system, so it looks something like this:
Needless to say, that shield is not visibly supposed to be there… (and this problem does not occur when I am just unequipping a shield for instance. It only happens when my players’ hands are full)
Can we fix this? Apparently using the ‘Destroy()’ function is not permitted by Unity, as per this error (this is what worked for me earlier in this post, but now it’s not working). After further analysis, I realized that on the hierarchy, the shield is still under the players’ left hand transform, and this is kinda bothering me tbh:
Destroying assets is not permitted to avoid data loss.
If you really want to remove an asset use DestroyImmediate (theObject, true);
UnityEngine.Object:Destroy (UnityEngine.Object)
GameDevTV.Inventories.Equipment:UnequipShieldAndEquipWeapon (GameDevTV.Inventories.Inventory,GameDevTV.Inventories.EquipableItem) (at Assets/GameDev.tv Assets/Scripts/Inventories/Equipment.cs:90)
GameDevTV.Inventories.Equipment:MaxAcceptable (GameDevTV.Inventories.EquipLocation,GameDevTV.Inventories.InventoryItem) (at Assets/GameDev.tv Assets/Scripts/Inventories/Equipment.cs:139)
GameDevTV.UI.Inventories.InventorySlotUI:TryHandleRightClick () (at Assets/GameDev.tv Assets/Scripts/UI/Inventories/InventorySlotUI.cs:98)
UnityEngine.EventSystems.EventSystem:Update ()
And here is my developed code so far, in ‘Equipment.cs’ (I’m posting this here because I seek feedback on ways that we can make this a little better, but generally speaking it seems fine to me. Can we shorten this code a little bit in any way shape or form though, or at least is there something repetitive there that I can eliminate? The main reason I got 2 of what looks like the exact same function, is because of one line at the end that makes all the difference):
public void UnequipWeaponAndEquipShield(Inventory inventory, EquipableItem itemToEquip) {
EquipLocation weaponSlot = EquipLocation.Weapon;
EquipLocation shieldSlot = EquipLocation.Shield;
Equipment playerEquipment = this;
EquipableItem equippedWeapon = playerEquipment.GetItemInSlot(weaponSlot);
EquipableItem equippedShield = playerEquipment.GetItemInSlot(shieldSlot);
if (equippedWeapon != null && inventory.HasSpaceFor(equippedWeapon)) {
inventory.AddToFirstEmptySlot(equippedWeapon, 1);
RemoveItem(weaponSlot);
Destroy(equippedWeapon);
}
if (equippedShield != null && inventory.HasSpaceFor(equippedShield)) {
inventory.AddToFirstEmptySlot(equippedShield, 1);
RemoveItem(shieldSlot);
Destroy(equippedShield);
}
AddItem(shieldSlot, itemToEquip); // Main difference between both functions is in this line
inventory.RemoveItem(itemToEquip, 1);
}
public void UnequipShieldAndEquipWeapon(Inventory inventory, EquipableItem itemToEquip) {
EquipLocation weaponSlot = EquipLocation.Weapon;
EquipLocation shieldSlot = EquipLocation.Shield;
Equipment playerEquipment = this;
EquipableItem equippedWeapon = playerEquipment.GetItemInSlot(weaponSlot);
EquipableItem equippedShield = playerEquipment.GetItemInSlot(shieldSlot);
if (equippedWeapon != null && inventory.HasSpaceFor(equippedWeapon)) {
inventory.AddToFirstEmptySlot(equippedWeapon, 1);
RemoveItem(weaponSlot);
Destroy(equippedWeapon);
}
if (equippedShield != null && inventory.HasSpaceFor(equippedShield)) {
inventory.AddToFirstEmptySlot(equippedShield, 1);
RemoveItem(shieldSlot);
Destroy(equippedShield);
}
AddItem(weaponSlot, itemToEquip); // Main difference between both functions is in this line
inventory.RemoveItem(itemToEquip, 1);
}
public int MaxAcceptable(EquipLocation equipLocation, InventoryItem item)
{
Inventory inventory = GetComponent<Inventory>();
if (item is EquipableItem equipableItem)
{
if (!equipableItem.CanEquip(equipLocation, this)) return 0;
switch (equipLocation)
{
case EquipLocation.Shield:
if (GetItemInSlot(EquipLocation.Weapon) is WeaponConfig weapon)
{
if (weapon == null) {
Debug.Log("No weapon equipped, wearing the shield");
return 1;
}
if (!weapon.isRightHanded) {
Debug.Log($"{weapon} is left handed, not going to wear the shield");
// Unequip that weapon here, and equip the shield
UnequipWeaponAndEquipShield(inventory, equipableItem);
return 0;
}
if (weapon.isTwoHanded) {
Debug.Log($"{weapon} is two-handed, not going to wear the shield");
UnequipWeaponAndEquipShield(inventory, equipableItem);
return 0;
}
Debug.Log($"{weapon} is right-handed, wearing the shield");
return 1;
}
return 1;
case EquipLocation.Weapon:
if (item is WeaponConfig weaponConfig)
{
if (!weaponConfig.isRightHanded) {
UnequipShieldAndEquipWeapon(inventory, weaponConfig);
return 0;
}
if (weaponConfig.isTwoHanded) {
UnequipShieldAndEquipWeapon(inventory, weaponConfig);
// Play the 2h weapon animation here
return 0;
}
return 1;
}
return 1;
default: return 1;
}
}
return 0;
}
Oh, and one last request for something I noticed here. I noticed that the items go to the first slot, but unlike wielding and unwielding weapons, where the replaced weapon goes to the slot of the weapon it’s replacing, this one goes to the first empty slot (which is a result of my own code), and I used that as a temporary placeholder because I forgot which function sends the weapon to be replaced to the replacer’s slot. Which function do we use to get it to replace whatever we have though…? I know it’s a little thing, but to me it makes a difference