Curious about "Singleton" (optimization) - c#

I have three of classes that I am using in my game and I got curious about Singleton pattern.
I have used singleton to access variables or functions easier and I didn't know how to access it without using a singleton pattern only except making "public GameObject" variable and assign object that has a script that I need in inspector.
under here is my sample code
public class ExampleClass : MonoBehaviour
{
public static ExampleClass instance;
private void Awake()
{
instance = this;
}
}
public GameObject assignScriptObject;
as you see, in the ExampleClass I used singleton pattern that I made
and at the las line is how I will assign script in inspector.
Is it fine to use Singleton pattern
(I call functions a lot by using that instance)
{i.e. ExampleClass.instance.LoadSomeFunctions() } there are dozens of lines with other functions
OR
Is it better to assign script in inspector
as an aspect of optimization.
THANKS!

Related

Awake function issues in relation to Singleton

So I was looking into implementing the new Unity input system into my game by reworking my code in my PlayerController script and got stuck pretty early on.
Here is the code that causes issues:
private PlayerInput playerInputController;
private void Awake()
{
playerInputController = new PlayerInput();
}
A green scribbly line appears under the 'Awake()' bit.
The code itself actually works, but it causes a lof of other issues, which makes a bunch of error messages appear saying:
NullReferenceException: Object reference not set to an instance of an object
The error messages all lead to places where I've used lines of code like this one in other scripts, to get variables and methods from my PlayerController script:
if (PlayerController.instance.isGroundedPhys)
Lastly, here's my singleton script, since it's likely relevant, as it's connected to my PlayerController script and allows it to be accessible from other scripts:
using UnityEngine;
public class Singleton<Instance> : MonoBehaviour where Instance : Singleton<Instance>
{
public static Instance instance;
public virtual void Awake()
{
if (!instance)
{
instance = this as Instance;
}
else
{
Destroy(gameObject);
}
}
}
This bit is at the top of my PlayerController script to make it accessible from other scripts:
public class PlayerController : Singleton<PlayerController>
{
I've been looking around and can't find anybody talking about similar issues. I think it's related to my singleton script, but I can't figure it out. :[
[Edit]:
I just found out it also gives this warning in the Unity console:
warning CS0114: 'PlayerController.Awake()' hides inherited member 'Singleton<PlayerController>.Awake()'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword.
PlayerInput is a MonoBehaviour!
No seriously, this is "Not Allowed" and you should actually give you an according warning in the console.
A MonoBehaviour "can"/should only exist attached to an according GameObject and always be created by the underlying c++ framework. It's a c# thing that Unity can't fully prevent you from using new to create one.
The only valid way of creating an instance of a MonoBehaviour are
Instantiate a prefab that has the component attached
use AddComponent on an existing GameObject
use the constructor of GameObject and pass in the according component type(s)
Or you probably rather want to use e.g. GetComponent or FindObjectOfType in order to get a reference to an already existing instance of PlayerInput.
And then the other warning means you implemented
public void Awake()
{
// ...
}
or similar in your PlayerController class. The warning already tells you exactly what to rather do:
// Use "override" in order to not hide the already existing implementation
// of "Awake" in the base class
public override void Awake()
{
// Make sure the base class behavior is executed
// this will initialize the Singleton thing
base.Awake();
// ... your additional behavior here
}

Member '<method>' cannot be accessed with an instance reference error in Singleton Unity

I've seen this question several times on the site, however most of the solutions seem to indicate that I should just make it an instance variable rather than a static one. However, the whole point of the Singleton pattern is this static object that's consistently referred to. Here are the links I have looked at:
Member cannot be accessed with an instance reference; qualify it with a type name
Member '<method>' cannot be accessed with an instance reference
This last link led me to the following:
What does the 'static' keyword do in a class?
And I feel I do understand this. The point of the Singleton is that all classes share this one instance so it feels perfect? I don't see the issue? It should be static according to Singleton conventions and frankly logic.
I'm in unity and am trying to make an inventory system for a game some fellow students and I are trying to make. I have the InventoryUI set up, however I would like to build a static inventory that is ever-present in the game. The InventoryUI will draw the necessary data from this Singleton class.
In other words, the PlayerInventory will act as the backend for the InventoryUI. The PlayerInventory will be a Singleton and the InventoryUI will draw the necessary data from PlayerInventory
Here is the relevant code for my Singleton class:
public class PlayerInventory : MonoBehaviour
{
private static PlayerInventory instance;
private PlayerInventory() { }
public static PlayerInventory getInstance()
{
if (instance == null)
return instance = new PlayerInventory();
return instance;
}
}
Here is the relevant code for my InventoryUI class:
public class PlayerInventoryUI : MonoBehaviour
{
//Inventory Instance
static PlayerInventory inventory;
void Start()
{
inventory = inventory.getInstance();
//cannot be accessed with an instance reference Error occurs here.
}
}
If possible, could someone explain to me why this error occurs as well as a possible solution.
That static method is in the class, not in an instance. So change your code in InventoryUI to this:
public class PlayerInventoryUI : MonoBehaviour
{
//Inventory Instance
static PlayerInventory inventory;
void Start()
{
inventory = PlayerInventory.getInstance();
//works because static methods are called from the class
}
}
I use Singletons with Unity a lot, have shared my pattern in a Quora answer: https://qr.ae/TSqaWt
Oh and if your Inventory is not in some GameObject Script component, it does not need to inherit from MonoBehaviour. Is better to use just a plain C# class if you don't need to use MonoBehaviour things like having Unity call Update on it.
If you wan't to have it as a script component, which can be nice to have it show in the inspector etc, then you should not 'new' it yourself but let Unity create it and assign the instance to the static reference when that happens. Is good to do that in Awake() so the singleton is already there when other scripts do Start()
Try the following instead:
inventory = PlayerInventory.getInstance();
You are attempting to call a static method on an (uninitialized) instance variable which is not allowed. Static methods must be qualified with the type (class) name, as the error suggests.
You have defined a static method inside a non static class, and although it's perfectly legal, the two should be thought of as seperate entities. Static methods only have access to static fields of the class, they cannot access any instance variables. The memory of static data members is allocated individually without any relation with the object.
Look at String.Parse() as an example, you wouldn't write mystring.Parse(), but instead you use the static method Parse of the String class which is always available and does not require a new string instance to use.
Hope this helps, if any further questions I will try to explain better.

What is MonoBehaviour in Unity 3D?

using UnityEngine;
using System.Collections;
public class VariablesAndFunctions : MonoBehaviour
{
int myInt = 5;
}
The full code is here Unity Official Tutorials
What is the purpose of MonoBehaviour
MonoBehaviour is the base class from which every Unity script derives. It offers some life cycle functions that are easier for you to develop your app and game.
A picture is worthy of thousands of words.
Source of the image: https://docs.unity3d.com/uploads/Main/monobehaviour_flowchart.svg
While the following statement is correct,
"MonoBehaviour is the base class from which every Unity script derives" -
I honestly feel it can be misleading to beginners. The phrase - "every Unity script" - being the culprit.
It gives a beginner the notion that all scripts created in unity must extend Monobehaviour. Which is not the case. You can create scripts that house classes that extend the c# base object class. In doing so, your script is then categorised as not a Unity script but nothing stops it from interacting with other Unity scripts and vice versa.
MonoBehaviour is another class that VariablesAndFunctions is inheriting from. This allows the inheritor to use the methods and variables of the other class providing they have the correct access level modifier set.
In the below example Class1 inherits from Base and so can use the protected method Method1
public class Base
{
protected void Method1 { /*...*/ }
}
public class Class1 : Base
{
public void Method2 { Method1(); }
}
Note in this particular example it would be better for Method1 to be marked as abstract or virtual so then Class1 can override it like so:
protected override Method1()
{
//...
base.Method1(); //Call the implementation of Method1 in Base here
//...
}
In particular though MonoBehaviour is described as being:
MonoBehaviour is the base class from which every Unity script derives.
Therefore when doing scripting in unity, you use this base class to better control how things are accessed so you do not need to do it yourself.
Monobehavior is what most of your scripts inherit from,
if you go to the documentation Click here!
you will see a bunch of variables and methods you get from this Inheritance.
such as:
Public Methods
Messages
Properties
Public Methods
Static methods
The most commonly used method (its under message in the documentation but honestly its better to see it as a function) is Update , its the main game loop, the speed at which the update function is called is based on your fps. But the important thing to take away is that if you didn't inherit from monobehavior, you wouldn't have access to this game loop.
Another important function that you get from Monobehavior is Start, which is called once on a script, and it's called after awake, so if you want to set some variables up you can do it here.
The important thing to take is that if you made a simple C# class that inherits from nothing, you wouldn't have access to these methods discussed. Monobehavior gives you access to many functions that help you build your game.
There are other behaviors your scripts can inherit from like ScriptableObject and StateMachineBehaviour, which give you access to other methods, but Monobehavior is the most common behavior your scripts will inherit from.
It's also good to note that whenever you use Monobehavior, it comes with a transform, some other scripts (Scriptable objects) don't come with a transform. The transform is simply a position in your game/scene where the gameobject lies its an x,y,z coordinate with rotation and scale.

Declare a variable class

i need to declare a variable class in my code so i can access a function (having the same name in all classes) but doing each time a different behavior).
and this is my code:
using UnityEngine;
using System;
using System.Collections;
public class Bubble : ItemBehaviour
{
// Use this for initialization
void Start ()
{
}
// Update is called once per frame
void Update ()
{
}
void OnMouseDown ()
{
theclass.Behaviour ();
}
}
knowing that (theclass gonna be variable ).
Thank you guys for your answer but it is a bit special.
My game is about interaction between player and game objects when the player approach any item that is "interactible" lets say, a bubble shows up, this bubble is a GameObject and it is the same for any object that allow interactions,
So since i am doing a 2D game i thought, it would be great if i make a "universal"
EmptyGameObject that contains all common aspects that anyObject would contain, and i grouped main functions and common ones in a general script and i added it to this emptyGameObject, then i added the Bubble prefab to this Game object and i a dded a code to it this code contains what i wrote in my firs post.
i was thinking that now each time i want an object i just drop this emptygameobject prefab and changes sprites and characteristics.
And each object have a different behavior (ex: i can delete an apple as if the character consumed it but i can not consume a door, the door would rather trigger an animation than being destructed ) i am specifying all this in a class for each item.
now whatever the class is (the object is) the trigger is in the bubble class (which i posted first) but the class will be different each time and i can not make a class that contains polymorphism because its not the same context each time.
I think you should create an interface that declares all the functions you would like to use in different classes.
interface IBehaviour
{
void Behaviour();
void AnotherBehaviour();
}
with this you define a behaviour what a class, which implements the interface, is capable of.
And then your classes would be:
class MyClass1 : Ibehaviour
{
}
class MyClass2 : IBehaviour
{
}
Apart from this you can use abstract classes. There are a lot of well-written articles about these topics on the Internet.
Firstly, I recommend to get familiar with OOP principles.
This link is a good way to start.
Good luck.
Thank you all,
The matter was solved by creating a global (abstract) gameOject that contains the class that we want to inherit from, and then each time the gameObject atached to this class calls (Behavior function) it trigger whatever the override is for this function for this object.

Instanced extension methods? C#

So I would like to create an extension method for a Type that the api has otherwise sealed.
If you know about extension methods the following should look familiar.
private static List<Member> memberList = new List<Member>();
public static List<Member> GetMemberList(this GameObject go)
{
return memberList;
}
Notice that to declare an extension method, it needs to be static, and because it needs to be static, the List that Im accessing through the GameObject type has to be static to.
I would like each GameObject to have its own list of Members. However Im pretty sure since this is a static field every instanced GameObject will point to the same static memberList.
So would my assumptions be true? And if so, what might be an alternative? I would like to avoid putting the GameObject in a wrapper class that also holds the memberList because the api only allows GameObjects to be detected and manipulated at runtime. There are ways to reverse reference the wrapper class through the gameObject but that adds a lot more complexity to the code i would like to avoid.
Yes, if you want to keep something outside the game object and access it through the extension method, it would have to be static.
You can use a dictionary to map one member list to each game object:
private static Dictionary<GameObject, List<Member>> memberLists = new Dictionary<GameObject, List<Member>>();
public static List<Member> GetMemberList(this GameObject go) {
return memberLists[go];
}
It appears you are working with Unity3. There is a related answer on the UnityAnswers site that may help: http://answers.unity3d.com/questions/22493/unity-3-sealed-class-gameobject-.html
It appears that there should be ways to attach the behaviors you want inherent in the Unity framework using the builtin scripting system.
Yes, you are right. If you have a static method, all instances of that class share the same data. The call return memberList; is illegal. It is the same as return this.memberList; and this is not available in a static method. Instead you'd have to call the class: return GameObject.memberList;. But I understand that you are not looking for this solution.
Extension methods are meant to create additional behavior. If you want to create additional data, extending the GameObject class using inheritance is the right choice.
Alternatively you could attach the memberList by using a dictionary of the form Dictionary<GameObject, List<Member>>. But personally I'd favor composition as shown below:
public class myGameObject
{
public List<Member> memberList { get; set; }
public GameObject go { get; set; }
}
private static ConditionalWeakTable<GameObject, List<Member>> dict = new ConditionalWeakTable<GameObject, List<Member>>();
public static List<Member> GetMemberList(this GameObject go)
{
return dict.GetOrCreateValue(go);
}
ConditionalWeakTable manages the object lifetime, because it uses weak-references. Therefore it doesn't stop the GC from collecting the GameObject if it there are no other live references to it, and this will also allow the List<Member> to be collected.
It is threadsafe, but this assumes that you want your starting point to be an empty list (the default constructor is called in GetOrCreateValue if there isn't a current value). If you want a different starting point, your threading issues become more complicated.
Extension methods are simply just static methods that "appear" to look like instance methods.
They however, do not add any additional functionality a static method doesn't, it's just for ease-of-use, maintenance, and readability. Extension methods cannot access protected / private members either.
If GameObject is not actually sealed (ie it doesn't have the sealed keyword), then you can write a class that inherits GameObject to gain access to its protected methods/fields/properties. This will only work if you yourself are the one constructing these objects.

Categories