That would do it. Good job getting that sorted!
Iāll leave a note here to other people so that the shield cannot be equipped with dual weaponsā¦(EquipmentSlotUI.cs) Just had to copy the solution for two-handed weapons.
public int MaxAcceptable(InventoryItem item)
{
EquipableItem equipableItem = item as EquipableItem;
if (equipableItem == null) return 0;
if ((equipLocation == EquipLocation.Weapon) && item is WeaponConfig weaponConfig)
{
if (weaponConfig.isTwoHanded && (playerEquipment.GetItemInSlot(EquipLocation.Offhand) != null))
return 0;
if (weaponConfig.isDualWield && (playerEquipment.GetItemInSlot(EquipLocation.Offhand) != null)) // this
return 0;
}
if (equipLocation == EquipLocation.Offhand)
{
EquipableItem mainHand = playerEquipment.GetItemInSlot(EquipLocation.Weapon);
if (mainHand is WeaponConfig mainHandConfig)
{
if (mainHandConfig.isTwoHanded) return 0;
if (mainHandConfig.isDualWield) return 0; //and this
}
}
//The line below only makes sense after completing the Shops and Abilities course
//if (!equipableItem.CanEquip(equipLocation, playerEquipment)) return 0;
if (GetItem() != null) return 0;
return 1;
}
Hello, Iām stuck with one problem, I made armor according to the principle of weapons. All armor slots work correctly spawn and are destroyed. But only the armor on the body does not want to be removed, I just donāt understand what the problem is, the code for all parts is identical. Based on your variant weapon code.
public class ArmorConfig : EquipableItem, IModifierProvider
{
[SerializeField] Armor equippedArmor = null;
[SerializeField] Armor equippedArmor2 = null;
[SerializeField]
Modifier[] additiveModifiers;
[SerializeField]
Modifier[] percentageModifiers;
[System.Serializable]
struct Modifier
{
public Stat stat;
public float value;
}
public enum ArmorVariant { Helmet, Necklace, Body, Trousers, Boots, Gloves}
[SerializeField] ArmorVariant armorVarianter;
const string EquipNameHelmet = "Helmet";
const string EquipNameNecklace = "Necklace";
const string EquipNameBody = "Body";
const string EquipNameTrousers = "Trousers";
const string EquipNameBoots = "Boots";//right
const string EquipNameBootsL = "BootsL";//left
const string EquipNameGloves = "Gloves"; //right
const string EquipNameGlovesL = "GlovesL"; //left
Transform oldEquip;
Transform oldEquip2;
public Armor Spawn(Transform Helmet, Transform Necklace, Transform Body, Transform Trousers, Transform Boots, Transform Left_Boots, Transform Gloves, Transform Left_Gloves)
{
//Debug.Log("Spawn");
DestroyOldArmor(Helmet, Necklace, Body, Trousers, Boots, Left_Boots, Gloves, Left_Gloves);
Armor equipment = null;
Armor equipment2 = null;
if (equippedArmor != null)
{
Transform armorTransform = GetTransform(Helmet, Necklace, Body, Trousers, Boots, Gloves);
Transform armorTransfromDouble = GetDoubleTransfrom(Left_Boots, Left_Gloves);
switch (armorVarianter)
{
case ArmorVariant.Helmet:
equipment = Instantiate(equippedArmor, armorTransform);
equipment.gameObject.name = EquipNameHelmet;
break;
case ArmorVariant.Necklace:
equipment = Instantiate(equippedArmor, armorTransform);
equipment.gameObject.name = EquipNameNecklace;
break;
case ArmorVariant.Body:
equipment = Instantiate(equippedArmor, armorTransform);
equipment.gameObject.name = EquipNameBody;
break;
case ArmorVariant.Trousers:
equipment = Instantiate(equippedArmor, armorTransform);
equipment.gameObject.name = EquipNameTrousers;
break;
case ArmorVariant.Boots:
equipment = Instantiate(equippedArmor, armorTransform);
equipment2 = Instantiate(equippedArmor2, armorTransfromDouble);
equipment.gameObject.name = EquipNameBoots;
equipment2.gameObject.name = EquipNameBootsL;
break;
case ArmorVariant.Gloves:
equipment = Instantiate(equippedArmor, armorTransform);
equipment2 = Instantiate(equippedArmor2, armorTransfromDouble);
equipment2.gameObject.name = EquipNameGlovesL;
equipment.gameObject.name = EquipNameGloves;
break;
}
}
return equipment;
}
private void DestroyOldArmor(Transform Helmet, Transform Necklace, Transform Body, Transform Trousers, Transform Boots, Transform Left_Boots, Transform Gloves, Transform Left_Gloves)
{
switch (armorVarianter)
{
case ArmorVariant.Helmet:
Debug.Log("Destroing Helmet.");
oldEquip = Helmet.Find(EquipNameHelmet);
break;
case ArmorVariant.Necklace:
Debug.Log("Destroing Necklace.");
oldEquip = Necklace.Find(EquipNameNecklace);
break;
case ArmorVariant.Body:
Debug.LogWarning("Destroing Body???");
oldEquip = Body.Find(EquipNameBody);
break;
case ArmorVariant.Trousers:
Debug.Log("Destroing Trousers.");
oldEquip = Trousers.Find(EquipNameTrousers);
break;
case ArmorVariant.Boots:
Debug.Log("Destroing Boots.");
oldEquip = Boots.Find(EquipNameBoots);
oldEquip2 = Left_Boots.Find(EquipNameBootsL);
break;
case ArmorVariant.Gloves:
Debug.Log("Destroing Gloves.");
oldEquip = Gloves.Find(EquipNameGloves);
oldEquip2 = Left_Gloves.Find(EquipNameGlovesL);
break;
}
if (oldEquip == null) return;
if (oldEquip2 != null)
{
oldEquip2.name = "DESTROYING2";
Destroy(oldEquip2.gameObject);
}
oldEquip.name = "DESTROYING";
Destroy(oldEquip.gameObject);
}
private Transform GetDoubleTransfrom(Transform L_Boots, Transform L_Gloves)
{
if (armorVarianter == ArmorVariant.Boots) return L_Boots;
if (armorVarianter == ArmorVariant.Gloves) return L_Gloves;
else return null;
}
private Transform GetTransform(Transform Helmet, Transform Necklace, Transform Body, Transform Trousers, Transform Boots, Transform Gloves)
{
//Transform armorTransform;
if (armorVarianter == ArmorVariant.Helmet) return Helmet;
if (armorVarianter == ArmorVariant.Necklace) return Necklace;
if (armorVarianter == ArmorVariant.Body) return Body;
if (armorVarianter == ArmorVariant.Trousers) return Trousers;
if (armorVarianter == ArmorVariant.Boots) return Boots;
if (armorVarianter == ArmorVariant.Gloves) return Gloves;
else return null;
}
public IEnumerable<float> GetAdditiveModifiers(Stat stat)
{
foreach (var modifier in additiveModifiers)
{
if (modifier.stat == stat)
{
yield return modifier.value;
}
}
}
public IEnumerable<float> GetPercentageModifiers(Stat stat)
{
foreach (var modifier in percentageModifiers)
{
if (modifier.stat == stat)
{
yield return modifier.value;
}
}
}
}
Honestly, Iām not sure. The code is identical between the different locations. Is the body armor being renamed to DESTROYING?
Now Iām completely confused, I didnāt change anything at all, Yesterday only the armor on the body did not work, now everything is not removedā¦ And the helmet does not even spawn, itās absurdā¦ No, no renamedā¦
I will write all parts of the armor scriptā¦
Fighter.cs
public class Fighter : MonoBehaviour, IAction
{
[SerializeField] Transform armorTransformHelmet = null;
[SerializeField] Transform armorTransformNecklace = null;
[SerializeField] Transform armorTransformBody = null;
[SerializeField] Transform armorTransformTrousers = null;
[SerializeField] Transform armorTransformBoots_Left = null;
[SerializeField] Transform armorTransformBoots_Right = null;
[SerializeField] Transform armorTransformGloves_Left = null;
[SerializeField] Transform armorTransformGloves_Right = null;
[SerializeField] ArmorConfig defaultarmorHelmet = null;
[SerializeField] ArmorConfig defaultarmorNecklace = null;
[SerializeField] ArmorConfig defaultarmorBody = null;
[SerializeField] ArmorConfig defaultarmorTrousers = null;
[SerializeField] ArmorConfig defaultarmorBoots = null;
[SerializeField] ArmorConfig defaultarmorGloves = null;
ArmorConfig currentArmorConfig;
LazyValue<Armor> currentArmor;
private void Awake()
{
currentArmorConfig = defaultarmorHelmet;
currentArmor = new LazyValue<Armor>(SetupDefaultArmor);
equipment = GetComponent<Equipment>();
if (equipment)
{
equipment.equipmentUpdated += UpdateWeapon;
equipment.equipmentUpdated += UpdateEquipment;
}
}
//armor
private Armor SetupDefaultArmor()
{
return AttachArmor(defaultarmorHelmet);
}
public void EquipArmor(ArmorConfig armor)
{
currentArmorConfig = armor;
currentArmor.value = AttachArmor(armor);
}
private Armor AttachArmor(ArmorConfig armor)
{
return armor.Spawn(armorTransformHelmet, armorTransformNecklace, armorTransformBody, armorTransformTrousers, armorTransformBoots_Left, armorTransformBoots_Right, armorTransformGloves_Right, armorTransformGloves_Left);
}
public void UpdateEquipment()
{
var Helmet = equipment.GetItemInSlot(EquipLocation.Helmet) as ArmorConfig;
var Body = equipment.GetItemInSlot(EquipLocation.Body) as ArmorConfig;
var Trousers = equipment.GetItemInSlot(EquipLocation.Trousers) as ArmorConfig;
var Boots = equipment.GetItemInSlot(EquipLocation.Boots) as ArmorConfig;
var Gloves = equipment.GetItemInSlot(EquipLocation.Gloves) as ArmorConfig;
var Necklace = equipment.GetItemInSlot(EquipLocation.Necklace) as ArmorConfig;
if (Helmet == null) EquipArmor(defaultarmorHelmet);
else EquipArmor(Helmet);
if (Body == null) EquipArmor(defaultarmorBody);
else EquipArmor(Body);
if (Trousers == null) EquipArmor(defaultarmorTrousers);
else EquipArmor(Trousers);
if (Boots == null) EquipArmor(defaultarmorBoots);
else EquipArmor(Boots);
if (Gloves == null) EquipArmor(defaultarmorGloves);
else EquipArmor(Gloves);
if (Necklace == null) EquipArmor(defaultarmorNecklace);
else EquipArmor(Necklace);
}
One thing I didnāt enquire aboutā¦ as most armor systems (like the Synty Modular Hero Set or InfinityPBRās Armor system) actually use individual skinned mesh components that are all set up to work with the skeleton, and components are added/removed by activating/deactivating those componentsā¦ Is this system a collection of armor that is attached to the skeleton, or is it more like what I just described?
Fully weapon system principle, same spawn.
All parts of the armor are separate objects. These parts are tied to body parts. And I didnāt use skeleton animation.
Iām not seeing a reason these wouldnāt be spawning/unspawning from the code presented. I would probably refactor this a bit, howeverā¦
private void DestroyOldArmor(Transform slot, string armorName)
{
var oldItem = slot.Find(armorName);
if(oldItem)
{
oldItem.Name = "DESTROYING";
Destroy(oldItem);
}
}
private Armor Spawn(Transform slot, string itemName, bool equip2 = false)
{
if(!slot)
{
Debug.Log($"Attemping to spawn slot {itemName}, but no transform is defined");
return null;
}
DestroyOldArmor(slot, itemName);
var ItemToInstantiate = equip2? equippedArmor2:equippedArmor;
Armor armor = Instantiate(ItemToInstantiate, slot);
armor.name = itemName;
return armor;
}
public Armor Spawn(Transform Helmet, Transform Necklace, Transform Body, Transform Trousers, Transform Boots, Transform Left_Boots, Transform Gloves, Transform Left_Gloves);
{
switch(armorVarianter)
case ArmorVariant.Helmet:
return Spawn(Helmet, EquipNameHelmet);
case ArmorVariant.Necklace:
return Spawn(Necklace, EquipNameNecklace);
case ArmorVariant.Body:
return Spawn(Body, EquipNameBody);
case ArmorVariant.Trousers:
return Spawn(Trousers, EquipNameTrousers;
case ArmorVariant.Boots:
Spawn(Left_Boots, EquipNameBootsL, true); //spawns left boot
return Spawn(Boots, EquipNameBoots);
case ArmorVariant.Gloves:
Spawn(Left_Gloves, EquipNameGlovesL, true);
return Spawn(Gloves, EquipNameGloves);
}
Tried to change to your version, still does not work completely. I just canāt figure out what to doā¦
Iām sorry to bother you so muchā¦
The weapon just now stopped working, after the changes.
āThe Object you want to instantiate is nullā
This would seem to indicate that in one or more of your ArmorConfig instances, the equippedArmor or equippedArmor2 is nullā¦
Add this to Armor.Spawn (the private one with the single transform and string)
if(equippedArmor==null)
{
Debug.Log($"Armor {name} is trying to equip an {itemName}, but does not have an equippedArmor assigned.");
return null;
}
if(equip2 && equippedArmor2==null)
{
Debug.Log($"Armor {name} is trying to equip {itemName}, but has no equippedArmor2 assigned");
return null;
}
Thanks, Spawn now work, but destroing no work and no renamed to āDESTROYINGāā¦
When the items are spawned, are they being renamed to the itemName?
Yes, items renamed to the itemName, maybe after ranamed no work find this item?
That is, I believe, the problem. What Iām unsure of is why.
Letās make a brute force method to try to ensure that the item is found:
private Transform FindByName(Transform slot, string nameToFind)
{
foreach(Transform child in slot)
{
if(child.name == nameToFind) return child;
}
return null;
}
Then replace
var oldItem = slot.Find(armorName);
with
var oldItem = FindByName(slot, armorName);
Itās all strangeā¦
public class ArmorConfig : EquipableItem, IModifierProvider
{
[SerializeField] Armor equippedArmor = null;
[SerializeField] Armor equippedArmor2 = null;
[SerializeField]
Modifier[] additiveModifiers;
[SerializeField]
Modifier[] percentageModifiers;
[System.Serializable]
struct Modifier
{
public Stat stat;
public float value;
}
public enum ArmorVariant { Helmet, Necklace, Body, Trousers, Boots, Gloves}
[SerializeField] ArmorVariant armorVarianter;
const string EquipNameHelmet = "Helmet";
const string EquipNameNecklace = "Necklace";
const string EquipNameBody = "Body";
const string EquipNameTrousers = "Trousers";
const string EquipNameBoots = "Boots";//right
const string EquipNameBootsL = "BootsL";//left
const string EquipNameGloves = "Gloves"; //right
const string EquipNameGlovesL = "GlovesL"; //left
Transform oldEquip;
Transform oldEquip2;
private Armor Spawn(Transform slot, string itemName, bool equip2 = false)
{
if (!slot)
{
Debug.Log($"Attemping to spawn slot {itemName}, but no transform is defined");
return null;
}
if (equippedArmor == null)
{
Debug.Log($"Armor {name} is trying to equip an {itemName}, but does not have an equippedArmor assigned.");
return null;
}
if (equip2 && equippedArmor2 == null)
{
Debug.Log($"Armor {name} is trying to equip {itemName}, but has no equippedArmor2 assigned");
return null;
}
DestroyOldArmor(slot, itemName);
var ItemToInstantiate = equip2 ? equippedArmor2 : equippedArmor;
Armor armor = Instantiate(ItemToInstantiate, slot);
armor.name = itemName;
return armor;
}
public Armor Spawn(Transform Helmet, Transform Necklace, Transform Body, Transform Trousers, Transform Boots, Transform Left_Boots, Transform Gloves, Transform Left_Gloves)
{
switch (armorVarianter) {
case ArmorVariant.Helmet:
return Spawn(Helmet, EquipNameHelmet);
case ArmorVariant.Necklace:
return Spawn(Necklace, EquipNameNecklace);
case ArmorVariant.Body:
return Spawn(Body, EquipNameBody);
case ArmorVariant.Trousers:
return Spawn(Trousers, EquipNameTrousers);
case ArmorVariant.Boots:
Spawn(Left_Boots, EquipNameBootsL, true); //spawns left boot
return Spawn(Boots, EquipNameBoots);
case ArmorVariant.Gloves:
Spawn(Left_Gloves, EquipNameGlovesL, true);
return Spawn(Gloves, EquipNameGloves);
}
return null;
}
private Transform FindByName(Transform slot, string nameToFind)
{
foreach (Transform child in slot)
{
if (child.name == nameToFind) return child;
}
return null;
}
private void DestroyOldArmor(Transform slot, string armorName)
{
var oldItem = FindByName(slot, armorName);
if (oldItem)
{
oldItem.name = "DESTROYING";
Destroy(oldItem.gameObject);
}
}
public IEnumerable<float> GetAdditiveModifiers(Stat stat)
{
foreach (var modifier in additiveModifiers)
{
if (modifier.stat == stat)
{
yield return modifier.value;
}
}
}
public IEnumerable<float> GetPercentageModifiers(Stat stat)
{
foreach (var modifier in percentageModifiers)
{
if (modifier.stat == stat)
{
yield return modifier.value;
}
}
}
}
public class Fighter : MonoBehaviour, IAction
{
[SerializeField] float timeBetweenAttacks = 1f;
[SerializeField] Transform rightHandTransform = null;
[SerializeField] Transform leftHandTransform = null;
[SerializeField] WeaponConfig defaultWeapon = null;
[SerializeField] ShieldConfig defaultShield = null;
[SerializeField] float autoAttackRange = 4f;
//armor
[SerializeField] Transform armorTransformHelmet = null;
[SerializeField] Transform armorTransformNecklace = null;
[SerializeField] Transform armorTransformBody = null;
[SerializeField] Transform armorTransformTrousers = null;
[SerializeField] Transform armorTransformBoots_Left = null;
[SerializeField] Transform armorTransformBoots_Right = null;
[SerializeField] Transform armorTransformGloves_Left = null;
[SerializeField] Transform armorTransformGloves_Right = null;
[SerializeField] ArmorConfig defaultarmorHelmet = null;
[SerializeField] ArmorConfig defaultarmorNecklace = null;
[SerializeField] ArmorConfig defaultarmorBody = null;
[SerializeField] ArmorConfig defaultarmorTrousers = null;
[SerializeField] ArmorConfig defaultarmorBoots = null;
[SerializeField] ArmorConfig defaultarmorGloves = null;
ArmorConfig currentArmorConfig;
LazyValue<Armor> currentArmor;
//armor
Health target;
Equipment equipment;
float timeSinceLastAttack = Mathf.Infinity;
WeaponConfig currentWeaponConfig;
LazyValue<Weapon> currentWeapon;
ShieldConfig currentShield;
LazyValue<Shield> currentEquippedShield;
private void Awake()
{
currentArmorConfig = defaultarmorHelmet;
currentArmor = new LazyValue<Armor>(SetupDefaultArmor);
currentWeaponConfig = defaultWeapon;
currentWeapon = new LazyValue<Weapon>(SetupDefaultWeapon);
currentShield = defaultShield;
currentEquippedShield = new LazyValue<Shield>(null);
equipment = GetComponent<Equipment>();
if (equipment)
{
equipment.equipmentUpdated += UpdateWeapon;
equipment.equipmentUpdated += UpdateEquipment;
}
}
//armor
private Armor SetupDefaultArmor()
{
return AttachArmor(defaultarmorHelmet);
}
public void EquipArmor(ArmorConfig armor)
{
currentArmorConfig = armor;
currentArmor.value = AttachArmor(armor);
}
private Armor AttachArmor(ArmorConfig armor)
{
//Debug.Log("AttachArmor");
return armor.Spawn(armorTransformHelmet, armorTransformNecklace, armorTransformBody, armorTransformTrousers, armorTransformBoots_Left, armorTransformBoots_Right, armorTransformGloves_Right, armorTransformGloves_Left);
}
public void UpdateEquipment()
{
var Helmet = equipment.GetItemInSlot(EquipLocation.Helmet) as ArmorConfig;
var Body = equipment.GetItemInSlot(EquipLocation.Body) as ArmorConfig;
var Trousers = equipment.GetItemInSlot(EquipLocation.Trousers) as ArmorConfig;
var Boots = equipment.GetItemInSlot(EquipLocation.Boots) as ArmorConfig;
var Gloves = equipment.GetItemInSlot(EquipLocation.Gloves) as ArmorConfig;
var Necklace = equipment.GetItemInSlot(EquipLocation.Necklace) as ArmorConfig;
if (Helmet == null) EquipArmor(defaultarmorHelmet);
else EquipArmor(Helmet);
if (Body == null) EquipArmor(defaultarmorBody);
else EquipArmor(Body);
if (Trousers == null) EquipArmor(defaultarmorTrousers);
else EquipArmor(Trousers);
if (Boots == null) EquipArmor(defaultarmorBoots);
else EquipArmor(Boots);
if (Gloves == null) EquipArmor(defaultarmorGloves);
else EquipArmor(Gloves);
if (Necklace == null) EquipArmor(defaultarmorNecklace);
else EquipArmor(Necklace);
}
//armor
}
Letās modify this a bit to see what information weāre getting from the FindByName
private Transform FindByName(Transform slot, string nameToFind)
{
Debug.Log($"{name} removing existing {nameToFind} from {slot}");
foreach (Transform child in slot)
{
Debug.Log($"Testing child {child.name} against {nameToFind}");
if (child.name == nameToFind) return child;
}
return null;
}
If you install a different helmet, does the old one remain with the new one?
It occurs to me, we may not even be attempting to unequip the item in the first place if it is dragged awayā¦
With the weapon, if you drag away the sword, then the default weapon of Unarmored is generally spawned in itās placeā¦ thatās a WeaponConfig with a blank GameObject (just the Weapon script, no model).
Are you checking to see if the slot is now empty, and if so, equipping an āunarmoredā/empty WeaponConfg?
No, the old one is destroy, the new one is spawn.
Now i will try checking.
So hereās what I believe is happeningā¦ if your default equipment is null, then nothing is telling the old armor (or weapon) to destroy itselfā¦
For each armor slot, create an Unarmored type ArmorConfigā¦ So an UnarmoredHelment, UnarmoredNecklace, UnarmoredBody, etc.
In those Unarmored configs, fill everything out as far as ArmorVariant, and fill the needed Armor fields with Armor Prefabs with no models in them. You wonāt need the models for this.
Then in every characterās defaultarmorxxx field, put the appropriate Unarmored ArmorConfig.
Now when you remove a piece of armor, but donāt replace it, it should despawn correctly.