Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help  NullReferenceException in ObiRopeCursor (build)
#5
(16-05-2023, 08:40 AM)josemendez Wrote: Could you share the entire script you're using?


Actors are initialized in OnEnable(), and that's called before Start() so the actor should be completely initialized by that point.

kind regards,

Yes, here is the script

Code:
using System.Collections.Generic;
using UnityEngine;
using CI.QuickSave;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using Obi;

public class SaveLoadManager : MonoBehaviour
{

    public InputField inputField;
    public ObiActor actor;
    public ObiRope tether;
    public ObiRopeCursor cursor;
    public List<GameObject> ObjectsToSave;
    public GameObject TMS_ROV;
    QuickSaveWriter writer;
    QuickSaveReader reader;
    SettingsManager sm;

    void Start()
    {
        var settings = GameObject.Find("Settings");
        sm = settings.GetComponent<SettingsManager>();

        if (sm.saveFile != "")
        {
            Load(sm.saveFile);
        }
        sm.scenarioLoaded = true;
    }

    public void Save()
    {
        if (inputField.text == "") return;
        writer = QuickSaveWriter.Create($"{SceneManager.GetActiveScene().name} - {inputField.text}");
        int idx = 1;
        foreach (var obj in ObjectsToSave)
        {
            writer.Write($"{idx}_{obj.name}_position", obj.transform.position);
            writer.Write($"{idx}_{obj.name}_rotation", obj.transform.rotation);
            idx++;

            if (obj.name == "TMS")
            {
                var ctrl = obj.GetComponent<HcuTmsController>();
                writer.Write("latched", ctrl.latched);
                writer.Write("latch_button", ctrl.latchedButton);
            }

            if (obj.name == "a-frame_edit")
            {
                var ctrl = obj.GetComponent<UmbilicalController>();
                writer.Write("frame_angle", ctrl.angle);
            }
            if (obj.name == "BULLET")
            {
                writer.Write("bullet_minAngle", obj.GetComponent<HingeJoint>().limits.min);
                writer.Write("bullet_maxAngle", obj.GetComponent<HingeJoint>().limits.max);
                continue;
            }
        }
        List<Vector3> positions = new();
        List<Vector3> velocities = new();
        for (int i = 0; i < actor.solverIndices.Length; ++i)
        {
            int solverIndex = actor.solverIndices[i];

            positions.Add(actor.solver.positions[solverIndex]);
            velocities.Add(actor.solver.velocities[solverIndex]);
        }
        writer.Write("tether_positions", positions);
        writer.Write("tether_velocities", velocities);
        writer.Write("tether_length", tether.restLength);

        writer.Commit();
        Debug.Log("Save complete!");

    }

    public void Load(string saveFile="test")
    {
        HcuTmsController ctrl = null;

        reader = QuickSaveReader.Create(saveFile);
        int idx = 0;
        foreach (var obj in ObjectsToSave)
        {
            idx++;

            if (obj.name == "TMS")
            {
                ctrl = obj.GetComponent<HcuTmsController>();
                ctrl.latched = reader.Read<bool>("latched");
                ctrl.latchedButton = reader.Read<bool>("latch_button");
            }


            if (obj.name == "a-frame_edit")
            {
                obj.transform.position = reader.Read<Vector3>($"{idx}_{obj.name}_position");
                obj.transform.rotation = reader.Read<Quaternion>($"{idx}_{obj.name}_rotation");
                var ctrl2 = obj.GetComponent<UmbilicalController>();
                ctrl2.Init();
                ctrl2.startAngle = reader.Read<Quaternion>($"{idx}_{obj.name}_rotation").eulerAngles.x;
                ctrl2.Rotate();
                continue;
            }
            if (obj.name == "BULLET")
            {
                continue;
            }

            obj.transform.position = reader.Read<Vector3>($"{idx}_{obj.name}_position");
            obj.transform.rotation = reader.Read<Quaternion>($"{idx}_{obj.name}_rotation");
        }

        // rope loading
        var positions = reader.Read<List<Vector3>>("tether_positions");
        var velocities = reader.Read<List<Vector3>>("tether_velocities");
        for (int i = 0; i < positions.Count; ++i)
        {
            int solverIndex = actor.solverIndices[i];
            actor.solver.positions[solverIndex] = positions[i];
            actor.solver.velocities[solverIndex] = velocities[i];
        }
        cursor.ChangeLength(reader.Read<float>("tether_length"));

        Debug.Log("Load complete!");
    }
}

I found the culprit!

I am using the Mirror networking package and it is enabling networked objects just after the complete scene load.
Since my rope is treated by Mirror as networked object, it was actually executing OnEnable and other methods a bit later than the normal offline gameObjects would.

So, my settings manager would initialize before the rope.

Thank you for your help, it went over my head that Mirror could be messing with execution order.
Reply


Messages In This Thread
RE: NullReferenceException in ObiRopeCursor (build) - by natko1412 - 16-05-2023, 09:46 AM