- Home /
Attempting to add object to dynamic array causing problems
Hi guys,
I have the following code for a navpoint object in a game which features traffic in a city:
var connections : GameObject[];
function Start () {
// TODO: Find 3 closest waypoints facing the same direction, if connections array has no members.
var allWaypoints : GameObject[] = GameObject.FindGameObjectsWithTag("Road Navpoint");
//var waypoints : GameObject[];
var nearestDistanceSqr = Mathf.Infinity;
var nearestObj : GameObject = null;
for (var obj : GameObject in allWaypoints)
{
if (obj.transform.rotation == transform.rotation)
{
var objectPos = obj.transform.position;
var distanceSqr = (objectPos - transform.position).sqrMagnitude;
if (distanceSqr < nearestDistanceSqr)
{
nearestObj = obj;
nearestDistanceSqr = distanceSqr;
}
}
}
connections[0] = nearestObj;
}
If a waypoint has had its connections set in the editor, agents use those references when they get to a navpoint and decide where to go next. If they get to a navpoint where no connections have been specified, they go straight for 30m. The idea is to set up one connection (and eventually, three) for navpoints whose connections have not been specified in the editor, using scripting. What I want to do is take the nearest navpoint with the same rotation as an unconnected navpoint and add it to connections[]. However, running the code leads to the following error:
IndexOutOfRangeException: Array index is out of range.
(wrapper stelemref) object:stelemref (object,intptr,object)
CarNavpoint.Start () (at Assets/Game Logic/Scripts/CarNavpoint.js:34)
So the above code throws an out of range exception when trying to add an object to a dynamic array whose size hasn't been specified. What am I missing?
MachCUBED
Formatted your code. You can use the "edit" button to do so.
Answer by Kryptos · Aug 14, 2012 at 08:06 AM
This is not a dynamic array. You just declared a variable as an array but you didn't create it. Most people think the array is dynamic because you can edit it in the inspector. But in fact the variable is just serialized. So if you didn't specify its size in the inspector, the array will be of size 0.
So it is better to explicitly allocate the array. For example, you can do:
connections = new GameObject[10];
See the documentation for more details.
You fixed the assignment problem pretty well. I then discovered that it wasn't checking to see if the array hasn't been initialized yet, so I modified the code like this:
function Start () {
if (connections == null)
{
// TODO: Find 3 closest waypoints facing the same direction, if connections array has no members.
var allWaypoints : GameObject[] = GameObject.FindGameObjectsWithTag("Road Navpoint");
//var waypoints : GameObject[];
var nearestDistanceSqr = $$anonymous$$athf.Infinity;
var nearestObj : GameObject = null;
for (var obj : GameObject in allWaypoints)
{
if (obj.transform.rotation == transform.rotation)
{
var objectPos = obj.transform.position;
var distanceSqr = (objectPos - transform.position).sqr$$anonymous$$agnitude;
if (distanceSqr < nearestDistanceSqr)
{
nearestObj = obj;
nearestDistanceSqr = distanceSqr;
}
}
}
connections = new GameObject[3];
connections[0] = nearestObj;
Debug.Log("Unpopulated connections array filled");
}
else
Debug.Log("Pre-existing connections found.");
}
However, it's not populating the array if it's not set to anything. Is "null" the wrong keyword to use in the initial if statement?
So if you didn't specify its size in the inspector, the array will be of size 0.
A public variable is automatically serialized. Therefore an array is never null but of size 0 by default. You have to check the size:
if (connections.Length == 0)
But in order to prevent unnecessary headaches, I recommend to use a mixed check:
if (connections == null || connections.Length == 0)
It will work in all cases, both with public variables (serialized) and protected or private variables (non-serialized, by default).
It's been fixed to look like this:
function Start () {
if (connections == null || connections.Length == 0 || connections[0] == null) { // Find closest waypoint facing the same direction, if connections array has no members.
var allWaypoints : GameObject[] = GameObject.FindGameObjectsWithTag("Road Navpoint");
//var waypoints : GameObject[]; var nearestDistanceSqr = $$anonymous$$athf.Infinity; var nearestObj : GameObject = null;
for (var obj : GameObject in allWaypoints) {
if (obj.transform.rotation == transform.rotation)
{
var objectPos = obj.transform.position;
var relativePoint = transform.InverseTransformPoint(objectPos);
if(relativePoint.x > 0.0 || relativePoint.x < 0.0)
{
var distanceSqr = (objectPos - transform.position).sqr$$anonymous$$agnitude;
if (distanceSqr < nearestDistanceSqr)
{
nearestObj = obj;
nearestDistanceSqr = distanceSqr;
}
}
}
}
connections[0] = nearestObj;
Debug.Log("Unpopulated connections array filled");
} else Debug.Log("Pre-existing connections found."); }
However, the code for filtering out waypoints that are next to a waypoint when deter$$anonymous$$ing the next waypoint in a sequence:
... if(relativePoint.x > 0.0 || relativePoint.x < 0.0) { var distanceSqr = (objectPos - transform.position).sqr$$anonymous$$agnitude;
if (distanceSqr < nearestDistanceSqr)
{
nearestObj = obj;
nearestDistanceSqr = distanceSqr;
}
}
...
Doesn't appear to be in local space. It seems to be in global space ins$$anonymous$$d. How should it be made into local space?
That's a new question. Please create a new topic to keep the board clean.