- Home /
"ArgumentException: The Object you want to instaintiate is null."
Hi everyone,
Recently I'm getting this ArgumentException while attempting to instantiate a Terrain.
I first click on a button, then the Run() void (code below) is executed.
The exception is thrown at line 33.
Code for LevelLoader.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class LevelLoader : MonoBehaviour {
public class LevelElemTag
{
public Dictionary<string, string> TagProperties = new Dictionary<string, string>();
}
public string fileName = "";
public void Run() {
if (!System.IO.File.Exists(fileName)) { throw new System.Exception("File " + fileName + " not found!"); };
//Load file content:
string[] fileContent = System.IO.File.ReadAllLines(fileName, System.Text.Encoding.Unicode);
//Process file:
foreach(string s in fileContent) //For each element (represented as a text line in the file)
{
//Read base properties:
Vector3 position = GetVector3(s,1);
Quaternion rotation = GetQuaternion(s, 2);
LevelElemTag data = GetTag(s, 3);
//What is -s-?
switch (GetNature(s))
{
case "tran":
//It's a train model
Instantiate(GetTrain(data), position, rotation);
break;
case "terr":
//It's a terrain
Instantiate(GetTerrain(data), position, rotation);
break;
case "rail":
//It's a rail
Instantiate(GetRailway(data), position, rotation);
break;
case "deco":
//It's a decoration
Instantiate(GetDecor(data), position, rotation);
break;
case "virt":
//It's an entity (controller, effect...)
Instantiate(GetEntity(data), position, rotation);
break;
default:
break;
}
}
}
string GetNature(string line)
{
return line.Split('|')[0];
}
Vector3 GetVector3(string line,int index)
{
string block = line.Split('|')[index];
float x = 0, y = 0, z = 0;
try
{
x = float.Parse(block.Split(';')[0]);
y = float.Parse(block.Split(';')[1]);
z = float.Parse(block.Split(';')[2]);
}
catch (System.Exception e)
{
throw e;
}
return new Vector3(x, y, z);
}
Quaternion GetQuaternion(string line, int index)
{
string block = line.Split('|')[index];
float w = 0,x = 0, y = 0, z = 0;
try
{
w = float.Parse(block.Split(';')[0]);
x = float.Parse(block.Split(';')[1]);
y = float.Parse(block.Split(';')[2]);
z = float.Parse(block.Split(';')[3]);
}
catch (System.Exception e)
{
throw e;
}
return new Quaternion(x,y,z,w);
}
LevelElemTag GetTag(string line, int index)
{
string block = line.Split('|')[index];
LevelElemTag my = new LevelElemTag();
foreach (string item in block.Split(';'))
{
my.TagProperties.Add(item.Split('=')[0], item.Split('=')[1]);
}
return my;
}
GameObject GetTrain(LevelElemTag meta)
{
GameObject model = (GameObject) Resources.Load("Trains/" + meta.TagProperties["family"] + "/" + meta.TagProperties["type"]) as GameObject;
return model;
}
Terrain GetTerrain(LevelElemTag meta)
{
Terrain model = (Terrain)Resources.Load("Objects/Terrains/" + meta.TagProperties["family"] + "/" + meta.TagProperties["type"]) as Terrain;
return model;
}
GameObject GetRailway(LevelElemTag meta)
{
GameObject model = (GameObject)Resources.Load("Objects/Rails/" + meta.TagProperties["family"] + "/" + meta.TagProperties["type"]) as GameObject;
return model;
}
GameObject GetDecor(LevelElemTag meta)
{
GameObject model = (GameObject)Resources.Load("Objects/Decor/" + meta.TagProperties["family"] + "/" + meta.TagProperties["type"]) as GameObject;
return model;
}
GameObject GetEntity(LevelElemTag meta)
{
GameObject model = (GameObject)Resources.Load("Objects/Entities/" + meta.TagProperties["family"] + "/" + meta.TagProperties["type"]) as GameObject;
return model;
}
}
Directory structure for the terrain:
Assets/Objects/Terrains/debug/grassy.prefab (as in the editor's Project window)
Values at runtime:
family is debug
type is grassy
Thanks in advance
Lorenzo
Answer by Bunny83 · Jul 15, 2017 at 06:31 PM
Your "Objects" folder is not located in a Resources folder. You can use Resources.Load only for assets stored in a Resources folder. Any other asset is not included in your build when it's not directly referenced by a script / component.
So the path should be
Assets/Resources/Objects/Terrains/debug/grassy.prefab
Btw: You currently do a double casting of the result of Resources.Load. Just use the generic version and remove all the casting:
Terrain model = Resources.Load<Terrain>("Objects/Terrains/" + meta.TagProperties["family"] + "/" + meta.TagProperties["type"]);
I also want to note that the way you parse your string is extremely inefficient. string.split will allocate a new array each time it is called.
Thank you for your answer @Bunny83 , but, how could I split the string in a more efficient way? Lorenzo
Your answer
Follow this Question
Related Questions
Access terrains "Alphamap 0" from within code 0 Answers
The problem of making large terrains 0 Answers
Terrain matrix 8*8 1 Answer
A question about terrain collision 1 Answer
How to export heightmap of a terrain during runtime. 0 Answers