Jump to content
  • Advertisement
Sign in to follow this  
Vanderry

Unity [C++] Proper enum usage

This topic is 3046 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello GameDevs ! I really love the clear visualization of enums but I'm not entirely sure how it should be used properly. What I see is an opportunity to manage indices with easily editable text labels, so what I've done is declare enums for things like for instance in my application "error message grades".
enum ERRORGRADE
{
	NONCRITICAL,	// Does not terminate the program
	TERMINATE,		// Terminates the program
	TERMINATEANDMSG	// Terminates the program and shows a message box
};

The declaration is stored within the header file for the CError class, and whenever I call the method Error I pass the enum element appropriate for the specific error.
void Error( std::string file, int line, ERRORGRADE grade, std::string text1 = "", std::string text2 = "" );

Now to the actual "problem". I am able to pass the elements by themselves without any hassle, but I would very much like to be explicit and pass the argument as such ERRORGRADE::NONCRITICAL to avoid passing a bad keyword (i.e. accidently using an element from a different enum). This always results in a warning in Visual Studio 2008 (warning C4482: nonstandard extension used: enum 'ERRORGRADE' used in qualified name) and it looks very bad after a whole lot of function calls. So my question is: am I using enumerators in a proper way and is there some way to call the elements through the enum scope without getting all those warnings? Many thanks in advance ! - Dave

Share this post


Link to post
Share on other sites
Advertisement
The way you are using enums now is fine. Think of them as defining a type for which its values are from a finite set of distinct elements that are explicitly enumerated.

