I am attempting to modify FileBasedPlayerPrefs to where it can save at multiple locations.
Lets say I have a string called myString,
And I have a method that changes the string when called upon,
And in another script, it references that variable and prints whatever it is,
So when I call my method, it changes the string, and my other script prints that.
How would I go about doing this?
Thanks in advance!
EDIT
If I run this code, I get this error: error CS0120: An object reference is required for the non-static field, method, or property 'Config.myString'
//Config.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Config : MonoBehaviour
{
public string myString = "myValue1";
public void ChangeString(string changeStr)
{
myString = "myValue2";
}
}
//MyScript.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MyScript : MonoBehaviour
{
public string myStringReferece;
void Update() {
myStringReference = Config.myString;
}
}
You can use UnityEvent or standard C# Events. So when function X updates a string for example, it then also triggers an event and then all other scripts can subscribe to that event and act accordingly
Since there should be only one Config in the game usually, you actually could make it static or use a singleton pattern.
A static class cannot derive from MonoBehaviour, so you won’t be able to attach it to a game object, and it want automatically execute MonoBehaviour methods like Update(), Awake() and such. There’re some other important things you’ll need to learn eventually about static classes, like how and when do the static class constructor, fields and properties are initialized, and other things. It might be quite complicated for a novice.
Another option, a singleton is basically a usual MonoBehaviour script that you attach to a GameObject, but you declare a static reference to the instance of it so you could access it from anywhere. The main difference between a usual reference and a static reference is that static one affects all the objects of the same type. That’s why it should only be used when you have only one object of that type. Otherwise you’ll get to a point where all of your enemies lose their health when you hit only one of them, for example.
So, here’s a singleton approach:
public class Config : MonoBehaviour
{
// This is the static reference that could be used to access the Config script as a static object from anywhere
public static Config singleton;
public string myString = "myValue1";
void Awake()
{
// Here you assign the `singleton` reference to this object instance
singleton = this;
}
public void ChangeString(string changeStr)
{
myString = "myValue2";
}
}
public class MyScript : MonoBehaviour
{
public string myStringReferece;
void Update()
{
// To get the string in Config you use the static `singleton` reference of the `Config` class that is accessible without 'GetComponent'.
myStringReference = Config.singleton.myString;
}
}
–
If you need some other object to react somehow whenever the myString is getting changed, you can use C# event system, as one of the options.
I prefer the C# own event Action system because to me it seems the most easy to read and pretty convenient to use.
Events are useful when you want certain objects to react to some specific events in another class. It works as a subscription. The notifier (the class that broadcasts the message “Hey, I did something. Is anyone interested?”) should declare an event that it will trigger when the thing happened. The listener (the class that want to know if something has happened) should subscribe to the event by using the reference to the notifier class instance.
In the case of singleton, the listener won’t need the reference to the exact instance of the notifier though. Just like with accessing myScript via Config.singleton.myString, the subscription is also could be made with Config.singleton.myEvent.
Here is how you could use events:
using System; //To use C# events system you need the System namespace
public class Config : MonoBehaviour
{
// Declare the event that other classes will subscribe to if they want. The `Action<string>` means that the StringHasChanged event will send a string as an argument to anyone who has subscribed to this event.
public event Action<string> StringHasChanged;
public string myString = "myValue1";
public void ChangeString(string changeStr)
{
myString = "myValue2";
// The string has changed. Let's trigger the event:
StringHasChanged?.Invoke(myString);
}
}
The ? in the StringHasChanged?.Invoke(myString) is actually a prettier version of null check. Basically, this code also could be written like this:
if (StringHasChanged != null)
StringHasChanged.Invoke(myString);
It means that we check if the event action has any subscribers actually. If it’s null, then nobody is interested in this event, and it won’t be broadcasted to not waste the CPU resources.
So, how to react to the event? In the singleton case, you do it like this:
public class MyScript : MonoBehaviour
{
public string myStringReferece;
void Start()
{
// On start we do subscribe to the event
Config.singleton.StringHasChanged += OnConfigStringHasChanged;
// Here the `OnConfigStringHasChanged` is the method that will be executed if the `Config` sends the signal that the string has changed.
void OnConfigStringHasChanged(string newString)
{
Debug.Log(newString);
}
}
Then you make an instance of this object in your project, you can call it ConfigString or something. Then you just make a reference to it where ever you need to access it.