Search Unity

Noob here, help needed :) Reference code from another script not working

Discussion in 'Scripting' started by DigitalHardware, Jun 2, 2020.

  1. DigitalHardware

    DigitalHardware

    Joined:
    Oct 30, 2016
    Posts:
    12
    Hello, I'm a designer by trade so whilst I pretend to understand bits n pieces of C# even the most simple things sometimes just feel like an alien concept to me and I struggle to understand how things work.

    Many thanks in advance for your help!

    The scenario:

    You're driving around a track - you have your lap time, current lap time and best lap time being displayed onscreen, along with your score, all updated in realtime. Cool, that all works.

    You pass the finish line and the code says "Hey, let's show the player how they did!". Currently, time left (in seconds), the score and your total score are made to appear in the middle of the screen. Again, that all works ok.

    What I want to do next - and where I'm having a problem:
    Next step is to also show the final lap time (it doesn't have to be the best lap time, just the last lap time will do) when the lap is complete (alongside the other info I mention above).

    So, I have two scripts, please see below.

    First, the error message in Unity:
    FinishLevel.cs(33,28): error CS0120: An object reference is required for the non-static field, method or property 'UIController.lastLapTime'

    For your reference, the line referred to in the error is:
    Code (CSharp):
    1. yourFinalLapTime = UIController.lastLapTime;
    SCRIPT 1: UICONTROLLER.CS
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5. using TMPro;
    6.  
    7. public class UIController : MonoBehaviour
    8. {
    9.     public GameObject UIRacePanel;
    10.  
    11.     public TextMeshProUGUI UITextCurrentLap;
    12.     public TextMeshProUGUI UITextCurrentTime;
    13.     public TextMeshProUGUI UITextLastLapTime;
    14.     public TextMeshProUGUI UITextBestLapTime;
    15.  
    16.     public Player UpdateUIForPlayer;
    17.  
    18.     private int currentLap = -1;
    19.     private float currentLapTime;
    20.     public float lastLapTime; //This WAS private but I couldn't access it, so I made it public
    21.     private float bestLapTime;
    22.  
    23.     void Update()
    24.     {
    25.         if (UpdateUIForPlayer == null)
    26.             return;
    27.  
    28.         if (UpdateUIForPlayer.CurrentLap != currentLap)
    29.         {
    30.             currentLap = UpdateUIForPlayer.CurrentLap;
    31.             UITextCurrentLap.text = $"LAP: {currentLap}";
    32.         }
    33.  
    34.         if (UpdateUIForPlayer.CurrentLapTime != currentLapTime)
    35.         {
    36.             currentLapTime = UpdateUIForPlayer.CurrentLapTime;
    37.             UITextCurrentTime.text = $"TIME: {(int)currentLapTime / 60}:{(currentLapTime) % 60:00.000}";
    38.         }
    39.  
    40.         if (UpdateUIForPlayer.LastLapTime != lastLapTime)
    41.         {
    42.             lastLapTime = UpdateUIForPlayer.LastLapTime;
    43.             UITextLastLapTime.text = $"LAST: {(int)lastLapTime / 60}:{(lastLapTime) % 60:00.000}";
    44.         }
    45.  
    46.         if (UpdateUIForPlayer.BestLapTime != bestLapTime)
    47.         {
    48.             bestLapTime = UpdateUIForPlayer.BestLapTime;
    49.             UITextBestLapTime.text = bestLapTime < 1000000 ? $"BEST: {(int)bestLapTime / 60}:{(bestLapTime) % 60:00.000} " : "BEST: NONE";
    50.         }
    51.     }
    52. }
    53.  
    SCRIPT 2: FINISHLEVEL.CS
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5. using TMPro;
    6.  
    7. public class FinishLevel : MonoBehaviour
    8. {
    9.     public GameObject levelMusic;
    10.     public AudioSource levelComplete;
    11.     public GameObject levelTimer;
    12.     public GameObject LevelFinishPanel;
    13.     public GameObject timeLeft;
    14.  
    15.     public GameObject theScore;
    16.     public GameObject totalScore;
    17.  
    18.     public GameObject yourLapTime;
    19.     public float yourFinalLapTime;
    20.    
    21.     public int timeCalc;
    22.     public int scoreCalc;
    23.     public int totalScored;
    24.    
    25.     void OnTriggerEnter()
    26.     {
    27.         timeCalc = GlobalTimer.extendScore * 100;
    28.         timeLeft.GetComponent<TextMeshProUGUI>().text = "Time left: " + GlobalTimer.extendScore + " x 100";
    29.         theScore.GetComponent<TextMeshProUGUI>().text = "Score: " + GlobalScore.currentScore;
    30.         totalScored = GlobalScore.currentScore + timeCalc;
    31.         totalScore.GetComponent<TextMeshProUGUI>().text = "Total score: " + totalScored;
    32.  
    33.         yourFinalLapTime = UIController.lastLapTime;
    34.         yourLapTime.GetComponent<TextMeshProUGUI>().text = "Your lap time: " + yourFinalLapTime;
    35.  
    36.         levelMusic.SetActive(false);
    37.         levelTimer.SetActive(false);
    38.         levelComplete.Play();
    39.         StartCoroutine(CalculateScore());
    40.     }
    41.  
    42.     IEnumerator CalculateScore()
    43.     {
    44.         LevelFinishPanel.SetActive(true);
    45.         yield return new WaitForSeconds(0.5f);
    46.  
    47.         yourLapTime.SetActive(true);
    48.         yield return new WaitForSeconds(0.25f);
    49.  
    50.         timeLeft.SetActive(true);
    51.         yield return new WaitForSeconds(0.5f);
    52.        
    53.         theScore.SetActive(true);
    54.         yield return new WaitForSeconds(0.5f);
    55.        
    56.         totalScore.SetActive(true);
    57.         yield return new WaitForSeconds(0.5f);
    58.     }
    59. }
    60.  
     
  2. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,909
    You need an instance of UIController, you can't access the fields straight from the class (how would that work if you had multiple instances of it?).

    It's also a little odd that you're using raw GameObject references for all of your fields and then calling GetComponent() - why not just have a reference straight to the component? It will make your life simpler. In short:
    • Make a UIController field on your FinishLevel.cs:
    Code (CSharp):
    1. public UIController controller;
    • Assign this reference to your UI Controller in the inspector from your scene.
    • Then use that in your code:
      Code (CSharp):
      1. yourFinalLapTime = controller.lastLapTime;
     
  3. DigitalHardware

    DigitalHardware

    Joined:
    Oct 30, 2016
    Posts:
    12
    Thanks @PraetorBlue
    The error is now gone but the Lap time is showing as "0". Screenshot attached.
    Any idea why that is?

    Many thanks.

    P.S. as I said, I'm not a coder by profession, so whilst I understand your reference about GameObjects I wouldn't know to do that :) I've put this project together from watching videos and hacking together code, tweaking it, see what works etc.

    laptime_missing.jpg
     
  4. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,909
    Do you have more than one UIController component in your scene?
     
  5. DigitalHardware

    DigitalHardware

    Joined:
    Oct 30, 2016
    Posts:
    12
    Not that I know of, here's a screenshot...

    hierarchy_assets.jpg
     
  6. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,909
    In your scene hierchy window there's a little search bar at the top. Would you mind doing this search?:
    t: UIController
     
  7. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,909
    Also one other thing. I notice that UIController is actually reading its lastLapTime value from UpdateUIForPlayer.LastLapTime. Maybe your FinishLevel script should do the same? Maybe UIController hasn't gotten the updated lap time yet by the time you're reading it in FinishLevel?
     
    DigitalHardware likes this.
  8. DigitalHardware

    DigitalHardware

    Joined:
    Oct 30, 2016
    Posts:
    12
    Sure, see screenshot...

    hierarchy_search.jpg
     
  9. DigitalHardware

    DigitalHardware

    Joined:
    Oct 30, 2016
    Posts:
    12
    Good idea!

    So, I replaced this line:
    Code (CSharp):
    1. yourFinalLapTime = controller.lastLapTime;
    With this line in the LevelFinish file:
    Code (CSharp):
    1. yourFinalLapTime = controller.UpdateUIForPlayer.LastLapTime;
    Result:
    The same as before, shows a "0".
     
  10. DigitalHardware

    DigitalHardware

    Joined:
    Oct 30, 2016
    Posts:
    12
    Ok, I ran the race for two laps and then the lap time WAS shown in place of 0 o_O
     
  11. DigitalHardware

    DigitalHardware

    Joined:
    Oct 30, 2016
    Posts:
    12
    Would anyone else like to forward some suggestions please?
     
  12. mistergreen2016

    mistergreen2016

    Joined:
    Dec 4, 2016
    Posts:
    226
    yourFinalLapTime = UIController.lastLapTime;
    UIController is never defined.
    Debugging is a skill you'll have to learn as well.

    Add to see if it's defined.
    Debug.Log("UIController: "+ UIController);

    Usually I Find the GameObject at Start() in Findishlevel.cs.
    like
    UIController = GameObject.Find("UIController").GetComponent<UIController>();
     
  13. DigitalHardware

    DigitalHardware

    Joined:
    Oct 30, 2016
    Posts:
    12
    Thanks for the reply.

    That's because, if you see previous suggestions from PraetorBlue, you'll see that additional code has been added to the script since my original post. In other words, UIController is now defined, but it still doesn't work.

    Debugging? I couldn't agree more! I'm trying! ;)
     
  14. mistergreen2016

    mistergreen2016

    Joined:
    Dec 4, 2016
    Posts:
    226
    Did you drag the UIcontroller gameobject into the public controller field? If not, you haven't defined it.

    Yeah, learn how to use break points or simple log for variables in the code. They will tell you what have been or not been defined.