For your second question, enums do not have their own scope. You could put them inside another scope (like a class's), or use a namespace instead (with the side-effect of it requiring a slightly longer identifier for the type):


namespace ErrorGrade {
enum Enum {
NONCRITICAL, // Does not terminate the program
TERMINATE, // Terminates the program
TERMINATEANDMSG // Terminates the program and shows a message box
};
}

ErrorGrade::Enum grade = ErrorGrade::TERMINATE;

Share this post


Link to post
Share on other sites
I'm fairly sure this is a problem they are addressing in C++0x. Right now enums aren't even type-safe, so I presume they would add something like scope resolution for enum members.

Share this post


Link to post
Share on other sites
Quote:
Original post by Normandy
I'm fairly sure this is a problem they are addressing in C++0x. Right now enums aren't even type-safe, so I presume they would add something like scope resolution for enum members.

C++0x doesn't fix the issue, it just sidesteps the issue by introducing a new type of enumeration, the "enum class" type. The enum class type is type safe, although you can use explicit casting to convert to integral type..

Share this post


Link to post
Share on other sites
Enum to int mapping is conceptually undefined, even though many languages support one way or another. Enum 'ERROR' is just that - 'ERROR'. If you choose to assign it a numeric value, the mapping is up to you. Enums conceptually also do not have relation between values. ERROR is different from WARNING, yet neither is greater as far as enums go.

Even without taking C++'s int/enum equivalence, your use of enums is not suitable for the purpose.

IMHO, the following is how the API should be used in this particular case:

void Error( std::string file, int line, std::string text1 = "", std::string text2 = "", ErrorGrade g = ErrorGrade::None );

...

Error("File.cpp", 17, "", "");
Error("File.cpp", 17, "", ErrorGrade::Terminate);
Error("File.cpp", 17, "", ErrorGrade::Terminate || ErrorGrade::MessageBox);


How the above is implemented depends. Values could be simple ints, or they could be more complex classes. The ErrorGrade above can be polymorphic as well, implementing the error behavior by itself. This design is more representative for values which can be combined (noncritical = 00, terminate = 01, terminate+box = 11, consequently just box = 10).

Alternatively, if grades are ordered, then providing a wrapper that defines order, as well as strong type safety will be better solution.

Given real world use, I'm consistently disappointed with enums and can't think of many uses for them, even in other languages. They reek too much of hardcoding. If they define functionality, then there are other ways to implement it (polymorphism, parameters). If they define data, then the data will often be best served from outside. And if for error or labeling, then const int values do the job, even if wrapped in some class.

Share this post


Link to post
Share on other sites
Quote:
Original post by Antheus
And if for error or labeling, then const int values do the job, even if wrapped in some class.


But...an enum IS an integer! It just gives a cute name for a number. People forget numbers, names not so quickly. It's actually really handy, the enum, though its a pity that C++ seems to go so difficult about it. I have to do a lot of casting when I add an integer to an enum value. Also the way we can't define the type for the integer is a pity, as well as it's not encapsulated like a class.

I do agree that most uses of enums are best from outside, though I still prefer something that names my integers. Would be better if we could 'append' enums too, where all elements of 2 enums have unique values. In other words, make it easy for library users to extend, for example add new events. Sure, you can start from the end of the last, but what if you have 3 enums? Just getting garbage.

If 'TERMINATEANDMSG' equals 2, then why is 'TERMINATEANDMSG' - 1 not just 1 and thus 'TERMINATE'? Because it is, except that C++ wants you to add a bunch of needless castings.

Share this post


Link to post
Share on other sites
Quote:
Original post by Decrius
But...an enum IS an integer!
Nope, an enum is just a name. That C/C++ choose to implement them in terms of integers is immaterial.
Quote:
It just gives a cute name for a number.
Nope, as Antheus already mentioned, const int is how one applies a cute name to a number in C/C++.
Quote:
***truncated***
And those are all problems which using const int instead of enum solves in one fell swoop.

Share this post


Link to post
Share on other sites
Quote:
Original post by Decrius

It just gives a cute name for a number. People forget numbers, names not so quickly.


As soon as you introduce ordering or treat them as ordinal types, you open a new can of bugs. Such as: ERROR + WARNING = FILE_NOT_FOUND, while WARNING * ERROR = EXIT and EXIT - FILE_NOT_FOUND + WARNING = DEFAULT.

And if treating them as bitmasks, the following problems arise:

LEFT,
RIGHT,
TOP,
BOTTOM,
LEFT_BUTTON,
RIGHT_BUTTON
DEVICE_OFF

Left, right, top, bottom is the direction of stick.
Buttons can be pressed at any time.
Device off means other values must be 0 or unspecified.

But this is what one uses in actual design, and enums fail to address any of those issues.

Share this post


Link to post
Share on other sites
Working on reasonably old code here (15 or so years in some places), and there are many places where plain integers are passed to and returned from functions to indicate things, with a (usually) outdated, incorrect comment explaining what that value meant there. Sometimes 2 or 3 values are used for the same thing, and sometimes the same value is used more than once for different things.

Replacing those with enums (NOT const ints) has been very helpful because now when building the compiler gives me errors when just passing in integers, and some well-hidden bugs are being removed. Though not completely type-safe, just the fact that it doesn't let ints pretend to be enums (without some explicit casting), and the choices are limited to only what's valid, (and can't use cross-enums either) has been very, VERY helpful. With hundreds, maybe thousands of constant identifiers (whether #defined or const int'ed or enumed) it's also very helpful to know which set of identifiers I will be choosing from, rather than try to decypher a bunch of code and #defines which are poorly named in the first place.

These are cases where the actual value of the identifier is really irrelevant, but they just need to be unique. And we don't want to use a CompressionType where we want to know which HlsBand we are using. Are these not good candidates for enums??

Share this post


Link to post
Share on other sites
Well, talking on the usage side of things:
There are almost always alternatives to the usage of named integers or enumerations.

The question becomes: Is it worth it? In the end the answer is "sometimes yes, sometimes no." More succinctly: "Maybe."

This depends heavily on your current design, on the goals of your project, on the technologies employed by your project, and many other issues as well.

The example used, which is one that deals with errors, seems a bit... wonky. I would never have an enumeration for my error severity. In fact, I'm not entirely certain what the code is trying to convey. Lets look at a few questions about the demonstration code:
Is the Error function exit-able, or does entrance to the function pose the potential to halt execution within the function?

Does the behavior of the Error function radically change depending on the parameters passed in?

Why aren't you using exceptions (and hence RAII)?

Depending on the answers to these questions your usage of an enumeration could be entirely...stupid. As an example: If the behavior of the function changes radically based on the ERRORGRADE enumeration, then you shouldn't have those behaviors all bound up in one function, but across a number of functions. If the function has the potential to exit the application without returning, then are you properly dealing with scoped objects? Less you forget: If the function never returns then some objects whose destructors would normally be called will not be. This means open files may be left dangling, sockets will abort mysteriously, and other resources you have allocated can be left in a dangling or unknown state (such as named mutexes).

Then there is the question of "Why is this in a class?" Depending on your usage of the class it may or may not be appropriate to have these functions in a class. If your simply calling these methods as single shot calls, then there's no point in using a class, free functions will be cleaner.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
  • Advertisement
  • Popular Tags

  • Similar Content

    • By MintyLyton
      I'm looking for any team / people that need a programmer for their project. I'm looking to expand my portfolio which you can see Here. I'm more experienced with Unity but I can spend the time to learn new Engines if that's your preference. I have worked on Unreal Engine 4 before but I might take some time to re-learn it, if the project requires it. Feel free to DM here or use the contact info on my website. 
    • By ethancodes
      I'm working on a system for my game that will allow the player to stack pick ups in a queue. As one pick up expires, the next automatically activates. I'm having an issue though where if I pick up the first one, it activates fine, but if i pick up a second directly after it, it overrides the first one, activates the second one, and then once it has run it's course, everything goes back to normal gameplay, no first pick up. I'm not sure why this is happening. Hopefully someone can spot what I'm doing wrong in my code.
      Here is the code for the pick up manager:
      // Update is called once per frame void Update () { if (pickUpQueue.Count != 0 && !pickUpActive) { pickUpActive = true; pickUpQueue[0].ActivatePickUp(); } DeactivatePickUp(); } void DeactivatePickUp () { if (pickUpQueue.Count != 0 && pickUpActive) { Destroy (pickUpQueue [0]); pickUpQueue.RemoveAt (0); pickUpActive = false; } } And here is the PickUp:
      public override void ActivatePickUp () { ball.GetComponent<Ball>().Speed = 2.0f; //increase ball speed... ball.GetComponent<Ball>().StartCoroutine(timer); //...set time that power up is active }  
      There is also a Base Pick Up:
      public void OnCollisionEnter2D (Collision2D collision) { Vector2 tweak = new Vector2 (Random.Range(0f, 0.2f),Random.Range(0f, 0.2f)); this.gameObject.GetComponent<Rigidbody2D>().velocity += tweak; //if the pickup makes contact with the paddle or ball.... if (collision.gameObject.tag == "Paddle" || collision.gameObject.tag == "Ball") { GameObject.FindObjectOfType<GameManager>().GetComponent<PickUpManager>().pickUpQueue.Add(this); Destroy(gameObject); //...and finally destroy power up object } } As a side note, I am trying to find a solution to this that will work for all of my pickups. Some pickups are ammo based, some are timed. 
    • By D34DPOOL
      Edit Your Profile D34DPOOL 0 Threads 0 Updates 0 Messages Network Mod DB GameFront Sign Out Add jobEdit jobDeleteC# Programmer for a Unity FPS at Anywhere   Programmers located Anywhere.
      Posted by D34DPOOL on May 20th, 2018
      Hello, my name is Mason, and I've been working on a Quake style arena shooter about destroying boxes on and off for about a year now. I have a proof of concept with all of the basic features, but as an artist with little programming skill I've reached the end of my abilities as a programmer haha. I need someone to help fix bugs, optomize code, and to implent new features into the game. As a programmer you will have creative freedom to suggest new features and modes to add into the game if you choose to, I'm usually very open to suggestions :).
      What is required:
      Skill using C#
      Experience with Unity
      Experience using UNET (since it is a multiplayer game), or the effort and ability to learn it
      Compensation:
      Since the game currently has no funding, we can split whatever revenue the game makes in the future. However if you would perfer I can create 2D and/or 3D assets for whatever you need in return for your time and work.
      It's a very open and chill enviornment, where you'll have relative creative freedom. I hope you are interested in joining the team, and have a good day!
       
      To apply email me at mangemason@yahoo.com
    • By davejones
      Is there a way to automatically change the start position of an animation? I have a bunch of animations set up on 3D models in unity. The issue is that I need to move the 3D models, however when I do so the animation start positions are not updated and I have to do it manually.

      Changing the transform of key frames is time consuming with the amount of animations I have, so I was wondering if there was a way to do it automatically?
    • By MoreLion
      hey all! We are looking for members for our Unity horror game! 
      Here’s the story:
      After a deadly virus plunges the world into chaos killing 85% of the human population there are now what they call “zones” these zones are watched very closely by the surviving government, people are checked every day for the virus, even if you touch the spit or any human waste or fluids of the victim who is infected, you will die. But one day, people in the west zone start to go missing, 1 woman goes outside the walls to uncover the mystery, is there more to the virus than meets the eye?, That is where your story starts.
      This game is not a long development game, I have loads other game ideas,
      I will also allow you to have a bit of creative freedom if you wish to add or share a idea!
      And no, it’s not a zombie game lol I feel like zombie games are too generic, in this game you will encounter terrifying beasts!
      There is some concept art one of our concept artists have made
      If interested email liondude12@gmail.com
    • By Canadian Map Makers
      GOVERNOR is a modernized version of the highly popular series of “Caesar” games. Our small team has already developed maps, written specifications, acquired music and performed the historical research needed to create a good base for the programming part of the project.

      Our ultimate goal is to create a world class multi-level strategic city building game, but to start with we would like to create some of the simpler modules to demonstrate proof of concept and graphical elegance.

       

      We would like programmers and graphical artists to come onboard to (initially) create:

      A module where Province wide infrastructure can be built on an interactive 3D map of one of the ancient Roman Provinces.
      A module where city infrastructure can be built on a real 3D interactive landscape.
      For both parts, geographically and historically accurate base maps will be prepared by our team cartographer. Graphics development will be using Blender. The game engine will be Unity.

       

      More information, and examples of the work carried out so far can be found at http://playgovernor.com/ (most of the interesting content is under the Encyclopedia tab).

       

      This project represents a good opportunity for upcoming programmers and 3D modeling artists to develop something for their portfolios in a relatively short time span, working closely with one of Canada’s leading cartographers. There is also the possibility of being involved in this project to the point of a finished game and commercial success! Above all, this is a fun project to work on.

       

      Best regards,

      Steve Chapman (Canadian Map Makers)

       
    • By Scouting Ninja
      So I have hundreds of moving objects that need to check there speed. One of the reasons they need to check there speed is so they don't accelerate into oblivion, as more and more force is added to each object.
      At first I was just using the Unity vector3.magnitude. However this is actually very slow; when used hundreds of times.
      Next I tried the dot-product check:  vector3.dot(this.transform.foward, ShipBody.velocity) The performance boost was fantastic. However this only measures speed in the forward direction. Resulting in bouncing objects accelerating way past the allowed limit.
       
      I am hoping someone else knows a good way for me to check the speed with accuracy, that is fast on the CPU. Or just any magnitude calculations that I can test when I get home later.
       
      What if I used  vector3.dot(ShipBody.velocity.normalized, ShipBody.velocity)?
      How slow is it to normalize a vector, compared to asking it's magnitude?
    • By Ds ds
      Hi, my name is Andres, I'm a programmer with a technician degree and a Diploma in C#, looking for a project in Unity to start my career in game development. I don't do it for a paid but a recognition and start a portfolio, preferably a 2D game. Thanks for read, have a nice day. 
       
    • By Victor Rodriguez
      Hi there! Is the first time that I'm posting here so I'm sorry if I'm doing it wrong ha. 
      So here it comes, my doubt is, I'm doing a game with different levels, each of these levels in one different scene. Each scene contains to cameras that you can change pressing a button. Everything works fine. 
      The only problem is that I would like it to look a bit more professional, and I would like that if you finish the level with camera2, the next level start the same way. I've been thinking about using dontdestroyonloadon both cameras, but obviously this cameras need to be attached to the player to make the movement work, what do you recommend? Sorry If I've explained it in a messy way, and feel free to dm me for anything. Thanks in advance! 
    • By Ike aka Dk
      Hello everyone 
      I am a programmer from Baku.
      I need a 3D Modeller for my shooter project in unity.I have 2 years Unity exp.
      Project will paid when we finish the work 
      If you interested write me on email:
      mr.danilo911@gmail.com
  • Advertisement
  • Popular Now

  • Forum Statistics

    • Total Topics
      631378
    • Total Posts
      2999665
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!