0
\$\begingroup\$

I have one script for all my weapons (I have 3 weapons in total) and each of these 3 weapons has 3 different tiers.

I'm currently using a method to set the values, like this:

public void SetTier1Value() { if (weapon1IsActive == true) { damage = 6 fireRate = 18 etc... } if (weapon2IsActive == true) { damage = 5 fireRate = 20 etc... } // and like this for the rest of the weapons and tiers } 

All the weapons and all the tiers will have the same variables, the only difference between them are the values of their stats.

I know that the way that I'm doing stuff is over-complicating a lot.

I want to fix so in the future it's easier to add new weapons and the code in general isn't that bad to change.

What I want from this script is to be able to change the values of the weapon easily by code.

What ways can I do this?

\$\endgroup\$
0

1 Answer 1

1
\$\begingroup\$

It looks like you want to have just a single instance of your weapon class, that can morph on demand into any of your weapons at any upgrade tier. This would more conventionally be solved by having a separate instance for each weapon - say as separate prefabs - and spawning/recycling or activating/deactivating them as the player switches weapons. But if you prefer to keep this single morphable weapon, we can still make it more maintainable like so...

First I'd make a data structure that stores a snapshot of all the stats for a particular upgrade tier:

[System.Serializable] public struct WeaponStats { public float damage; public float fireRate; // Add any other attributes of your weapon that can change with upgrades. } 

Then I'd create an asset that can store the set of upgrade tiers, and possibly other traits, associated with a specific weapon. This can hold an array of these stats.

[CreateAssetMenu(fileName = "NewWeaponProperties.asset", menuName = "Data/Weapon Properties")] public class WeaponProperties : ScriptableObject { public WeaponStats[] upgradeTiers; // Add other stuff that distinguishes your weapon - visual, sounds, etc? } 

The attribute at the top lets you create instances of this class as asset files in your project folder, so you can make one for each weapon, with meaningful names.

Creating a new WeaponProperties asset

Configuring WeaponProperties asset

Your weapon class can then keep track of which set of WeaponProperties it's currently using (ie. which weapon type is active), and what upgrade level it's currently at, from which we can deduce its current stats:

public class Weapon : MonoBehaviour { [SerializeField] WeaponProperties _properties; [SerializeField] int _currentUpgradeLevel; [SerializeField] WeaponStats _currentStats; public void SetUpgradeLevel(int level) { if (level < 0 || level >= _properties.upgradeTiers.Length) { Debug.LogWarning($"Tried to set weapon {name} to non-existent level {level}."); level = Mathf.Clamp(level, 0, _properties.upgradeTiers.Length - 1); } _currentUpgradeLevel = level; _currentStats = _properties.upgradeTiers[_currentUpgradeLevel]; } public void SetWeaponType(WeaponProperties type, int level = -1) { _properties = type; SetUpgradeLevel(level >= 0 ? level : _currentUpgradeLevel); } void Start() { SetUpgradeLevel(_currentUpgradeLevel); } // ...and the rest of your weapon behaviour. } 

Now you can define as many upgrade levels as you want for each weapon type, and you can set them up in the inspector data, instead of hard-coding them into the weapon class individually, and recompiling anytime you want to change them. This makes it much easier to tune your data - even while the game is running - to dial in the values that feel best.

This also makes it easy to experiment with different weapon types: just create a new asset file for the new idea. Didn't work out? Just stop referencing that file, and it won't be included in your build, but you can keep it around in your project folder in case you want to come back to it later. In the meantime, this "dormant" data doesn't clutter your code like a commented-out chunk of your upgrade function.

\$\endgroup\$
2
  • \$\begingroup\$ Wow, that is insanely good, thank you so much. I know I didn't explain myself properly but on the script I have rn I have it the way you said it would be better, by activating/deactivating the weapon according to if the player swaps. So I don't know if that detail will change anything of what you explained. I'll try to implement it soon but so far it sounds insanely efficient \$\endgroup\$ Commented Apr 24, 2021 at 12:45
  • \$\begingroup\$ If you don't need to swap between different weapon types on a single instance, then you can just skip the SetWeaponType() method, and keep only the SetUpgradeLevel instead. \$\endgroup\$ Commented Apr 24, 2021 at 12:48

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.