I am getting the infamous “A Native Collection has not been disposed, resulting in a memory leak. Enable Full StackTraces to get more details.” error, and I’m fairly sure I know why, but I 'm not sure how to fix it. I’m working on a jobified unit selection system, where I build a native array of Entities to pass into the job. Afterwards I dispose of the array. But I do not dispose of copy of the array inside the job. And quite frankly, I’m not sure how I would manage to. I’m using the array as a list which holds the currently selected units. This is necessary because I switch which units are being selected based on a “hostility-priority gauge”. The player can select, either their own units, the enemy units, or neutral units, but never a combination of the three. I’ll post the job for reference.
public struct SelectionJob : IJobForEachWithEntity<SelectableComponent, Translation>
{
public EntityCommandBuffer.Concurrent buffer;
public float3 lowerLeftPosition;
public float3 upperRightPosition;
public int selectingHostileLevel;//set to 0
public int numberOfCurrentSelected;//set to 0
public NativeArray<Entity> currentSelectedTemp;
public float3 camPos;
public float4x4 camProjMaxtrix;
public float3 camUp;
public float3 camRight;
public float3 camForward;
public float screenWidth;
public float screenHeight;
public int myID;
public NativeArray<bool> teamMatrix;
public void Execute(Entity entity, int index, ref SelectableComponent selectionData, ref Translation translation)
{
float2 entityPosition = ConvertWorldToScreenCoordinates(translation.Value, camPos, camProjMaxtrix, camUp, camRight, camForward, screenWidth, screenHeight, 1);
if (entityPosition.x >= lowerLeftPosition.x &&
entityPosition.y >= lowerLeftPosition.y &&
entityPosition.x <= upperRightPosition.x &&
entityPosition.y <= upperRightPosition.y)
{
int ownerID = selectionData.ownerID;
int ownerHostilityGauge = DeterminTeam(ownerID, myID, teamMatrix);
if (ownerHostilityGauge == selectingHostileLevel)
{
buffer.AddComponent<SelectedComponent>(index, entity);
if (selectingHostileLevel != 1)
{
currentSelectedTemp[numberOfCurrentSelected] = entity;
numberOfCurrentSelected++;
}
}
else if (selectingHostileLevel != 1)
{
if ((selectingHostileLevel == 0 && ownerHostilityGauge != 0) || (selectingHostileLevel == -1 && ownerHostilityGauge == 1))
{
selectingHostileLevel = ownerHostilityGauge;
int length = numberOfCurrentSelected;
for (int i = 0; i < length; i++)
{
buffer.RemoveComponent<SelectedComponent>(index, currentSelectedTemp[i]);
}
numberOfCurrentSelected = 0;
buffer.AddComponent<SelectedComponent>(index, entity);
if (selectingHostileLevel != 1)
{
currentSelectedTemp[numberOfCurrentSelected] = entity;
numberOfCurrentSelected++;
}
}
}
}
}
int DeterminTeam(int unitTeam, int myID, NativeArray<bool> teamMatrix)
{
//var teamMatrix = sceneManager.playerList[myID].playerTeamMatrix;
if (myID == unitTeam)
{
return 1;
}
else if (teamMatrix[unitTeam])
{
return -1;
}
else if (!teamMatrix[unitTeam])
{
return 0;
}
return 0;
}
public static float2 ConvertWorldToScreenCoordinates(float3 point, float3 cameraPos, float4x4 camProjMatrix, float3 camUp, float3 camRight, float3 camForward, float pixelWidth, float pixelHeight, float scaleFactor)
{
/*
* 1 convert P_world to P_camera
*/
float4 pointInCameraCoodinates = ConvertWorldToCameraCoordinates(point, cameraPos, camUp, camRight, camForward);
/*
* 2 convert P_camera to P_clipped
*/
float4 pointInClipCoordinates = math.mul(camProjMatrix, pointInCameraCoodinates);
/*
* 3 convert P_clipped to P_ndc
* Normalized Device Coordinates
*/
float4 pointInNdc = pointInClipCoordinates / pointInClipCoordinates.w;
/*
* 4 convert P_ndc to P_screen
*/
float2 pointInScreenCoordinates;
pointInScreenCoordinates.x = pixelWidth / 2.0f * (pointInNdc.x + 1);
pointInScreenCoordinates.y = pixelHeight / 2.0f * (pointInNdc.y + 1);
// return screencoordinates with canvas scale factor (if canvas coords required)
return pointInScreenCoordinates / scaleFactor;
}
private static float4 ConvertWorldToCameraCoordinates(float3 point, float3 cameraPos, float3 camUp, float3 camRight, float3 camForward)
{
// translate the point by the negative camera-offset
//and convert to Vector4
float4 translatedPoint = new float4(point - cameraPos, 1f);
// create transformation matrix
float4x4 transformationMatrix = float4x4.identity;
transformationMatrix.c0 = new float4(camRight.x, camUp.x, -camForward.x, 0);
transformationMatrix.c1 = new float4(camRight.y, camUp.y, -camForward.y, 0);
transformationMatrix.c2 = new float4(camRight.z, camUp.z, -camForward.z, 0);
float4 transformedPoint = math.mul(transformationMatrix, translatedPoint);
return transformedPoint;
}
}
If anyone has any ideas on how to dispose of this implementation of native array, your help will be appreciated.