- Home /
GUI, SpellBar and C#-related questions
Hello everyone,
I am fairly new to Unity and C#, though I have been exposed to programming overall, so I am able to follow the logic. What I usually miss is the syntax and Unity-specific features that can solve a problem more easily than my typical overcomplicated way of processing things.
I have seen a bunch of tutorials, but I am unable to provide myself with a summary of what I want to do.
To get things started, I am wondering about the following:
I want to create a spellbar. The buttons of this bar are placed by script on a canvas. Although I am able to do that, my question is related to how I detect which of these buttons was clicked. Assuming that I store my buttons in an array of variable type "Button", which of the following methods should I be using: OnGUI(), RayCasting or OnMouseDown() with a subsequent if statement (which will check if button clicked == SpellButtons[n])? Basically, in game development terms, can you give me an example for each and how to decide which of the aforementioned methods is suitable for a given problem?
I have also seen people using the AddListener. How is this related to GUI? The way they termed it, it echoes audio-related functionality. When would I use this and why?
C# related question; why would I use a delegate instead of an if/then/else statement? There is a really good example explained here, of what it means to employ a delegate in your scripts. However, I can't help it but wonder about the specific statement of "In programming, you are often faced with situations where you need to execute a particular action, but you don't know in advance which method, or even which object, you'll want to call upon to execute it.". As I am a programmer of my own game, why wouldn't I know which action (method/object) should be executed? If we had to utilize this concept in game developing terms, in which case wouldn't we know the expected method?
Still in the context of the first question, but this time suppose we have pre-set buttons from the editor; I want to assign a functionality to each spell. However, I do not want to attach (as in, drag and drop) a different script for each new button that I generate (because, although I currently have 7 buttons, I might end up with 200). What is the best way to check which screen button was pushed? Should I go with tags, should I go with a public string variable called name that will return the name of the button or something else? I am used to another game engine, where, everything you placed in your scene would "emit" a unique ID. You could then check if the object was equal to this ID and this is how the engine understood how to attach functionality to the object. Do we have anything similar in Unity? Additionally, do we have a prefab-type check? E.g. I have 3 types of rocks, each having 20 instances in the scene. I want to check if the clicked prefab-type object is e.g. Rock Type [1] (out of 3) and then have a different kind of effect taking place. Finally, is there any way to check if the object that was interacted with is the specific object I want to refer to from the scene? E.g. Out of the 60 rocks, I want one specific to release a very unique event. How do I check if this specific rock was clicked? This is primarily why the ID I talked about in the previous engine was easy to deal with.
I am having trouble understanding the following naming convention: the underscore_name, e.g. _slider or _img. What does this do? Is it like a variable?
I want to save some data into a file in a form of a matrix (if you are also familiar with MatLab). This file will have X columns and Y rows; how do I organize their display in the txt file to resemble to a matrix?
I still don't understand the necessity of the static keyword (and I have looked at tutorials, examples and books). Let's say I have float CupOfTea and a static float CupOfTea. What is their fundamental difference that will dictate the use of the static keyword in a situation? Again, could you please share a game-development example for me to understand and never forget?
Which one is more efficient, waitforseconds or a timer? What is their difference and why would I use one over another? In the following scenarios: i) Damage over time, ii) Delayed damage (after X second of having cast the spell), iii) moving an object along with another one by setting its transform.position at the same as the primary one's.
How do I fire a projectile from a specific body part of a game object? E.g. a wizard's staff, the right hand, a dragon's mouth, the eyes.
Say I have an animation clip, which has been set to Looped from the Inspector. I want to know whether a script's wrapmode will override this setting; if it does, how to disallow it from doing it? Should I first GetComponent and if it is not equal to the wrapmode I want to add, then set it back to the original value?
What is the role of the "out" keyword in the following line?
if (Physics.Raycast(rayOrigin, out hitCheck, _distance)))
I'd like to create an effect (particle emitter) that is displayed as fire to its "owner" player, but the enemy player will be seeing e.g. water instead (and obviously anything happening to the actual particles, the fire, will be happening to the water as well). How do I do that? Do I create a clone of each other, attach the same scripts and change the transform values of the latter to the former's or is there a function that accounts for that? In the same concept, how do I set a particle system to be visible to one player but not to another?
How do you define a "spawning" point? How to refer to a specific coordinate that you are seeing in the scene?
Sorry for the extensive list of questions, but I'd rather ask them all at once than creating separate topics for each. If I get a deep understanding of these, I will have already covered a great percentage of familiarity with C# and Unity (well, the beginner's stage, that is).
Thank you a lot for your attention!
This definitely belongs in the forums. UnityAnswers is for specific technical questions; the forums welcome more abstract conceptual stuff.
Answer by AlwaysSunny · Mar 10, 2015 at 02:25 PM
First off, you should probably avoid OnGUI and the legacy GUI stuff unless you're scripting for the editor. 4.6+'s UI buttons expose an editable list of events to invoke OnClick. This is fine in many cases, but for dynamic buttons (something like a spellbar) you'll want another approach. Give each dynamically-instantiated button prefab a script which implements the IPointerClickHandler interface and you'll have scripted control over what it does. Use this to call a SpellBarManager script, passing "this" (the button itself) as a parameter. Then you know which button was clicked.
public script MyButton : MonoBehaviour, IPointerClickHandler {
public void OnPointerClick( PointerEventData ped ) {
MyManager.OnButtonClicked(this);
}
}
AddListener is another way to invoke custom logic with buttons. I prefer the interface approach, but it's essentially an alternative.
"Why wouldn't I know which action (method/object) should be executed?" You simply haven't encountered the need for this yet. You will! Delegates often solve cases where you'd otherwise have to write many hard-coded, inter-dependant methods. Among other things, they're useful for event systems to which other objects can subscribe. You'll want the features delegates offer eventually, guaranteed. Don't worry about it for now, relative newcomers will not descry their value at first.
"You could then check if the object was equal to this ID and this is how the engine understood how to attach functionality to the object. Do we have anything similar in Unity?" Not exactly? Eventually, you won't miss this. It sounds a tad messy. Explicit control over scope and access are good things.
"Additionally, do we have a prefab-type check?" I don't think so. At least not directly. I'm sure there's a clever solution to make this happen that I'm just blanking on. There are ways around this, especially if you're pooling objects, or otherwise maintaining a collection of like objects.
"Finally, is there any way to check if the object that was interacted with is the specific object I want to refer to from the scene" This is kind of a general programming question about scene and reference management. The management style you prefer may not be in keeping with Unity's preferred practices. Generally I keep lists of anything instantiated, so I can have "group" access whenever I need it. Knowing "which among several" objects you're dealing with depends upon how you're picking. You'll see this as you experiment; there's always a "most convenient" way to get access to what you need. As far as creating "special" items from among generic items, often the easiest way is to attach a specialized script. If the object has that script, it's the special one.
Variable naming conventions are mostly a matter of preference, just be consistent. Some folks like _underscores for local-scope variables, or prefixes that remind you of the variable's scope. I generally use camelCase for any local field and SentenceCase for public properties and eschew this tomfoolery. ;)
About saving a matrix; I trust you understand there's a difference between saving something for a human to read versus saving something your program will later load back in and read. For a human-readable matrix, I'd recommend a string building method which takes a matrix of arbitrary size and returns a string formatted however you like.
Think of static variables and methods like this: Non-static members of a class belong to an instance of the class. Static members belong to the class itself. I have a giant static class full of static methods and extensions that act as helpers for common functions. I don't have to instantiate an object to use those static methods, I just qualify them with the name of the class:
public static class Statics {
public static bool CoinFlip { get { return Random.value > 0.5f; } }
}
Because these are static, I don't need to create a "Statics" object to call those methods. I just write "Statics.CoinFlip" and get the result. There's more to learn about statics, but this is a cursory overview.
"Which one is more efficient, waitforseconds or a timer?" Don't worry about this. Use whichever is more convenient or appropriate. All the examples you mentioned would work fine in a Coroutine, which is what I'd recommend for each.
"How do I fire a projectile from a specific body part of a game object" I think the common way to do this involves adding some kind of meta information to the model or an empty parented to the model.
"Say I have an animation clip, which has been set to Looped from the Inspector" - I don't know about animation.
The "out" and "ref" modifiers inform the compiler that the variables they precede should be treated in a special way. Generally, this is done when you want a method to make changes to the specific value-type object you've passed as an argument. Without these modifiers, any attempted changes to the argument you passed in are lost when the method returns. These modifiers ensure the variable is actually changed when the method returns. I think the only difference is, with a "ref", making changes to the variable within the method is optional, and with an "out", writing to the variable is mandatory.
I suppose the "different object for different players" concept would be best handled by the server-client relationship. In other words, if other player has type fire here, use type water here instead. In a split-screen environment, I guess you'd want to use multiple cameras. Both objects exist simultaneously, but one player's camera renders A and not B, and vice versa.
"How do you define a "spawning" point?" A quick-and-easy approach is to use an empty. That is, a gameobject with a transform and nothing else. Your spawn script can keep a reference to this empty and use its position for spawning.
I hope this was helpful, it was a rather nice distraction from my work. ;)