0

Background: I trying to make multidimensional scoring system for a live robotics competition.

Each team’s competes on a track with multiple challenges, across 5 rounds.

The referee scores the robots progress on a device this this application, pressing respective button to allocate each tasks score, which vary reach round.

Each round produces 4 values for each team’s score: Gross Score, Touches, Time & Net Score.

This part of the scoring system is working perfectly and is producing the data I want and is accessible in other scripts.

I have created a Scriptable Object to collate all this data in to the one place, so (potentially) to push it to a leaderboard table.

The Scriptable Object has built the way I want it to look like (whether this is the correct way forward, I don’t know)

The Scriptable Object, has 3 levels of data.

3 string variables for storing basic ‘current’ round data as I switch between scenes (scoring pages) and to interact with the main menu page.

There is then the ‘Team Data’ a list with data and a second list inside with each round data.

Team Data x number of team in the competition.

With 6 round lists containing the above round data achieved for each round. (as above).

I can access and manipulate the string data in the Scriptable Object, and from other scripts.

But, with sheer frustration, I can’t work out how to access and manipulate the data in the list(s).

I mainly want to do this from my ‘MenuManager’ Script. But also need to get the game data from the round scripts and pass them to the leaderboard table script.

This is the C# Script for the Scriptable Object

[CreateAssetMenu]
public class CurrentGameData : ScriptableObject
{
    public string currentCategory;
    public string currentRound;

    [System.Serializable]
    public class TeamDataContainer
    {
        public string TeamName;
        public int TeamID;
        public string TeamSchool;
        public string TeamCatID;
        public GameObject tableTeamLine;
        public List<RoundDataContainer> roundDataContainer = new();
    }

    [System.Serializable]
    public class RoundDataContainer
    {
        public string RoundID;
        public int GrossScore;
        public int Touches;
        public int Time;
        public int NetScore;
    }

    [SerializeField]
    public List<TeamDataContainer> teamRoundData = new();  
}

The Scriptable Object Layout

Scriptable Object Layout

The 'MenuManager' That is tring to interact with the contect

public class MenuManager : MonoBehaviour
{
    public GameObject categoryDropdownGO;
    public GameObject primaryDropdownGO;
    public GameObject secondaryDropdownGO;
    public GameObject openDropDownGO;

    [SerializeField]
    private CurrentGameData currentCategory;
    
    [SerializeField]
    private CurrentGameData currentRound;

    [SerializeField]
    private CurrentGameData currentGameData;


    //public TextMeshProUGUI[] teamCat; // this works, but it would mean adding every text object from every team!!!!!

    // Start is called before the first frame update
    void Awake()
    {
        var catDD = categoryDropdownGO.GetComponent<TMP_Dropdown>();
        var rndDD = categoryDropdownGO.GetComponent<TMP_Dropdown>();

        Debug.Log(currentGameData.teamRoundData[1].TeamName); // This isn't working

        if (currentCategory.currentCategory == "primary")
        {
            CategoryMenuSwitch(1);
            catDD.value = 1;
            catDD.RefreshShownValue();
            
        }

the //comment line is one of my may attempts to access the data.

Each 'TableTeamLine' Gameobject in the menu Scene and associated with the Scriptable Object has the script to be able to present the Team Data.

public class TeamTableData : MonoBehaviour
{
    public TextMeshProUGUI teamIDText;
    public TextMeshProUGUI teamNameText;
    public TextMeshProUGUI teamSchoolText;
    public TextMeshProUGUI teamCatText;
    public TextMeshProUGUI roundIDText;
    public TextMeshProUGUI grossScoreText;
    public TextMeshProUGUI touchText;
    public TextMeshProUGUI grossTimeText;
    public TextMeshProUGUI netScoreText;

}
Br Barry
  • 21
  • 8
  • in `Debug.Log(currentGameData.teamRoundData[1].TeamName); // This isn't working` .. what exactly does not working mean here? And if you want to react to something changing in the SO you still have to e.g. update your UI accordingly .. might want to add an `event` you can subscribe and react to when it is invoked – derHugo Aug 29 '23 at 12:13
  • And two more points: First I would use `TeamTableData` instead of `GameObject` for `tableTeamLine` so you directly have the correct component reference and access to its fields ... and then you are currently referencing **prefabs** (you can't have scene references in an asset like a ScriptableObject) => The instances of those prefabs you have in the scene are in no way affected by the changes you might make to the prefab assets on runtime – derHugo Aug 29 '23 at 12:28
  • @derHugo The Debug.Log line causes a NullReferenceException: Object reference not set to an instance of an object MenuManager.Awake (). Which I assumed that I am calling a single instance from the `currentGameData.teamRoundData[1].TeamName`. – Br Barry Aug 29 '23 at 22:49
  • @derHugo. The `GameObject` in `tableTeamLine` wasn't originally in the Scriptable Object. I put it there hoping it would link the instance of the `Team` **prefabs**, which is the line in the table in the team results are displayed. – Br Barry Aug 29 '23 at 23:04
  • Regarding the `NullReferenceException` I would assume this means that `currentGameData` isn't assigned ... regarding the other comment, your ScriptableObject is a data container - and further it is an asset and can not have any scene references -> it should be the other way round: The UI should have a reference to the SO, consume it and update its displayed content accordingly – derHugo Aug 30 '23 at 07:59
  • do you actually need the Inspector of the ScriptableObject? Or in other words why is it a ScriptableObject other then just sharing the reference between objects in the scene (which could as well be done with any scene component) .. do you need this across multiple scenes? In general I would recommend [UniRX](https://github.com/neuecc/UniRx) and make the whole thing reactive using `IObservable`s – derHugo Aug 30 '23 at 08:22
  • Ok, my original idea to go ScriptableObject was to: 1) retain and use some of the data across scenes, all the scoring data is created in other scenes, and I'm trying to pass it back to the **MainMenu** scene and present it in the Table, and retain it. 2) to export/import the data to CSV, to use in Excel (which was my next task once I solved the internal access problems). Can I achieve both these two goal with the UniRX?... _I think my floaties have fallen off, and I'm floundering in the deep end_... – Br Barry Aug 30 '23 at 11:43

1 Answers1

1

I finally figured out what I had what I had left out...

Although I have assigned public CurrentGameData currentGameData; (also originally creating it private as a [SerializeField]) I had not added the ScriptableObject to the script component in the inspector of the MenuManeger GameObject, which was drawing the error.

I have also removed the TableTeamLine out of the ScriptableObject and put them into a new list within the MenuManage, giving me direct access to the Table, as @derHugo suggested.

@derHugo, thanks for your suggestions and support. It did help to fix my problems, although indirectly.

Br Barry
  • 21
  • 8
  • Upvote for leaving an answer even though you solved it yourself offline. This might help someone else in the future. – Rocketman Dan Aug 30 '23 at 13:27
  • `I had not added the ScriptableObject to the script component in the inspector of the MenuManeger` .. this basically means you did **not** assign it ;) You only declared the field – derHugo Aug 30 '23 at 13:35