what is the difference between public and private variables , gameobjects and other things in Unity - C# ? ; Thanks for help.
The public variables can easily be changed, while the private variables cannot be easily changed.If you compile the code you can see an input for the public variable in the inspector panel, by changing the variable in the inspector panel you change the variable for that case. However, you will not see one for a private variable.
I would suggest for scripts in which will be use more than 1 times, expose the elements that would be used differently.
If a variable/function is public, other classes with access to the class can access it.
If a variable/function is private, other classes can't access it. Only the class itself can use it.
Good programs try to have as few public variables/functions as possible, see Loose coupling.
Related
I think it's inefficient to implement these two lines of variables.
[SerializeField] private int i;
public int I => i;
So I would like to express this in one line, but this is not serialized in Unity.
[SerializeField] public int I { get; private set; }
I want to make it visible in Unity Inspector.
So my question is below.
Can this property be serialized?
If impossible, is it possible to solve it in a way other than the above?
Starting in C# 7.3 (which Unity supports), you can now add attributes to the backing fields generated by autoproperties.
For this instance, where the backing field is auto generated, you can add this attribute:
[field: SerializeField] public int MyField { get; private set; }
This serializes the backing field as if it were a normal variable.
Well that's correct behavior.
[SerializeField]
public int I { get; private set; }
This is a property (with a getter and setter accessor), not a variable. These are not, cannot and should not be serialized. If you want an exposed variable that you can set (or see) in the Inspector, use a public modifier on a variable, not a function or accessor. If you don't want the variable to be public, then it can be protected or private, but marked with [SerializeField] as you already know. This is by design and is the correct approach.
Some additional information as it seems you might have different expectations on how Unity should behave:
Unity has some different paradigms as opposed to conventional programming and this is by design as the engine has a different approach to how each game object (and by this I mean any UnityEngine.Object descendant, not just UnityEngine.GameObject) interacts with another and how it should be implemented in the game (i.e. adding it as a Component or ScriptableObject as opposed to using new() or how the garbage collection of said objects is handled in the engine). This means that if you want the convenience of the Inspector real-time editing features, you'll need to "break" some rules regarding object access and mark a lot of variables as public. If you don't want that, there's always the option of referencing them in code or using ScriptableObjects, but that might be overkill in some cases.
Unity is also akin to encapsulated, as extending existing deployments is done differently from C#, so using public or private variables or functions doesn't change much. It's not like somebody is going to make a library and extend from your game's library since Unity doesn't work that way.
I was wondering if in the order of a class should I write first the Serializedfileds that let me edit them in the editor, or the public variables (that even can be nonSerialized) but can be edited in the editor too.
I use to do it in this way:
-Public Vars
-Serialized vars
-Private Vars
-Public Methods
_Private Methods
It's that right?
From a functional point of view, it doesn't matter. You can order them however you want, it will still work the same.
However, there are coding guidelines most developers adhere to.
Jonathan Wright answered a similar question where he also linked the c# coding guidelines he cited from:
You would order them as follows:
Fields
Constructors
[...]
Properties
[...]
Methods
Within each of these groups order by access: (SA1202)
public
internal
protected internal
protected
private
So while members with attributes like [SerializeField] are not explicitly listed, I would order them the same way you do, since the [SerializeField] attribute exposes the field to the Unity Editor and makes them accessible from outside.
It does not matter which order you choose, so long as you are consistent and have some sort of structure that you follow
I'm using InvokeRepeating() to call a method in a game. I call InvokeRepeating() in the Start() method of one of the GameObject classes. To set the repeatRate parameter for InvokeRepeating(), I am passing it a public field called secondsBetweenBombDrops.
Unity ignores the value I specify for secondsBetweenBombDrops in the code and instead uses some default value (i.e. 1) when secondsBetweenBombDrops is declared without a static modifier:
public float secondsBetweenBombDrops = 10f;
void Start() {
InvokeRepeating("DropBomb", 1f, secondsBetweenBombDrops);
}
However, once I add the static modifier to secondsBetweenBombDrops, the code behaves as expected and the correct value of 10 is used:
public static float secondsBetweenBombDrops = 10f;
void Start() {
InvokeRepeating("DropBomb", 1f, secondsBetweenBombDrops);
}
Why does this field require the static modifier to use the appropriate value?
In the Unity inspector, the script component shows that secondsBetweenBombDrops is 1. This default value of 1 is present regardless of whether I instantiate the prefab on game start or create prefab instances while the game is running.
The double-edged sword of serialization
Unity wants to make things easier for everyone, including people with limited coding knowledge (beginners, designers).
To help them out, Unity displays data in the inspector. This allows the coder to code and the designer to design by tweaking the values without opening MonoDevelop/an IDE.
There are two ways to have values display in the inspector:
public int myVar = 10;
[SerializeField] private int myOtherVar = 0; // Can also be protected
The second one is better since it complies with encapsulation principle (variables are private/protected and modified via methods or properties).
When you display a variable in the Editor, the value given in the script is only used when dragging the script. Unity then serializes those values and does not care about any script modification anymore. This can lead to confusion if, for instance, myVar is set to 20 inside the script after the fact, it will not be used. The serialization is written in the scene file.
The two lines in the example work exactly in the same way.
Possible solutions
It is possible to get Unity to consider new values in a script by pressing Reset on the settings wheel of the script component. That will also reset all the other variables of the component, so only do this if that is intended.
Making the variable private and omitting the attribute [SerializeField] will disable the serialization process, so Unity will no longer look in the scene file for a value to display - instead, the value will be created at runtime by the script.
When adding a component to Unity, a new object of the type of the component is created. The values that are displayed are the serialized values from that object. For this reason, only member values can be displayed and static variables are not, as they are not serializable. (This is a .NET specification, not strictly specific to Unity.) Because Unity does not serialize static fields, this is why adding the static modifier seemed to solve the problem.
Explaining the OP
In the OP case, based on the comments, your public field was showing a value of 1 in the editor. You thought this value was a default one, when it was actually the value you most likely gave to the field when originally declaring it. After you added the script as a component, you made the value 10 and thought it was buggy as it was still using the value of 1. You should now understand that it was working just fine, as designed.
What does Unity serialize?
By default, Unity will serialize and display value types (int, float, enum and so on) as well as string, array, List and MonoBehaviour. (It is possible to modify their appearance with Editor scripts, but this is off-topic.)
The following:
public class NonMonoBehaviourClass{
public int myVar;
}
is not serialized by default. Here again, this is .NET specification. Unity serializes MonoBehaviour by default as part of the engine requirement (this will save the content to the scene file). If you wish to display a "classic" class in the editor, just say so:
[System.Serializable]
public class NonMonoBehaviourClass{
public int myVar = 10;
}
Obviously, you cannot add it to a game object so you need to use within a MonoBehaviour:
public class MyScript:MonoBehaviour{
public NonMonoBehaviourClass obj = new NonMonoBehaviourClass();
}
this will display the object in the inspector and allow modifications to the myVar variable in the instance of NonMonoBehaviourClass. And again, any changes to myVar within the script will not be considered after the value is serialized and stored to the scene.
Extra tips on displaying things in the inspector
To finish, interfaces are not displayed in the inspector either since they don't contain any variables - just methods and properties. In debug mode, properties are not displayed by default. You can change this mode using the button with three lines in the top right corner of the Inspector. The first two settings are Normal/Debug. The first one is the default one, the second will also display private variable. This is useful to watch their values but cannot be altered from editor.
So if you need an interface to be displayed, you would have to consider an abstract class as it offers a similar functionality (except for multi inheritance) but can be a MonoBehaviour.
References:
http://docs.unity3d.com/ScriptReference/SerializeField.html
http://docs.unity3d.com/Manual/script-Serialization.html
https://www.youtube.com/watch?v=9gscwiS3xsU
https://www.youtube.com/watch?v=MmUT0ljrHNc
Title explains it all, I want to know how to access variables from another script. I've searched online, but found nothing that's worked.
You could make a class, instantiate an object of the class and access propterties.
Or you could use static variables.
Or even beter, lets say you have a GameManager.cs script attached to an empty object called GameManager. And you want to access its variables form the LevelManager.cs script. You do this inside the LevelManager.cs
public GameManager gameManager;
Then you can drag and drop your GameManager empty object to this public field, and everytime you want to access a variable you type gamemanager.yourVariableHere
Or, if you dont want to drag and drop:
in the start method...
void Start()
{
gameManager = GameObject.Find("GameManager");
//this way it finds your object automatically
}
Hope it helped, good luck.
First you need to make your variables public. Then get the GameObject, get the Componend and access your variable.
var variable = GameObject.Find("name").GetComponent<ScriptClass>().yourVariable;
To add to the previous answer, if your class is a pure c# class and doesnt inherit from monbehaviour then must create an instance of class. If you want global access to certain variables you should look into static variables or implement a singleton pattern
I have two objects that I will be mainly use inside of single class. I will initialize them at the beginning and use them throughout the life of the program. Now, my question is that if I should just create them as global variables and access them anywhere in the code (in side of single class) or I should create them as local variables and pass them as parameters to other functions. I just want to see what would be the best programming practice.
I am using C#.
Thanks.
In general you should avoid global variables. If it will be practical, I recommend keeping them as locals and passing them as parameters to your functions.
As Josh pointed out, if these variables are only used inside a single instance of the class, then you should just make them private (or protected) members of that class and be done with it. Of course, then they could only be passed in as parameters to other methods with the same access level (IE, private).
Alternatively, you may consider using the Singleton Design Pattern, which is slightly cleaner (and preferable) to using globals.
If the scope of the objects is the lifetime of the class they are instantiated in, then they should be private member variables.
If they do not maintain state themselves, then you should make them static classes.
You should still pass them around as variables, or at least create property accessors to get at the backing field. This way you can change implementation details without blowing up your code.
SOLID design principles are a good place to start when thinking about these things.
I have two objects that I will be
mainly use inside of single class. I
will initialize them at the beginning
and use them throughout the life of
the program.
This sounds like a perfect time to use a private static readonly variable. These can be initialized in their declaration, or you can make a static constructor to initialize them.
The fact that you are only referencing these objects within a single class is key point. There are other better ways to do things if these objects are ever needed outside of the single class.
If the objects will be the same for every instance of the class then
static const double PI = 3.14158;
You should generally use accessor methods (e.g. getters and setters) and keep your internal variables private. This way the rest of your code, outside of your class, is not dependent on your actual variables.
See this tutorial.
If your class is dependent on these 2 objects then they should probably be members on the class itself. Something like this (where A is the class you are talking about and B is one of the objects you initialize:
public class A
{
private B _b;
public A(B b)
{
_b = b;
}
public void DoSomething()
{
//do something with _b;
}
private void DoSomethingElse()
{
//do something else with _b;
}
}
In this example A is dependent on B (so you pass your instance of B into A's constructor or through some Dependency Injection framework). It wouldn't make a lot of sense for every method on class A to need a parameter of type B to be passed to it.
I think in this case you should ask what makes more sense. Is there some kind of relationship between the 2 objects and the new class. Also, how often are they used in the class.
Generally, If only a couple of methods use the objects, pass them around otherwise, instantiate them as class level variables (possibly using private static readonly as Jefferey suggests) and use them in the class. Making the code more readable should be your goal here.