Skip to main content

Designing and coding the switches

When I first started thinking about translating a switch into code, I did not map out every method, inheritance, relationship, and try to think of every consideration. This was likely not Best Practice(tm), so why did I just do what every noob does and start writing code?

Because I am a noob coder.



There is an important interdisciplinary principle which is that you don't know what you don't know, and when you learn something that you didn't know, you learn many new somethings that you do not know. So, rather than me get on this blog and try to talk big about my planning, I want to be transparent and discuss my inefficient and laborious process to building a code base that so far is working.

First, a little aside. I view coding as nothing different than learning a language that computers speak -- that is, listen to. Whereas German is a language that humans speak and listen to, C# is a language that processors register with the help of an interpreter. So yes, it's not a perfect analogy, but let me get to the point. When we learn to write or speak other languages, we do not start out by learning the proper MLA format for headers and the subjunctive mood. There is a progression of learning that requires mastery of basics before moving into more advanced methods of expression. In coding, as in writing, there are often many ways to achieve the same result. In writing, we speak of style. In coding, we consider style secondary to efficiency; after all, we are speaking with computers and not humans.

So when you read my code, you will see a different style. It's written in conventions that only work with Unity, and the variable names are long and obvious. I write for myself. But, you must also write for your readers. My amateur opinion is that if the code works, and I can understand it, and my colleagues (readers) can understand it, then it is successful.

Up to this point, it almost seems that I'm suggesting not to consider efficiency or best practices. On the contrary, what I am suggesting is that I do not yet know what are the best practices, naming conventions, and commenting techniques. I'm looking forward to learning how this could have been coded better, because this code is written to the best that I know how. I don't like to cut and paste. I like to understand and implement. I do not doubt that there are assets in the store with better switches. That's not the point of this writing exercise, as I see it.

Thinking about coding the switch, it needed to do at least a few things:
  1. Be clicked on
  2. Do something when clicked on
The class also had to be able to accommodate different types of switches, so I knew it either had to be abstract or at least have some virtual methods that could be overridden. I wasn't confident enough to know which was the best choice, so I went with a base class that allowed for some overridden methods.

The GameManager should manage all player input, so when a player clicked the mouse, the manager would determine whether they clicked on something. If that something was a switch, it told the switch it was Clicked(). Simple so far!

Problem was the switch didn't feel right because the player could spam click. Adding a reset internal timer allowed the switch to receive a Clicked() call, but to ignore it if it was not yet Reset.

I decided that the Clicked() method should just manage the logic about what to do with the click. This meant that any future restriction on behavior could be handled in Clicked(), and the actual "do something" could branch out from there. So, if a switch that is eligible to be clicked is Clicked(), the switch will Activate() -- "do something"

OK, so if a switch is activated, what should it actually do? A few things:
  1. The switch state should change to READY or NOT READY
  2. Animate
  3. Make sound
  4. Start the reset timer over again
Implementing #2-4 were easy enough to do.

I had to think more about #1 because I knew that the level needed to keep track of whether the switches had been toggled to READY. I also didn't want to have to use an Update() loop to constantly check whether a "win condition" or similar had been achieved. This meant some type of Event and EventHandler relationship. At this point, I was not sure what information should be passed during the event, so I created a new type of UnityEvent that would pass the Switch object and its newReadyState as a boolean:

// Create a new event type that takes Switch, bool. Must be serialized in order to work properly
[System.Serializable]
public class SwitchEvent : UnityEvent<Switch, bool> { }

Now, when the Switch was activated, it could call an Event which would presumably do whatever magic was needed when switches went READY (or NOT READY, for that matter).

But now, who was going to listen to these switches?????????

TO BE CONTINUED

Comments