Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Yielding and NullReferenceException

Discussion in 'Scripting' started by ozzwozz, Jan 23, 2018.

  1. ozzwozz

    ozzwozz

    Joined:
    Sep 15, 2015
    Posts:
    39
    Hi I have two errors that appear when I run my app, the first is:
    "You are trying to load data from a www stream which has not completed the download yet.
    You need to yield the download or wait until isDone returns true."
    Then the second is:
    "NullReferenceException: A null value was found where an object instance was required."
    The www section was originally in an IEnumerator function however it was causing too many issues and I decided it was best not to use this as it was causing too many errors that I could not fix.
    Code (csharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. public class Userdata : MonoBehaviour
    6. {
    7.     string url = "http://localhost/Wellbeing/userdata.php";
    8.     public string[] users;
    9.     public string[,] userArray;
    10.     public string[] User = new string[2];
    11.     private int nRow;
    12.     private string[] Temp;
    13.     private string userDataString;
    14.     private bool value = false;
    15.     public string[] CallDetail(string UsernameInput, string PasswordInput)
    16.     {
    17.         Debug.Log("hi");
    18.         WWW userData = new WWW(url);
    19.         string userDataString = userData.text;
    20.         //splits the data taken from the url and splits it into a 2d array
    21.         //splits each section of information into strings of each users data
    22.         users = userDataString.Split(';');
    23.         Debug.Log(users);
    24.         //iterates through the strings and splits the into indiviual fields of data
    25.         for (var item = 0; item <= users.Length; item++)
    26.         {
    27.             Temp = users[item].Split('|');
    28.             //stores each of piece of data in the 2D array
    29.             for (var field = 0; field <= Temp.Length; field++)
    30.             {
    31.                 userArray[nRow, field] = Temp[field];
    32.             }
    33.             nRow++;
    34.         }
    35.        
    36.         //iterates through each row in the 2D array and searches for the Username and password that has been input
    37.         for (var item = 0; item < userArray[item, 0].Length; item++)
    38.         {
    39.             if (userArray[item, 2] == UsernameInput && userArray[item, 1] == PasswordInput)
    40.             {
    41.                 //stores each piece of relevant data into an array
    42.                 User[0] = userArray[item, 1];
    43.                 User[1] = userArray[item, 2];
    44.                 User[2] = userArray[item, 6];
    45.             }
    46.         }
    47.         return User;
    48.     }
    49. }
    50.  
     
  2. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    I just don't think it's going to work there. You should move it back to a coroutine, so you can yield on the result.
    I'm not sure about all the rest of your code, but it looks as though you're assigning at least 1 extra string to the User array (than its size).

    Not sure where your null ref error is, but maybe because you're using the data early and it's not ready?
    If it's something else, you should say what it is. We can't guess it :)

    If you need to know when it's done and/or return information, you could pass in a delegate for a callback at the end of the coroutine.
     
  3. ozzwozz

    ozzwozz

    Joined:
    Sep 15, 2015
    Posts:
    39
    Okay I've done this, and sorted the issue with the adding too many strings to userArray however it now is saying "cannot implicitly convert type 'System.Collection A2 Project Program s.IEnumerator' to 'string[]' when I run the program, the error is being highlighted on the getcomponent in the main script where I call the IEnumerator
     
  4. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Right, well send a delegate (callback) as a parameter to the coroutine. Then, when it's done you can either return the string array directly or just take the callback as an indication that the string array is ready for you (like a signal/flag of sorts).
     
  5. ozzwozz

    ozzwozz

    Joined:
    Sep 15, 2015
    Posts:
    39
    I haven't heard of these before could you give an example? Or maybe explain how they work?
     
  6. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Sure, I can try to show you an example.
    Code (csharp):
    1.  
    2. // at the top of your script
    3. using System;
    4. void MethodThatCallsCoRoutine() {
    5.     Action act = AfterCoroutine;
    6.     StartCoroutine(YourRoutine(act));
    7.  
    8. }
    9. // obviously you might have other variables, too.
    10. IEnumerator YourRoutine(Action act) {
    11.  //your code here..
    12.  // at the end, when you're done
    13.    if(act != null) act(); // this calls the method referenced by 'act'.
    14. }
    15. void AfterCoroutine(){
    16.    // in here, you know that the stuff you needed is done, unless there was an error.
    17.    // so just check that whatever you need is valid before using it, then proceed :)
    18. }
    that's an action, which is just void delegate. In this case, no parameters are used.
    An action can have parameters, too.

    You can search for "System.Action C#" or "delegate c#" or "actions and delgates c#". Stuff like that, I'm sure you'll find some docs & examples, etc..

    Hope that helps. This way your code can run and you can be notified when it's done. Or if you go the route of passing variables, you can do that. This is assuming you can't finish everything you need in the coroutine itself, of course.

    Generally speaking, it's good to know about actions/delegates/events. (Events are almost the same thing). :)[/code]
     
  7. ozzwozz

    ozzwozz

    Joined:
    Sep 15, 2015
    Posts:
    39
    Ahhhh, okay thanks. Is there a way to show the user that the program is doing something and hasn't frozen or crashed? or does it have to just be left alone to do its thing?
     
  8. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Can you show a message to the the user in Unity? Why, yes you can :)

    An idea is, if you think it's going to take a little bit of time, in addition to showing a message if you want, you can break the coroutine into smaller sections with some yield return null(s).

    I'm not sure, is this just for loading at the start or it happens often? If it's not too long and rarely happens, it's up to you..
     
  9. ozzwozz

    ozzwozz

    Joined:
    Sep 15, 2015
    Posts:
    39
    The are several points that it would be quite useful to have a "loading screen" or "message", as from what I understand WWW can take a few seconds