Setting an asset to an instance of a class in a script

I handle the weapons in my project in a script called PlayerWeapons.cs. The first thing this script does is define a public serializable class (PlayerWeapon) that defines all the variables and functionality, then the PlayerWeapons class that came with the script, which defines a bunch of static instances of weapons. The theory is that if I want to respawn the player or an ai or replace their weapons for whatever reason I can do

PlayerWeapon curweapon = PlayerWeapons.gun

The problem with this is that while I can use these static instances to set all the numerical values, I also need to store the weapon’s mesh and material so that I can swap weapon graphics simply by changing the mesh and material objects in a weaponholder object attached to my player. Assets like these can’t be typed in though, usually I just make them public or add [SerializeField], but if I do that it has to be in an instance of the PlayerWeapons script, meaning I’d have to attatch it to all the objects that might need access to it and manually redefine the variables for each prefab in the inspector, which will get lengthy the more weapons I add.

So that’s a bit confusing but I think I got the question across. Is there a way to specify an asset via code so I can set it directly when I declare the static instances of PlayerWeapon or some other workaround/method of organizing the weapons that I haven’t thought of yet?

You may put a Prefab in the Resources folder, and use Resources.Load () to load it in a static List/Dictionary.
You may also use ScriptableObject to store your Weapons data.