Reputation: 21
I'm having an issue with a C# game I'm developing in Unity. While in the editor text notifications with animations are triggered, but not when I build and run.
I checked the Output Log and got this.
NullReferenceException: Object reference not set to an instance of an object
at NarrativeLocation+<InitializePanel>c__Iterator0.MoveNext () [0x00000]
in <filename unknown>:0
at UnityEngine.SetupCoroutine.InvokeMoveNext (IEnumerator enumerator,
IntPtr returnValueAddress) [0x00000] in <filename unknown>:0
UnityEngine.MonoBehaviour:StartCoroutine_Auto_Internal(IEnumerator)
UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator)
NarrativeLocation:Update()
Code for NarrativeLocation.Update
void Update()
{
if (!popupIsPlaying && GameState.popupQueue.Count != 0)
{
int temp = GameState.popupQueue.Dequeue();
StartCoroutine(InitializePanel(temp));
}
int num = 1;
while(inZone)
{
if (this.gameObject.tag == "NarrativeEvent" + num)
{
if (Input.GetKeyDown(KeyCode.E))
{
Destroy(GameObject.FindGameObjectWithTag("Notification"));
Destroy(GameObject.FindGameObjectWithTag("NarrativeEvent" + num));
Constants.GameState.popupQueue.Enqueue(num);
}
return;
}
num++;
}
}
Code for InitializePanel
IEnumerator InitializePanel(int num)
{
popupIsPlaying = true;
panel = GameObject.Find("Panel").GetComponent<PanelConfig>();
currentEvent = JSONAssembly.RunJSONFactoryForScene(1);
StartCoroutine(IntroAnimation());
panel.characterIsTalking = true;
panel.Configure(currentEvent.dialogues[num - 1]);
yield return new WaitForSeconds(6f);
StartCoroutine(ExitAnimation());
Debug.Log("Event " + num + " destroyed");
popupIsPlaying = false;
}
public IEnumerator IntroAnimation()
{
panelAnimator.SetBool("IntroAnimationIn", true);
yield break;
}
public IEnumerator ExitAnimation()
{
panelAnimator.SetBool("IntroAnimationIn", false);
yield break;
}
When I run the game, the panel pops up with no text. The Exit Animation doesn't seem to be called either.
The JSON Assembly Class.
namespace JSONFactory {
class JSONAssembly {
private static Dictionary<int, string> _resourceList = new Dictionary<int, string>
{
{1, "/Resources/GameScript.json"}
};
public static NarrativeEvent RunJSONFactoryForScene(int sceneNumber)
{
string resourcePath = PathForScene(sceneNumber);
if (isValidJSON(resourcePath) == true)
{
string jsonString = File.ReadAllText(Application.dataPath + resourcePath);
NarrativeEvent narrativeEvent = JsonMapper.ToObject<NarrativeEvent>(jsonString);
return narrativeEvent;
}
else
{
throw new Exception("JSON is not valid");
}
}
private static string PathForScene(int sceneNumber)
{
string resourcePathResult;
if (_resourceList.TryGetValue(sceneNumber, out resourcePathResult))
{
return _resourceList[sceneNumber];
}
else
{
throw new Exception("Scene not in resource list");
}
}
private static bool isValidJSON(string path)
{
return (Path.GetExtension(path) == ".json") ? true : false;
}
}
}
Upvotes: 2
Views: 567
Reputation: 1
In builds, you cannot use a resources path to load files at runtime using File.ReadAllText. Files in Resources/ directories get packaged into a proprietary packed-asset format during the build process and cannot be retrieved b path that way.
You must use the Resources api if you want to load files that way.
However, files placed in Application.streamingAssetsPath
(aka /Assets/StreamingAssets
) CAN be read at runtime this way. Files in that folder are preserved as is. They could be accessed by
System.IO.Path.Combine(
Application.streamingAssetsPath, "/Path/To/file.json");
// assuming path is:
// /Assets/StreamingAssets/Path/To/file.json
Resources is probably closer to what you want.
Alternatively, Unity imports json files (or any other text file for that matter) as TextAssets
. You can reference these TextAsset
files in the inspector like any other type of asset.
public class MyMono : MonoBehaviour
{
public TextAsset json;
void Start() {
Debug.Log(json.text);
}
Upvotes: 0
Reputation: 125305
While in the editor text notifications with animations are triggered, but not when I build and run.
I can spot few possible reasons why your code is not working in a build. There could be more that I missed but see them below:
1. Where you are trying to load the json file from:
{1, "/Resources/GameScript.json"}
A. When reading from the Resources folder, you do not include the "Resources" in the path. The path is relative to the Resource folder.
B. Do not include the file extension names such as .txt, .jpeg, .mp3 in the path.
To fix both, replace:
{1, "/Resources/GameScript.json"}
with
{1, "GameScript"}
2. How you are currently reading the file:
string jsonString = File.ReadAllText(Application.dataPath + resourcePath);
You are currently reading the file with File.ReadAllText
. This will work in the Editor but not in a build because that's not how to read a file in the Resources folder.
Files in the Resources folder are read with the Resources API.
To fix this, replace:
string jsonString = File.ReadAllText(Application.dataPath + resourcePath);
with
TextAsset txtAsset = Resources.Load<TextAsset>(resourcePath);
string jsonString = txtAsset.text;
Make sure that the json file is placed in a folder named "Resources" in your project and that must be spelled correctly.
Other issues will likely run into later on:
Infinite loop:
The while(inZone)
code doesn't have a way to to exit, If you ever run into that, you risk causing your program to freeze because there is no code to make inZone
false in that loop. You have to find a way to re-write that code.
Upvotes: 2