|
Post by Flynn92 on Oct 2, 2021 18:19:24 GMT
Hello. I'm struggling to get to terms with the workings of World Variables. Is there a clean and easy way to "hook" into their values and listen for changes without using the WorldVariableListener? I find this class to be very restrictive as I can only have a single WorldVariableListener per WorldVariable; unless I am missing something?
|
|
|
Post by DarkTonic Dev on Oct 2, 2021 18:35:49 GMT
That's the only way. It's not restrictive if done properly. Your single Listener can notify other components that register with it if it wants to. For example, a number of public scripts you can add to your Inspector that you can notify. Think of the Listener as a Manager for changes on that World Variable.
Let me know if I should add some notes to the documentation to make that clearer.
Thanks!
|
|
|
Post by Flynn92 on Oct 2, 2021 18:40:00 GMT
Thank you for the sqift response. Could you perhaps provide a small example of how to register other scripts to a particular listener?
|
|
|
Post by DarkTonic Dev on Oct 2, 2021 18:45:16 GMT
Sure, see the code below. I added the following. Up top:
public YourScriptListener[] YourScriptListeners;
Drag your other Listeners into that field in the Inspector to "register" them. YourScriptListener isn't a real class name, use your actual class name here that you want to listen to the World Variable.
At the bottom of the UpdateValueInt method, added this:
foreach (var yourListener in YourScriptListener) { yourListener.NotifyOfWorldVariableChange(newValue); }
This means you would need to have a method called NotifyOfWorldVariableChange in your real class name. Hope that helps.
Here's the full code in context.
using UnityEngine; using System.Text;
using UnityEngine.UI;
namespace DarkTonic.CoreGameKit { [RequireComponent(typeof(Text))] [AddComponentMenu("Dark Tonic/Core GameKit/Listeners/World Variable Listener")] // ReSharper disable once CheckNamespace /// <summary> /// This class is used to listen to key events for a World Variable. /// </summary> public class WorldVariableListener : MonoBehaviour { public YourScriptListener[] YourScriptListeners;
// ReSharper disable InconsistentNaming /*! \cond PRIVATE */ public string variableName = ""; public WorldVariableTracker.VariableType vType = WorldVariableTracker.VariableType._integer; public bool displayVariableName = false; public int decimalPlaces = 1; public bool useCommaFormatting = true; public bool useFixedNumberOfDigits; public int fixedDigitCount = 8; // ReSharper restore InconsistentNaming /*! \endcond */
private int _variableValue; private float _variableFloatValue;
private Text _text;
// ReSharper disable once UnusedMember.Local void Awake() { _text = GetComponent<Text>(); }
void OnEnable() { WorldVariableTracker.UpdateAllListeners(); }
/// <summary> /// This Gets called when the integer World Variable's value changes. /// </summary> /// <param name="newValue">new value</param> /// <param name="oldVal">old value</param> public virtual void UpdateValue(int newValue, int oldVal) { _variableValue = newValue; var valFormatted = new StringBuilder(string.Format("{0}{1}", displayVariableName ? variableName + ": " : "", _variableValue.ToString("N0")));
if (!useCommaFormatting) { valFormatted = valFormatted.Replace(",", ""); }
if (_text == null || !SpawnUtility.IsActive(_text.gameObject)) { return; }
if (useFixedNumberOfDigits) { while (valFormatted.Length < fixedDigitCount) { valFormatted.Insert(0, "0"); } }
_text.text = valFormatted.ToString(); foreach (var yourListener in YourScriptListener) { yourListener.NotifyOfWorldVariableChange(newValue); } } } }
|
|
|
Post by Flynn92 on Oct 2, 2021 18:52:08 GMT
Thank you, that is very helpful. I think i'll edit a little more to remove the text box updates too. Very useful if only 1 listener is required but restrictive if you're wanting multiple listeners as I am. Thanks again!
|
|
|
Post by DarkTonic Dev on Oct 2, 2021 23:39:23 GMT
No problem.
The Textbox is only used by the main Listener. If you don't need it, you can remove it. You're free to put whatever code you like in your other Listener classes that notify the main Listener.
|
|
|
Post by hairgrow on Oct 12, 2021 2:28:41 GMT
How do you remove the Text Component when creating a subclass of the WorldVariableListener? I have a class called PlayerXP that derives from WorldVariableListener. When I try to remove the text component it can't because PlayerXP depends on it. This is due to the WorldVariableListener.
|
|
|
Post by DarkTonic Dev on Oct 12, 2021 4:56:03 GMT
That's actually on the roadmap to have a Listener without UI required. For now, just comment out the Required attribute and have at it.
|
|
|
Post by hairgrow on Oct 12, 2021 14:42:49 GMT
Gotcha. If possible, maybe the Text object could be an option. And if so, it should be a TextMesh Pro text. When testing the World Variable Listener it was helpful seeing it update in the scene, but it's not usable with the default Unity text.
|
|
|
Post by DarkTonic Dev on Oct 12, 2021 15:09:19 GMT
We actually already have a TextMeshPro option. You can install the package in Assets\Plugins\DarkTonic\CoreGameKit\3rd Party Plugin Integration for that. Why do you say the default Unity text is unusable?
|
|