Error after weapon prefabs refactor

After the refactor the game breaks when i try to launch it with this error:

InvalidCastException: Specified cast is not valid.
(wrapper castclass) System.Object.__castclass_with_cache(object,intptr,intptr)
UnityEngine.Object.Instantiate[T] (T original, UnityEngine.Transform parent, System.Boolean worldPositionStays) (at <c2d036c16ca64e0eb93703a3b13e733a>:0)
UnityEngine.Object.Instantiate[T] (T original, UnityEngine.Transform parent) (at <c2d036c16ca64e0eb93703a3b13e733a>:0)
RPG.Combat.WeaponConfig.Spawn (UnityEngine.Transform rightHandTransform, UnityEngine.Transform leftHandTransform, UnityEngine.Animator animator, RPG.Combat.SkeletonType type) (at Assets/Scripts/Combat/WeaponConfig.cs:33)
RPG.Combat.Fighter.SetupDefaultWeapon () (at Assets/Scripts/Combat/Fighter.cs:130)
GameDevTV.Utils.LazyValue`1[T].ForceInit () (at Assets/AssetPacks/GameDev.tv Assets/Scripts/Utils/LazyValue.cs:56)
RPG.Combat.Fighter.Start () (at Assets/Scripts/Combat/Fighter.cs:45)

So, following the call stack (at least to the point where I can reach, inside my scripts), we have line 45 of Fighter, which is inside Fighter.Start, which is

currentWeapon.ForceInit();

currentWeapon being

LazyValue<WeaponConfig> currentWeapon = null;

We then go to internal LazyValue stuff, which I hope it’s not broken because I wouldn’t know where to fix it since I didn’t write it, and we pass to line 130 again in Fighter.

private WeaponConfig SetupDefaultWeapon()
        {
            previousWeapon = defaultWeapon;
            defaultWeapon.Spawn(rightHandTransform, leftHandTransform, animator, skeletonType); //This >           is line 130
            return defaultWeapon;
        }

defaultWeapon being of the correct WeaponConfig type, I checked that.
[SerializeField] private WeaponConfig defaultWeapon = null;

So we finally reach the last call, which is line 33 of WeaponConfig

public void Spawn(Transform rightHandTransform, Transform leftHandTransform, Animator animator, SkeletonType type)
        {
            DestroyOldWeapon(rightHandTransform, leftHandTransform);

            if (equippedWeaponPrefab != null)
            {
                Transform handTransform = GetHandTransform(rightHandTransform, leftHandTransform);

                Weapon weapon = Instantiate(equippedWeaponPrefab[(int)type], handTransform); //this is line   33
                weapon.gameObject.name = WEAPON_NAME;
            }

            AnimatorOverrideController overrideController = animator.runtimeAnimatorController as AnimatorOverrideController;
            if (weaponAnimationOverride != null)
            {
                animator.runtimeAnimatorController = weaponAnimationOverride;
            }
            else if (overrideController != null)
            {
                animator.runtimeAnimatorController = overrideController.runtimeAnimatorController;
            }
        }

This method is a bit more convoluted than what is presented in the course because I’m using a mix of different free low poly models assets rather than the ones provided with the course, or even the rest of the paid package from Sinty. So I came up with the idea to make equippedWeapoPrefab an array of different prefabs tailored to each skeleton, and pass a SkeletonType enum variable so that the method chooses the right one and spawn the weapons in the right place and with the right orientation, because each model does its own thing in those departments. It worked reasonably well up until this moment and anyway it’s not part of the problem, I reckon. For what I can see, all the relevant variables are of the correct type. I’m not casting anything except the SkeletonTpe enum.

The call stack continues to internal Unity stuff that I cannot control whatsoever, so I’m hoping the mistake is somewhere in these bits. If not (like ho suspect), I can’t see how I could start to fix it.

I so far found that the culprit is changing the weaponprefab into a Weapon type. If I revert back to GameObject it does not complain anymore. So I think it’s Instantiate which doesn’t like being passed a Weapon object as prefab.
I’m at a loss, can anyone spot where the mistake is? How to fix it? Thanks!

First of all, GREAT job working through the call stack on the error! This is a skill that is essential in debugging code!

Weapon weapon = Instantiate(equippedWeaponPrefab[(int)type], handTransform);

The weapon declaration is expecting the result of Instantiate to be a weapon. I’m going to go out on a limb and predict that your declaration for equippedWeaponPrefab is

[SerializedField] GameObject[] equippedWeaponPrefab;

There are a couple of possible fixes for this, and they all require some extra work…

  • You can change the declaration to be Weapon[] equippedWeaponPrefab instead of Gameobject, but you’ll find that the inspector breaks, in that you can only drag weapons into the array slot, you can’t use the small selector on the right.
  • You can instantiate as a GameObject, and then use GetComponent() to get the weapon value.
GameObject weaponGo = Instantiate(equippedWeaponPrefab[(int)type]), handTransform);
Weapon weapon = weaponGo.GetComponent<Weapon>(); //Don't forget to return this in Spawn!  You'll need that later!
1 Like

Thanks!
I did change EquipWeaponPrefab to Weapon, but it doesn’t like it anyway. I did reassign prefabs in the inspector when I made the change, and I made sure all the prefabs have a Weapon component (well, since they all derive from the same base Unarmed prefab in my project, they automatically have it once I assigned it to Unarmed). Maybe it’s another case of 2022.3 derping out.
I guess I’ll use GetComponent to work around it for the rest of the course, thanks!

Privacy & Terms