How do I access my "Current Screen" variable from within other classes? - c#

I have a bunch of screens that all inherit from a base abstract class called GameScreen. They include various buttons that, if pressed, I want to use to change the Current Screen. For now, I am trying to change the screen from startScreen to overviewScreen.
I have a variable in my Game1 class:
public GameScreen CurrentScreen;
Which is initially set as:
CurrentScreen = startScreen;
I then use the following lines to Update and Draw the game, based on which screen is the Current screen:
CurrentScreen.Update();
...
CurrentScreen.Draw(spriteBatch);
In my startScreen classs, I want to write something like this within the update method:
if (//Button is pressed)
{
game.CurrentScreen = overviewScreen;
}
Now clearly that won't work. But I can't see how to do it. Basically I want to access the CurrentScreen variable from within a class, and change it to whichever screen I want, and I feel like there must be a clean way to do this.
Let me know if any additional info is required, I feel like I haven't explained this at all well.
EDIT
startScreen and overviewScreen are classes that, primarily contain the Update and Draw methods for screens I want to display. GameScreen is a base class they all derive from. CurrentScreen is just meant to be a variable that determines which screen is active.

Ok, notw it's cleaner for me. You could add few methods to your Game1 class
public void SwitchToStartScreen(){...}
public void SwitchToOverviewScreen(){...}
//etc
Then you could add a property to your startScreen class (and other ones too)
public Game1 Parent {get;set;}
And force the constructor to pass Game1 object, in which you would assign that parameter to Parent property. Then on particular condition you could just use
Parent.SwitchToOverviewScreen();
Accessing and changing properties manually from outer classes is violating object-oriented principles.
Also, use brief naming convention, because it's hard to understand what you wrote if one of class definitions uses Pascal case while other use Camel case. Your startScreen has more like an object name, while it's used like a class name. Eithar that or you're not seeing the difference between class and an object.
By default in C# Pascal case is used for declaring classes.

use the static objects
public static GameScreen CurrentScreen;
and same for the overviewScreen

Related

Unity/C# what's wrong with the way I think about this problem

I have an abstract parent class called Item
From this I inherent to Equipment and from here to Weapon and Armor. Since I want my weapons to have varying behavior, I want my logic to operate on the classes. From my Item class I also inherit to a Resource class, which should be static. My Equipment class shouldn't and should be instansiable , since an individual sword eg. Can be sharpened or damaged, to change it from its base class without changing all other swords. So I need to clone these class instances. But since cloning a class is a very non forward thing to do, I was wondering if I am doing something wrong in my architecture, and thinking about the problem in the wrong way? Do anyone have any thoughts? /Mikael
I think you should consider setting the 'stats' for items in a file (xml or such) and then create a Factory class that can give you a file with all the stats already set.
i.e.
public abstract ItemFactory{
public static Sword GetSword(){
var sword = new Sword();
//Set stats for sword from file
return sword;
}
}
Why use cloning when you can just use referencing? If I understand your problem correctly, I would utilize ScriptableObjects for defining your item objects, which makes them Assets in your project. Which then can be assigned via the inspector.
The general class layout could look something like this.
class Equipment : ScriptableObject
{
public int goldCost;
}
class Weapon : Equipment
{
public intDefaultSharpness;
}
These are your definition classes, remember they are to define the general properties of each item category. So you might have a Sword, but not a "Broadsword of fiery Dragonkiller". If you check the link about ScriptableObjects you will find code that allows you to instantiate new Assets from these definition classes. Now you can create your Broadsword and ofc many more. Now your objects just become assets like Textures and 3D models. You can easily edit them in the inspector (and probably want it to make it even nicer with custom editors)
Similar to a texture or 3D Model we don't copy it every time we use it, instead we reference it. So when your player character holds a weapon you have a sub GameObject that just keeps a reference to the original object and any additional "local" data.
class PlayerWeapon : GameObject
{
public Weapon template;
public int durability;
}
The nice thing is, the template Weapon is assignable via inspector in the editor, as it is just a normal asset. And the durability property is local to this playerWeapon and the GameObject could be used multiple times.
Of course, this can be expanded on as much as you want. I would probably add getter/setter to hide additional calculation based on buffs/debuffs. Something like
public int AttackStrength
{
get
{
return owner.strength + template.strength
}
}

Why aren't UI components declared as static?

Let's say that my main class is this:
public class mainActivity: MonoBehaviour { ... }
When I want to initialize an Image for example, I have to declare it as:
public Image myImage;
Only then I can have access to this instance from Unity's menu. My question is simple. In OOP when we want to access a variable without creating an object we declare it as static. So it becomes class' variable. Right? But Unity lets me create an Image while it's not static and I don't create an object of my class.
How is this possible? Does unity create any "invisible" object of my main class or so?
It's not necessarily an invisible object. The class in question is serialized into a text-based version of the class in which Unity is able to read/write from the editor. If you open a .Unity scene file in a text editor you will see this serialization in practice.

Extending a class with a new nested class

first question so I'm open to advice on effectively participating in the StackOverflow community as well as pertaining to the question.
I'm working on a text-based UI in C#. I have an abstract window class and an abstract control class, each of which implements common functionality for the types that inherit them (e.g. pop-up windows or text box controls). Currently, within a program that might implement the library, a developer would have to create window objects and control objects, and then add the controls to their respective windows, and the windows to a window manager class, like this:
var mainWindow = new MainWindow(...);
var textBox1 = new TextBox(...);
mainWindow.AddControl(textBox1);
WindowManager.Add(mainWindow);
This works, but it's a bit clunky. Since a control should never have to exist outside of a window, I was hoping to implement the control types as nested types. However, to maintain extensibility of the program, I'd like for there to be a way to extend the window class with new control types. My question is this: Should I use reflection, or rely on developers using container classes to extend the window class? Alternatively, is there a better way to structure the program than how it's currently laid out?
I've also considered using generics, e.g.:
public abstract class Window : DrawableObject, IWindow
{
public void AddControl <T>(object[] constructorArgs) where T : class, IControl
{
}
}
I'm aiming for ease of implementation without sacrificing extensibility/loose coupling. Thanks in advance for any thoughts!
EDIT: Should clarify, the primary reason for this is to fix some weirdness with how Windows and Controls cooperate. Each control has a parentWindow property which is used to access the window on which a control resides, for various purposes like creating an exit button for a particular window, etc.
Right now, this property is passed to the constructor, but that seems redundant to me since after doing so you have to add the control to the window's control list. I'd like to find a way to set this property when the control is added to a window instead, but restrict this action to when the control is added only, to prevent potential problems if the parentWindow property is changed outside of this context.
The way you coded AddControl method:
public void AddControl <T>(object[] constructorArgs)
where T : class, IControl
{
}
You intend developers to just provide type and your AddControl method will create an instance of it using constructorArgs. This method itself implicitly forces you to use reflection. Anything else does not stand a chance. Because To Add control of type T, Creating Instance of Control of type T is necessary. Since your Window class does not have a clue about T reflection is the only solution.
To facilitate other approaches, you might want to consider few overloads of AddControl.
public virtual T AddControl <T>()
where T : class, new(),IControl
{
//now you can create instance no reflection required
var control = new T();
this.Controls.Add(control);
return control;
}
public void AddControl <T>(T control)
where T : class, IControl
{
}
public abstract void AddControl <T>(object[] constructorArgs)
where T : class, IControl;
Creating an abstract method passes onus of implementation on child class and creating new instance of T can be handled the assuming type of T is known there or at-least all cases of known types of what T might be are handled.
It's a wide scope topic and I guess subjective as well. The best use of OOP is to achieve a design which fits your logical objective whatever that maybe.

C# in Unity 3D/2D: Am I required to use Classes for every script?

A little background: I'm new to C# and Unity, but catching on very quickly. I'm also hoping this thread will not spark a debate about the merits of classes and abstract coding, as that debate is unrelated and well-worn (and unnecessarily heated); so please keep that in mind.
I'm simply wondering if every C# script in Unity is required to have a main class in any way or for any reason.
Or instead, can methods, and variables can be written outside of a class in a blank file (with namespaces) to be used in a video game?
I'm asking because, when I create a new C# script, it seems to force a class into my file and I'm afraid of breaking things.
I hope to keep code abstraction to a minimum, and the current project
I'm working on has several situations where a class is not needed, or
only one instance of the class will be used. I'd like to simply avoid
using classes in those cases.
In terms of declaring/defining variables and methods outside of any class, you can't really do that in C#. It just isn't how the language was designed (the answers to the question I linked to expand on that idea, so I won't duplicate them here).
You're not without options, though; if you have a number of variables or methods that need to be accessible from different places and don't need an object reference, you can make them static, so you won't need to instantiate the class to make use of them:
public class UtilityClass
{
public static float GravityConstant = 3.51f;
public static string GameName = "MyFirstGame";
public static float CalculateProduct(float a, float b)
{
return a * b;
}
}
Then, you can reference the class's methods/members by accessing it through its name:
float product = UtilityClass.CalculateProduct(6, 1.5f);
An example of where you might use this pattern is when defining mathematical formulae which aren't included in Unity's Mathf methods, and using them in multiple classes.
Additional note: Creating a new C# script through Unity's editor UI will default to declaring a class of the same name that inherits from Monobehaviour. You can alter it to remove the inheritance from Monobehaviour if you don't need any of the methods/attributes of the class, which avoids unnecessary overhead. One example for this would be with a static class that you never need to instantiate.
Yes, you are.
In C#, things like global variables and functions just do not exist. Everything must be contained in a class.
"But what should I do in order to declare some stuff that can be accessed everywhere, without creating an object?" you asked. There is something called the static modifier. You can access the methods or variables or fields or properties marked with this modifier without creating an object of that class.
You just add the word static in a method and it becomes a static method! How simple!
Let's see an example.
I have this non-static method:
public class MyClass {
public void DoStuff () {
}
}
I can call it like this:
var obj = new MyClass();
obj.DoStuff();
But if I modify it with static,
public class MyClass {
public static void DoStuff () {
}
}
I can call it like this:
MyClass.DoStuff();
How convenient!
Note:
Please do not misuse the static modifier! Only use it when it makes sense! When? When the method is a utility method or when the method does not belong to individual objects but the class itself.
First of All you need to check where Methods define as offical
docs stated
"Methods are declared in a class or struct by specifying the access
level such as public or private...."
So, Method should be declare in a Class or struct and A given class
should be, ideally, responsible for just one task.(see also)
Your this question "Or instead, can methods, and variables can be
written outside of a class in a blank file (with namespaces) to be
used in a video game?" answer is hidden in the below question.
Can there be stand alone functions in C# without a Class?
No. Make them static and put them in a static utility class if they indeed don't fit within any of your existing classes.
You have to make a class in order to use methods or its variable
either instance class or static class.
Am I required to use Classes for every script? Every script means you required a class. Unity Support Component Based
Architectural Design and if you require any script related
work then you definitely require a script component which means a
class require.
Finally for singleton, thanks to Unity3dWiki great detail
available. I think you will be feel comfortable to code and writing
class if you keep in mind component based architecture of Unity3d.
Singleton vs Static: I will also recommend to check this: Why do you use a Singleton class
if a Static class serves the purpose
Hope it will help.
[Note: If this helpful Any one can update this answer for future reference and use].

Passing objects to a UITypeEditor

I am currently hoping to use a PropertyGrid to allow users to edit some of my classes, however I've hit a wall with passing objects to the UITypeEditor(s) they use. When the user presses the drop down I want to show a listbox of already loaded textures to choose from, if they want to use a texture the application hasn't loaded yet they can click a button to choose one from a file dialog. In case I make no sense here a mock of the form:
.
My problem: To fill the listbox I need access to the class that manages the list of resources from the UITypeEditor.
Now I've solved this problem for my own classes by giving them a reference on creation to their managing object. In the UITypeEditor I then use that reference to access what I need. However I can't do this for classes I haven't written, such as the XNA Texture2D class.
Here are what the classes I'm using look like:
class StaticGeometryChunk
{
// Geometry data to draw with. Contains a reference to its managing
// class for use in its UITypeEditor.
public GeometryData { get; set; }
....
}
class Material
{
// These are XNA classes. I can't just add a reference to its managing
// class (I think?).
public Texture2D Texture1 { get; set; }
public Texture2D Texture2 { get; set; }
....
}
I've been looking at my options and they seem to be:
Make the managing classes static.
I don't really want to do this. There are several managing classes as each resource is loaded differently. There are also classes that need to be created before these and are passed in.
Make the managing classes singletons.
I don't really want to do this either. It seems like a quick and dirty way to "hide" the problem instead of "solve" it. I also might want the option of having several managing classes in the future which the singletons eliminate.
Create a wrapper class which holds the reference to a managing class and its target (such as the XNA Texture2D).
This is currently what I'm thinking of doing. Its would be quite simple and quick to do but something about it nags me but I don't know what.
Any thoughts on the above or other methods to pass what I need into the UITypeEditor?
Thank you for reading.
In the EditValue method, you are given a context. Use context.Instance to access the object that holds your property. This object should also contain a property that gives you access to the list of things you want to display. You could test if context.Instance is ITextureProvider for example, then cast it and access the textures. Not sure if this makes sense in your design but let me know.
As an alternative you can try the following approach. I find it very elegant, because it does not require to store a list of available property values in the object. Therefore, for example, you can show one set of values on one form and another set on another.
Create an interface IYourDataProviderService.
Create an implementation of IYourDataProviderService, which knows the concrete data to provide.
Create a class implementing ISite. In GetService() method return an instance of class which implements IYourDataProviderService, if the serviceType parameter is typeof(IYourDataProviderService).
I left rest of ISite methods throwing NotImplementedException (except DesignMode property) and for me it worked, but probably this is not an ideal solution.
In 'Load' event handler assign your implementation to the Site property of your propertygrid.
Enjoy!

Categories