I’ve looked around the forums for solutions to this but I didn’t find any that looked like they could apply to what I’m trying to do.
(Code will be provided for context)
I’m trying to use Normcore VR to sync an integer (mX) over the network. The integer syncs fine and updates the equation text. However, I need GraphSync (the Normcore part) to call an equation from the UnityEquationExample class. Actually, it’s the child of that class called DataSeriesXyEquation that is causing the problem. Currently, GraphSync is tring to call the function EvaluatePressed() every time mX is changed. The mEquationPlot1.Reveal = 2.0f is where the NullReferenceException error shows up.
After some debugging, I found that GraphSync Awake() is called before UnityEquationExample Awake() although I’m not sure that matters.
Since I’m not exactly sure what could be causing this (a lot of the code comes from other assets), I’ve included most all of the code:
GraphSync:
public class GraphSync : RealtimeComponent<GraphSyncModel> {
private UnityEquationExample equationScript;
private DataSeriesXyEquation equationPlot;
private int _mX;
// private string _equationText;
// private float _equationReveal;
private void Awake() {
Debug.Log("GraphSync AWAKE()");
equationScript = GetComponent<UnityEquationExample>();
equationPlot = GetComponentInChildren<DataSeriesXyEquation>();
_mX = equationScript.getX();
// _equationText = equationScript.getEquationText();
// _equationReveal = 0f;
}
protected override void OnRealtimeModelReplaced(GraphSyncModel previousModel, GraphSyncModel currentModel) {
if (previousModel != null) {
// Unregister from events
previousModel.mXDidChange -= MXDidChange;
//previousModel.equationTextDidChange -= EquationTextDidChange;
// previousModel.equationRevealDidChange -= EquationRevealDidChange;
}
if (currentModel != null) {
// If this is a model that has no data set on it, populate it with the current values.
if (currentModel.isFreshModel) {
currentModel.mX = equationScript.getX();
//currentModel.equationText = equationScript.getEquationText();
// currentModel.equationReveal = 2.0f;
}
// Update the values to match the new model (updating graph can't go here)
_mX = equationScript.getPowFromEquation();
Debug.Log("currentModel update getPowFromEquaiton(): " + equationScript.getPowFromEquation().ToString());
// _equationText = equationScript.getEquationText();
// Register for events so we'll know if the values change later
currentModel.mXDidChange += MXDidChange;
//currentModel.equationTextDidChange += EquationTextDidChange;
//currentModel.equationRevealDidChange += EquationRevealDidChange;
}
}
private void MXDidChange(GraphSyncModel model, int value) {
UpdateGraphModel();
Debug.Log("Sync via MXDidChange");
}
private void EquationTextDidChange(GraphSyncModel model, string text) {
UpdateGraphModel();
equationScript.updateEquationText(); // update the local graph text on change
Debug.Log("Sync via EquationTextDidChange");
}
/*private void EquationRevealDidChange(GraphSyncModel model, float value) {
UpdateGraphModel();
}*/
private void UpdateGraphModel() {
Debug.Log("Update Graph Model Called");
_mX = model.mX;
// _equationText = equationScript.getEquationText();
equationPlot.Reveal = 2.0f;
}
public void SetGraphX(int x) {
Debug.Log("SetGraphX(): " + x);
model.mX = x;
equationPlot = equationScript.getEquationPlot();
}
UnityEquationExample:
namespace GraphMaster {
public class UnityEquationExample : MonoBehaviour {
public InputField Equation;
public InputField XMax;
public InputField XMin;
public InputField YMax;
public InputField YMin;
public InputField InputResolution;
public Text ErrorLabel;
private Graph mGraph;
private DataSeriesXyEquation mEquationPlot1;
private int mXPow;
private GraphSync _graphSync;
public int MXPow {
get => mXPow;
set {
mXPow = value;
updateEquationText();
}
}
private void Awake() {
Debug.Log("equationExample AWAKE()");
mGraph = gameObject.GetComponent<Graph>();
_graphSync = GetComponent<GraphSync>();
mEquationPlot1 = mGraph.addDataSeries<DataSeriesXyEquation>("Simple Equation", Color.blue);
}
// Use this for initialization
private void OnEnable() {
if (mGraph == null) {
Debug.LogWarning("NGraph component not found. Aborting.");
return;
}
// Setup the graph
mGraph.setRangeX(-5, 5);
mGraph.setRangeY(-15, 15);
//mEquationPlot1 = mGraph.addDataSeries<DataSeriesXyEquation>("Simple Equation", Color.blue);
mEquationPlot1.Resolution = 0.05f;
mEquationPlot1.Equation = "pow(x, " + mXPow.ToString() + ")";
updateEquationText();
ErrorLabel.text = "";
Equation.text = mEquationPlot1.Equation;
InputResolution.text = mEquationPlot1.Resolution.ToString();
XMin.text = mGraph.RangeX.x.ToString();
XMax.text = mGraph.RangeX.y.ToString();
YMin.text = mGraph.RangeY.x.ToString();
YMax.text = mGraph.RangeY.y.ToString();
Debug.Log("Equation Awake: Reveal 2.0f");
mEquationPlot1.Reveal = 2.0f;
}
public void EvaluatePressed() {
ErrorLabel.text = "";
mXPow = getPowFromEquation();
try {
mEquationPlot1.Equation = Equation.text;
} catch (Exception ex) {
ErrorLabel.text = ex.Message;
}
// equation is pulled before instantiated
mEquationPlot1.Reveal = 2.0f;
RangePressed();
}
public void RangePressed() {
float res = float.Parse(InputResolution.text);
mEquationPlot1.Resolution = res;
float xMax = float.Parse(XMax.text);
float xMin = float.Parse(XMin.text);
float yMax = float.Parse(YMax.text);
float yMin = float.Parse(YMin.text);
mGraph.setRanges(xMin, xMax, yMin, yMax);
mEquationPlot1.Reveal = 2.0f;
}
public void updateEquationText() {
Equation.text = "pow(x, " + mXPow.ToString() + ")";
// _graphSync.SetEquationText(Equation.text);
EvaluatePressed();
}
public void increasePow() {
mXPow += 1;
updateEquationText();
_graphSync.SetGraphX(mXPow);
}
public void decreasePow() {
mXPow -= 1;
updateEquationText();
_graphSync.SetGraphX(mXPow);
}
// takes the mXPow out of the string (as long as it's the only thing between " " and ")". (Very specific to the function: "pow(x, <#>)"
public int getPowFromEquation() {
int space = Equation.text.IndexOf(" ");
int lp = Equation.text.IndexOf(")");
int length = lp - space;
string pow = Equation.text.Substring(space, length);
// return Convert.ToInt32(pow);
int powf = Convert.ToInt32(pow);
Debug.Log("powFromEquation = " + powf);
return powf;
}
public int getX() {
return mXPow;
}
public string getEquationText() {
return Equation.text;
}
public DataSeriesXyEquation getEquationPlot() {
return mEquationPlot1;
}
}
}
DataSeries Class (Parent Class of DataSeriesXyEquation that includes the equation variable):
namespace GraphMaster {
public abstract class DataSeries : MonoBehaviour {
protected float revealTime = 0.0f;
protected float elapsedRevealTime = 0.0f;
private float revealPercent = 0.0f;
protected bool finalizedReveal = false;
public float Reveal {
set {
Debug.Log("Reveal Called");
finalizedReveal = false;
elapsedRevealTime = 0.0f;
revealTime = value;
}
get {
return revealTime; // added for GraphSync (probably not used)
}
}
}
}
I might be misunderstanding the problem completely. Any help would be greatly appreciated. If any more information is needed please let me know.