Using numbers and letters in an enum

I’m not entirely sure if this is the most accurate way (or place) to ask this question and I will edit it to make it more accurate as I get new info, but I’m doing my best.

I want to make a scriptable object for creating ammo data for firearms in a project of mine. I want to store the data for the caliber of the ammo so I can check if its compatible for mags/guns.

public enum AmmoCaliber
{
    //.300BLK
    //5.56x45
    //7.62x39
    //5.45x39
    //7.62x51
    //9x19
    //.50BMG
    //12 gauge
    //40VOG
    //40x46
}

public enum SpecialEffect
{ 
    Explosive,
    APHE,
    Incendiary,
    TracerRed,
    TracerGreen
}

[CreateAssetMenu(fileName = "Ammo", menuName = "Weapons/Ammo", order = 2)]
public class AmmoData : ScriptableObject
{
    //public AmmoCaliber Caliber;
    public float Damage;
    public float ArmorPiercing;
    public float MuzzleVelocity;
    [NonReorderable]
    public List<SpecialEffect> RoundEffect;
}

I wanted to use an enum for the ammo calibers to make making many new ammo types easier but when i type them down theres an error saying “identifier expected”. I assume the issue is that im trying to have numbers and letters and periods in the enum but id like to store the ammo caliber information this way, what should i do? Id like to still be able to have the ammo calibers be listed with their exact names like “5.56x45” but i dont know if I can name an enum value that.

Use scriptable objects for the calibre, and probably the special effects, too. Avoid enums as much as you can, honestly.

2 Likes

I didnt think to use scriptable objects for the caliber, ill look into how im going to go about doing that. That being said, why should I avoid enums? I dont have an in depth knowledge of programming so theres a good chance im missing something but so far they seem to be helpful.

You’d use scriptable objects for ammo calibre the same way you’d use them for your ammo data. Just an asset to outline the properties of a weapon calibre, that you reference in your ammo data scriptable objects.

As for avoiding enums: the issue is they’re not scalable and they don’t contain any meaningful information on their own. If you want some behaviour that differs based on the calibre of an ammo, you need to do a big if-else chain most likely. With scriptable object (a more object oriented approach), you can simply express the required information in each asset, and pull from that. You can make as many scriptable objects as you want without having to change any code either, too.

They’re really just one tiny step above a raw number, which is what they are underneath.

I still use enums here and there for nice small-scope stuff: a list of states, types, modes, etc, but only if Unity will NEVER see my enum. If only my code touches the enum, no serialization, etc., yeah, I still use them sparingly.

Enums have some extra gotchas in Unity unless you follow strict rules.

Adding onto what Spiney already said:

Enums enums are bad in Unity3D if you intend them to be serialized:

It is much better to use ScriptableObjects for many enumerative uses. You can even define additional associated data with each one of them, and drag them into other parts of your game (scenes, prefabs, other ScriptableObjects) however you like. References remain rock solid even if you rename them, reorder them, reorganize them, etc. They are always connected via the meta file GUID.

Collections / groups of ScriptableObjects can also be loaded en-masse with calls such as Resources.LoadAll<T>();

Best of all, Unity already gives you a built-in filterable picker when you click on the little target dot to the right side of a field of any given type… bonus!

1 Like

okay, that makes sense with the enums. Ill try to use them as little as I can, but I only know so much. Once im finished with my current degree (in robotics) i want to come back and take programming classes for more in-depth programming knowledge, I only took programming in high school and it was pretty surface level.

As for the scriptable objects for ammo caliber, im still not entirely sure im following. Do you mean each ammo caliber would need its own scriptable object?

the way I originally thought I was going to make this happen is on the firearm itself, there would be 2 variables. “AmmoData ChamberedRound” and “AmmoCaliber CombatableAmmoCaliber”. When firing, I was going to do something like
if(ChamberedRound.AmmoCaliber == CompatibleAmmoCaliber) { shoot }
(something along those lines). All the AmmoCaliber Enum was going to be used for was just checking if its compatible ammo. Damage and AP are still stored on AmmoData because there might be more than one round of the same caliber (hollow point, fmj, ap, etc) which would each have different stats and names from one another. I could just store it as an int or something where 1 = 9x19, 2 = 5.56 and so on but that sounds like a pain to keep track of and id rather be able to select the exact ammo caliber when im making creating the asset from the AmmoData.

I appreciate your help here but to be honest, alot of these words are going a bit above my head. enumerative uses? meta file GUID? serialized? I dont think ive gotten quite that far into my programming journey for those words to mean much to me. I understand on a practical level why I shouldnt use enums, unity doesnt play well with them and they arent much better than just using a number, but on the technical level youve described here, i just dont get it, and probably wont without some kind of professional c# education.

You can still do this with scriptable objects by just comparing equality (== operator) between two Unity objects.

And I guess if a gun supports more than one (I don’t know how guns work), you can have a list of scriptable objects, and introduce a boolean method that can be used to determined whether a bullet calibre is compatible.

Edit: And yes, you’d make a scriptable object asset for each calibre, which can contain all information about a bullet calibre.

What you don’t get now will eventually make sense in time. I don’t have any formal programming education but I’ve learnt all this stuff in due time. A lot of what Kurt is mentioning is general advice, and mostly specific to Unity as well. You’ll learn this stuff as it comes.

making a scriptable object asset for each caliber seems like so much more work than just being able to store the caliber as a variable, because I didnt want the caliber itself to store information, i wanted the caliber to be the information being stored. All a bullet’s caliber is, is just the diameter of the bullet. I wont be using an enum for reasons discussed earlier still, but I think i might just do the backup plan of storing caliber information as ints where 1=9x19, 2=5.56 etc.

Also, there are a few firearms that do support multiple different calibers of ammo, but what im more interested in is firearms whos magazines support multiple different types of ammo, but the gun itself doesnt. For example, .300BLK and 5.56 do take the same mags. However, the guns that fire them cannot use the ammo interchangeably. Not really sure what happens if a 5.56 round ends up in a .300blk gun, but i DO know what happens if a .300blk ends up in a 5.56 gun, which is that the gun chambers it correctly, and then the gun explodes when you try to shoot it. I think it would be really cool to have this feature in my project. And that list of the guns compatible ammo types would probably work exactly the same as the mags compatible ammo types so it works out.

and im sure this is true but man its been a real long time since ive wanted to learn programming and a very small amount of progress since. I dont really know what to do to learn this all naturally i guess.

hmm. Although, if I were to try to make each caliber be its own scriptable object, could I make AmmoData an abstract class and make the different calibers inherit from it? For example, for 5.56,

public class AmmoCaliber_556x45 : AmmoData
{

}
public abstract class AmmoData : ScriptableObject
{
    public string AmmoName;
    public float Damage;
    public float ArmorPiercing;
    public float MuzzleVelocity;
    public int Projectiles;//the amount of projectiles in each cartrige 
    [NonReorderable]
    public List<SpecialEffect> RoundEffect;
}

If i had a magazine of this ammo, even if “Public class AmmoCaliber_556x45” didnt have any data specific to it, wouldnt it still have its class name? If so, is it possible to just use its class name to check if its compatible ammo?

I might not be understanding how classes work.

Okay, just to be clear, I’m not talking about a separate class pre calibre. I’m just talking about something like this:

[CreateAssetMenu]
public class AmmoCaliber : ScriptableObject
{
	[SerializeField]
	private Vector2 _dimensions;
	
	public Vector2 Dimensions => _dimensions;
	
	public string CaliberName => $'{_dimensions.x}x{_dimensions.y}";
}

Then you just make instances of this scriptable object as needed, and reference this scriptable object in your AmmoData scriptable object.

We’ll you’re learning stuff now! Just take on what you learn here, and keep doing that, and before long, you’ll have a solid foundation of knowledge.

It does take time. I started learning about 3 and a bit years ago. The first few months was pretty rough, but you eventually hit a point where it starts to come naturally.

1 Like

this makes wayyy more sense now. I didnt understand what you were getting at until now. Not to mention, there are gaps in my programming vocabulary, so to speak. The => and $'name'' are things I dont understand. I swear in programming every key on my keyboard does something special and i never remember what they would do until i see someone elses code

I was able to figure out a rough solution with enums just by changing the wording to something like “Caliber556x45”. i wanted to avoid enums after this discussion, but wanted some temporary solution so i could actually start working on the scripts that would make guns start shooting bullets. thankfully I havent really started on that part so i can go back and change things to use scriptable objects for caliber instead, this time in a way that makes sense.

I havent been really able to consistently learn, its always been off and on with my programming projects, i work on one project for a few months, then get busy with jobs/school/whatever happens that keeps me busy and then i take a few months off, and by the time I come back to it i forget alot, not so much that im starting from 0 but not usually far from it. I think I would benefit from a structured learning environment. Im not gonna stop working on my little side projects but once i have a proper career job ill probably be going back to school for programming, so i can hopefully get the foundational knowledge of programming i feel like i might be missing.

1 Like

I just started learning here: Junior Programmer Pathway - Unity Learn

No point in paying, honestly, until you think you can commit to it. Plenty of free resources too, and to be honest… I’ve not paid a dime when it comes to programming since I started.

1 Like

Ill give it a look, definitely looks promising, thank you!

1 Like

And I suppose for completeness sake I should explain these. Really, in both cases it’s just syntax sugar.

The first is a read-only expression bodied property: Expression-bodied members - C# | Microsoft Learn

The second is a way of concatenating strings: How to concatenate multiple strings - C# | Microsoft Learn

In both cases it’s just syntax that makes things more convenient for us.

1 Like

Just so you know there are a lot of different areas of knowledge here, “buckets” I like to call them.

It isn’t all just “C# programming” or “Unity3D stuff.” There’s how Unity manages assets, how it imports them, how you connect them, etc. When you sense that there’s a gap in your knowledge, don’t instantly stop and freeze. Set aside a gap for that knowledge and finish whatever thought you are working on, for instance in the case above text basically the takeaway is “when in doubt, don’t use enums under Unity.” Everything else is “why.”

When you encounter terms you don’t understand you should timebox the interruption. Yes, it’s always good to look stuff up, certainly for vocabulary reasons, such as “what does meta mean?” and “what is a GUID?” Both of these things have generic meanings and specific meanings, and getting the PRECISE meaning is not always immediately necessary.

Aaaaanyway… here’s more on organizing your learning:

Your programming learning will be (largely) broken into broad areas of knowledge.

You may find these main buckets helpful to organize your learning:

  • C# language syntax (organization, structure, grammar, punctuation)
  • the .NET API (all the tools that come with C#: lists, dictionaries, file IO, etc)
  • the Unity API (everything in the using UnityEngine; namespace)

Beyond that mechanical stuff comes the interesting stuff: how to actually solve real world problems.

And alongside all of this are things like:

  • how to use Unity’s interface
  • how assets are imported
  • how Unity manages assets
  • how Unity connects things

You won’t learn it all at once. You will steadily layer on more and more knowledge as long as you are diligent and pay attention what you are doing.

1 Like