0
\$\begingroup\$

I have attached a script (1) to the InputField for ease and it displays HA changing when I alter it during run time in the script. I have created another script (2) and attached it to the object I would like to move in order to retrieve this value and upon pressing of the space bar change the object's location.

No errors come up when running this and the object does change position, however for some reason it seems to always return the object to the same place (even after inputting a new value) with the Debug.Log returning 20 in the consoles...

I am fairly new to Unity so any help in explanations would be much appreciated.

(On another note: I would prefer to use enter rather than space so that after clicking enter for the input field it activates, but "KeypadEnter" doesn't seem to work. Any ideas?)

Script 1

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using static UnityEngine.RuleTile.TilingRuleOutput;

public class PointValHA : MonoBehaviour
{

    [SerializeField] private float HA;
    [SerializeField] private TransformerFW connect1;



    public void HAgrab(string inputHA)
    {

        HA = float.Parse(inputHA);

    }
    private void Start()
    {
        connect1.Transformer1(HA);
    }
//how I edited section
  public void Update()
  {
      connect1.Transformer1(HA);
  }

//end of edit
}

Script 2

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using Unity.VisualScripting;
using UnityEngine;

public class TransformerFW : MonoBehaviour
{
    public float HACheck;
    
    private float HA;
    
    public void Update()
    {
        
        if (Input.GetKey(KeyCode.Space))
        {
            HACheck = 1;
            UnityEngine.Debug.Log("Hellofailure");
            Transformer1(HA);
        }
    }
   
    public void Transformer1(float HA)
        {

            if (HACheck == 1) 
            {
                
                HA = Mathf.Cos(HA) * 5;
                transform.position = new Vector3(HA, HA, 0);
                UnityEngine.Debug.Log("Hellofailure2" + HA);
                HACheck = 0;
            }


        }
    public void Start()
    {
        if (HACheck != 1)
        {
            UnityEngine.Debug.Log("Hellofailure2" + HA);
        }
    }
    

}
\$\endgroup\$
4
  • \$\begingroup\$ I see your PointValHA script sends one value to the TransformerFW, once, in Start, then never communicates with it again. How were you planning to send the new value to the transformer after it changes? Remember that value type data like float numbers are passed by value, not by reference — so if the number is 0 on start, you send a copy of the number zero, not a reference to the variable that will later hold a different value. Changing the value of HA in the first script will not propagate that new value to the second script. Am I misunderstanding what you're trying to do here? \$\endgroup\$
    – DMGregory
    Commented Feb 7 at 1:57
  • \$\begingroup\$ No I am trying to send across the variable so that it changes when updated from the inputfield, so yeah thats a good point, however I have now changed it to update and it is still returning 20, would this method not work, or can it be altered to send the variable across rather than just 1 instance of the value? \$\endgroup\$
    – Stan
    Commented Feb 7 at 12:43
  • \$\begingroup\$ Can you show what you changed? \$\endgroup\$
    – DMGregory
    Commented Feb 7 at 12:48
  • \$\begingroup\$ As in I simply change it from public void start() to public void update() as in script 1 becomes using System.Collections; using System.Collections.Generic; using UnityEngine; using static UnityEngine.RuleTile.TilingRuleOutput; public class PointValHA : MonoBehaviour { [SerializeField] private float HA; [SerializeField] private TransformerFW connect1; public void HAgrab(string inputHA) { HA = float.Parse(inputHA); } public void Update() { connect1.Transformer1(HA); } } \$\endgroup\$
    – Stan
    Commented Feb 7 at 13:29

1 Answer 1

0
\$\begingroup\$

If you want to pass a reference to a live-updating value, it needs to be inside a reference type like a class that has its own independent lifetime:

[System.Serializable] // Makes this visible in Inspector.
public class LiveValue<T> {
    public T value;
}
public class Publisher : MonoBehaviour {
    [SerializeField] LiveValue<float> myFloat;
    [SerializeField] Subscriber subscriber;

    void Start() {
        subscriber.SubscribeTo(myFloat);
    }

    public void ParseNewText(string text) {
        if (float.TryParse(text, out float newValue) {
            myFloat.value = newValue;
        }
    }
}
public class Subscriber : MonoBehaviour {

    LiveValue<float> subscription;

    public void SubscribeTo(LiveValue<float> floatValue) {
        subscription= floatValue;
    }

    void Update() {
        // Do stuff with subscription.value
    }
}

But a more conventional/idiomatic way to set up this kind of pub-sub relationship is via the Observer Pattern, which is mostly a fancy name for events:

Using UnityEngine.Events;

public class Publisher: MonoBehaviour {
    public UnityEvent<float> OnFloatChanged;

    [SerializeField] cachedFloat;

    public void ParseNewText(string text) {
        if (!float.TryParse(text, out float newValue) 
            return; // Not a float; abort.

        if (cachedFloat == newValue) 
            return; // No change to report; abort.

        // Remember the latest value.
        cachedFloat = newValue;

        if (OnFloatChanged == null)
            return; // No listeners subscribed; abort.

        // Tell all listeners to update / act on the new value.
        OnFloatChanged.Invoke(newValue);
    }
}
public class Subscriber() : MonoBehaviour {

    public void OnValueChanged(float value) {
        // Do something with value
    }
}

The Publisher.OnFloatChanged event will show up in the inspector, just like click/text input events for UI components. You can use that to wire up Subscriber.OnValueChanged to listen to this event and receive calls when it fires. You can also add a listener through code if either party needs to be spawned dynamically.

The advantage of this approach is that it reduces coupling between these clases: note that Publisher no longer contains any reference to Subscriber or vice versa. That means you can re-use the same classes in many different combinations. Say you have a dozen different input fields that all need to convert text into a number then trigger a dozen different changes. Instead of writing a dozen copies of your text-to-number-and-forward script, you can write one, and just instantiate it once for each input, then wire the appropriate subscribing scripts to each one.

That does also come with a downside, in that the control flow is less explicit in your code: now it depends on the data of which subscribers are listening to which events. This can make debugging and reasoning about code more challenging in complex situations, but this scenario is straightforward enough that this should not be an issue.

\$\endgroup\$
4
  • \$\begingroup\$ Great thank you for the help will try implement it over this afternoon. I think the observer would be better to use as technically will need to take multiple variables from inputfields and do some maths with them to then get the final position vector. \$\endgroup\$
    – Stan
    Commented Feb 7 at 13:44
  • \$\begingroup\$ I'm having a couple issues. When I change the value the value of CachedFloat does change but how to I get this value to the subscriber, it is activating the subscriber when a value it changed I'm just struggling to figure out how the value then gets passed across. \$\endgroup\$
    – Stan
    Commented Feb 7 at 16:43
  • \$\begingroup\$ The value is passed as an argument to the event-handling function you provide. You can store it from there if you want. \$\endgroup\$
    – DMGregory
    Commented Feb 7 at 17:05
  • \$\begingroup\$ Yeah have got it working with just Publisher.HAUpdate in the subscriber to retrieve it once called. thanks for the help. Much appreciated \$\endgroup\$
    – Stan
    Commented Feb 7 at 18:07

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .