I am making a game using MonoGame and C#. The main class is called Program.cs and is automatically added when creating the project. It uses these lines of code to run the game:
using (var game = new Game1())
game.Run();
The Game1 class contains properties that I need to use in other classes, but the only way to access them at the moment is by making the properties static and using code like the following:
int exampleNumber = Game1.MyNumberProperty;
I'm sure that this is bad programming practice, so I was wondering if there was any way for me to access the "game" instance variable from Program.cs so that I don't need to use static properties. However, the "game" instance is a local variable. Is there any way at all for me to call it using a manner like the following:
int exampleNumber = Program.game.MyNumberProperty;
Edit:
I've created an example class to hold some of the variables and have instantiated it in the Game1 constructor.
MyClass exampleClass;
public Game1() : base()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
exampleClass = new MyClass(); //The class is instantiated here
}
However, I am confused as to how I can now access this instance in another class. The way that I am doing it now is to make the instance static and use a static property, but now I'm back to the original problem.
Put your variables inside specific classes, something that describes them better than just game. For example, a Settings class, this way you would actually ask for the Settings object that is stored in the game class, it gives more context to what your dependencies are.
Now, to fix the static property you would have to create for the Settings class, you have 2 ways:
1: Instantiate all objects manually in the start up of the game class, basically you will wire all the dependencies yourself.
2: Use a dependency injection framework like Unity.
Related
I've been trying to grasp the concept of Dependency Injection within .NET Core but have hit a problem. I think I'm missing the point somewhere along the line.
As an example, say I have a top level GameHandler class, then a Game class and a ScoreCard class.
My Game class has a dependency on the ScoreCard class and this needs to be registered as a transient service since each new game needs a new scorecard. I can achieve that by doing this...
public class Game
{
private readonly IScoreCard _scoreCard;
public Game(IScoreCard scoreCard)
{
_scoreCard = scoreCard;
}
}
Then I register the service in startup.cs in the ConfigureServices method
services.AddTransient<IScoreCard, ScoreCard>();
This is all good, it's a simple one to one relationship where the Game class needs a single instance of the ScoreCard class.
My GameHandler class also has a dependency on the Game class. However, in this case, I want to potentially have multiple games, probably stored in a dictionary of some sort along with a key. And I don't know how many I'll need because it depends on who is playing at a particular time so I'd need to create new Game objects whenever I need them.
If I try and do this using new, like this
Game _newGame = new Game();
it obviously doesn't work because my Game constructor now has the DI ScoreCard stuff in there and that doesn't match. So how do I create new instances of Game using DI without using new?
At some point, you need a 'scope'. That scope is a level in your code where your instances are created. In some cases, the scope may be main, in message passing systems, each 'message' will have a new scope.
If your scope is 'every time a new game is created', then using whatever DI package you are using (I'm guessing it's the default net core one), then you need to call IServiceProvider.CreateScope(). After this point, any time you ask the service provider to give you a new Game(), it will return one based on how each class was registered.
With dependency injection, you should never call new, you need to ask the service provider to give you an instance of a type.
IServiceProvider.GetService<YourType>();
IServiceProvider can be retrieved either when you create it (after registration, and building), or it can actually be injected into a constructor too.
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.
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].
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
I have a class by itself called clientChat that does basic network stuff. I have several other classes linked to different window forms. In my first form I have a variable referenced to the chat class like so:
clientChat cc = new clientChat();
Everything works okay their, the class has been initialized and everything is in motion. After the first forms is done performing it's duty I bring up my second form that's obviously linked to a new class file.
Now my question is, how can I reference what's going on in the clientChat class without setting a new instance of the class? I need to pass data from the form to the networkstream and if I create a new instance of the class wouldn't that require a new connection to the server and basically require everything to start over since it's "new"? I'm a bit confused and any help would be great, thanks. C# on .NET4.0
You could create an instance of clientChat in the beginning of your program and then, simply pass its reference to the classes that need it.
You may want to look into the Singleton design pattern. Mr Skeet has written a good article on how to implement it in C# here. (Just use version 4. its the easiest and works fine =) )
Presumably you would either:
Create the object from the code that creates and shows both forms, and pass a reference to that same instance to both forms, or:
If you create the second form from inside the first form, pass a reference to the instance referenced by the first form to the second somehow (via a property or a constructor, for example).
In additional to #Jens's answer, there are 5 approaches on the linked page, while I think we have the 6th using Lazy<T> in C# 4.0
public sealed class Singleton
{
private Singleton() { }
private static readonly Lazy<Singleton> m_instance = new Lazy<Singleton>(() => new Singleton());
public static Singleton Instance
{
get
{
return m_instance.Value;
}
}
}