-1

I am working on creating a unidirectional flow framework in Unity.

Currently I am stuck on getting text updates to work the way I want. Here is how I would like it to work:

  1. I have a string stored on a script: myString
  2. I can bind any number of other string's to it: string1 = myString, string2 = myString etc
  3. When I change myString, all other bound strings change as well

Here is my (of course not working) code:

public class Binder : MonoBehaviour
{
  public Button button;

  public string buttonText = "Hi";

  void Start ()
  {
    buttonText = button.GetComponentInChildren<Text>().text;
  }

    // Update is called once per frame
    void Update ()
  {
    buttonText = Time.time.ToString();
  }
}

As is obvious, updating buttonText does not update the button.GetComponentInChildren<Text>().text (which stays at "Hi") because its just pointing buttonText to another string.

If string was an object, I could mutate the object and it would update all references. That would be awesome.

My question is: do you know how I can mutate a string so all other pointers to the same string will of course show the same value? For example, say I store the string "Hello" and have two UnityButtons. I set those two UnityButtons.text to that "Hello" string. When I change "Hello" to "Bye" both of those buttons text also change to "Bye"?

Aggressor
  • 13,323
  • 24
  • 103
  • 182
  • The answer here couldn't be simpler, you just use a property. FB's idea is silly, and really only conceptually meaningful when you're talking about large-scale database activities. Note that indeed, what FB means by their "Flow" system is nothing more than this: all they are saying is ***"work the same way on your high level db architecture, as ordinary properties work in any programming language"***. Their "flow" idea is indeed nothing more than the everyday "property" concept at the language level in c#. – Fattie May 28 '16 at 12:14
  • Secondly, Aggressor, I'm not sure if you are new to Unity (it's hard to remember everyone on here!) but you often get very **experienced** programmers who are **new** to Unity who tie themselves in knots because they have not stumbled on to UnityEvent .. http://stackoverflow.com/a/36249404/294884 .. which is the basic idea in Unity engineering. You use it constantly for everything. (Everything given to you by Unity that is already implemented, is done that way, and everything new you or I make is done that way.) Indeed, FB's "Flow" idea is, precisely, "UnityEvent" (on the architecture scale). – Fattie May 28 '16 at 12:18
  • I setup the dispatch system to use Unity Events and Actions but I was trying to also also bind script properities to the store so that bound properties are auto updated. The idea that I like most is the single store system. Theres one place where all instance (state) data resides. I just attach prefabs to the store and then update the store. Ive been experimenting though and Im pretty close to recreating it. The key benefit I 'think' is worth doing this for is the single state aspect. – Aggressor May 28 '16 at 13:40
  • sure it's just "a property" in c#. as in Prog's answer – Fattie May 28 '16 at 15:38
  • It is probably overkill :/ Thank you for your opinion :) – Aggressor May 28 '16 at 16:02
  • i would like to see some code, for what you have come up with. it could be I don't understand what your aim is, so it would be good to see it. – Fattie May 28 '16 at 16:22
  • I've edited Prog's answer to show how to put a UnityEvent INSIDE a property. I feel that does everything you say ... you can "point to" the store either in the Editor (drag) or easily in code. Maybe it helps! – Fattie May 28 '16 at 16:26
  • Its exactly like in that video. You have a dispatcher, domain stores (e.g. battle store, item store, character store), and views which react to store updates. But rather than doing a dispatch event when the store changes, I want to bind properties directly to the store. – Aggressor May 28 '16 at 17:06
  • I don't know how often I can repeat myself :) You could save an incredible amount of time if you spend 1 minute doing an experiment with UnityEvent. UnityEvent is exactly what you describe. Once you try it you will say "oh imagine that!" LOOK in Prog's answer, I put in the code for calling a UnityEvent from a property. As you say you **bind things directly to the store**. Can you see in the code in Prog's answer where it says "store". that would be the "store". OK? you can bind *anything* to it. – Fattie May 28 '16 at 18:07
  • Note that you say "rather than doing a dispatch event when the store changes, I want to bind things directly to the store". That does not make sense. When you **bind** a Thing to the store, what that **means** is that from that point on the **store** will send events **to** the Thing. Look at the Store code at the bottom of Prog's answer. You bind things to the store either using the drag mechanism in the Editor, or, you can easily do it in code (just google). – Fattie May 28 '16 at 18:10

1 Answers1

1

I don't think you can do with pointers. Although you can do it with another method. This can be accomplish with auto property in C#. Look at the code below. Each time buttonText is changed, the Button's texts will be automatically changed. You can add more Texts inside it.

If look closer, you will realized that I cached the Texts of the buttons in the Start function. You should always cache the variables and avoid using GetComponentInChildren repeatedly if you are gonna be using that variable multiple times.

void Start()
{
    buttonText1 = button1.GetComponentInChildren<Text>();
    buttonText2 = button2.GetComponentInChildren<Text>();
}

void Update()
{
    buttonText = Time.time.ToString();
}

public Button button1;
public Button button2;

Text buttonText1;
Text buttonText2;

string _buttonText = "HI";
public string buttonText
{
    set
    {

        _buttonText = value;

        //Change Text 1
        if (buttonText1 != null)
        {
            buttonText1.text = _buttonText;
        }

        //Change Text 2
        if (buttonText2 != null)
        {
            buttonText2.text = _buttonText;
        }
    }

    get
    {
        return _buttonText;
    }
}

Note that, indeed, you can put a UnityEvent inside a property. This creates a "store" that anything can follow. Simply set the "pointer" to the store.

If you haven't used UnityEvent with an argument before, the slightly annoying syntax is this...

[System.Serializable] public class ExplosionEvent:UnityEvent<int> {}
public ExplosionEvent:UnityEvent followExplosions;
// and then ...
if (followExplosions!=null) followExplosions.invoke(42);

So, to have

a UnityEvent inside a property

it's just..

public class HappyClass:MonoBehaviour
    {
    
    [System.Serializable] public class StoreEvent:UnityEvent<string> {}
    public StoreEvent followStore;
    string _store;
    public string store
        {
        set {
            _store = value;
            if (followStore!=null) followStore.Invoke(_store);
            }
        get { return _store; }
        }
    ...
Community
  • 1
  • 1
Programmer
  • 121,791
  • 22
  • 236
  • 328
  • Yes, of course this is trivially correct and true. The key point, Aggressor, is to see the overall "idea" there with FB's "Flow" thinking which, to repeat, is nothing more than "we want it to work the same way as properties in c#" - - !! In c# you use properties to do this as a matter of course. If you happen to program iOS also, it is even easier and more natural in Swift now (there's a "didSet" type of approach to properties). – Fattie May 28 '16 at 12:16
  • Yes I hadnt thought of doing it this way I was focused on trying to mutate. This might be more work than I had hoped but it will work. – Aggressor May 28 '16 at 13:41