EDIT: The problem was that I have a List of game objects, that I convert into entities and then when I need to place that auto/entity on the road I make a new instance of the original entity. Those Entity-Prefabs are the ones that caused my problem. NOT Unity at all!
Ok, I have an odd situation, and I can’t think of a short way to state this so…
I have an road asset (Easy Roads 3D, HIGHLY recommend, good asset, FANTASTIC support) and it has lane data (a series of Vector3 points)
So, when my game starts I create a series of entities:
- Autos and their current set of lane points
- Roads and their lanes
In my System it moves the Auto from point to point, and when it reaches the end of the Auto’s current set of points, it gets the next set.
So simple right? So as you look at the code below you’ll see that each Auto is now assigned an ‘identity’ (this is for debugging) and only one Auto is not being created (the issue ONLY happens with the first Auto, I have tested it with all roads get an Auto, and yea, the output showed only Identity=0 has the issue)
First we make the roads and each road gets the opportunity to get an auto (percentageLanesPopulated is set to 100)
private void CreateRoadEntities()
{
var roadEntityArchetype = entityManager.CreateArchetype(
typeof(ERRoadTag),
typeof(RoadDetails),
typeof(LanePoints)
);
var connectionEntityArchetype = entityManager.CreateArchetype(
typeof(ERConnectionTag),
typeof(ConnectionDetails),
typeof(LanePoints)
);
int nextRoadIdentity = 0;
int nextLaneIndex = 0;
int connectionIndexEnd;
int connectionIndexStart;
int connectionIdentityEnd = 0;
int connectionIdentityStart = 0;
ERConnection erConnectionEnd;
ERConnection erConnectionStart;
ERRoadNetwork roadNetwork = new ERRoadNetwork();
ERRoad[] roads = roadNetwork.GetRoadObjects(); // .GetRoads();
List<Vector3> allLanePoints = new List<Vector3>();
List<Vector3> connectionLanePoints = new List<Vector3>();
ConnectedTo connectedTo;
//Make entities for each of these objects
//Roads first. They need a collection of Lanes and each lane has an input and output connection identity.
//This collection of Road Identity & Lane Identity, or Connection Identity & Lane Identity
//will be used in the JOB to get the next load of data
foreach (ERRoad road in roads)
{
int roadIdentity = road.gameObject.GetComponent<ERRoadConnectionIdentity>().value;
int laneCount = road.GetLaneCount();
for (int lane = 0; lane < laneCount; lane++)
{
ERLaneData erLaneData = road.GetLaneData(lane);
if (erLaneData.direction == ERLaneDirection.Right)
{
erConnectionEnd = road.GetConnectionAtEnd(out connectionIndexEnd);
erConnectionStart = road.GetConnectionAtStart(out connectionIndexStart);
}
else
{
erConnectionEnd = road.GetConnectionAtStart(out connectionIndexEnd);
erConnectionStart = road.GetConnectionAtEnd(out connectionIndexStart);
}
connectionIdentityStart = RoadConnectionIdentity(erConnectionStart.gameObject);
connectionIdentityEnd = RoadConnectionIdentity(erConnectionEnd.gameObject);
//Create the Road/Lane entity
Entity roadEntity = entityManager.CreateEntity(roadEntityArchetype);
entityManager.SetComponentData(
roadEntity,
new RoadDetails
{
RoadIdentity = roadIdentity,
LaneIndex = erLaneData.laneIndex,
ConnectionIdentityEnd = connectionIdentityEnd,
ConnectionIdentityStart = connectionIdentityStart,
ConnectionIndexEnd = connectionIndexEnd,
ConnectionIndexStart = connectionIndexStart
});
//Get and store the road's lane points
Vector3[] roadLanePoints = erLaneData.points;
var roadLanePointsBuffer = entityManager.GetBuffer<LanePoints>(roadEntity);
for (int point = 0; point < roadLanePoints.Length; point++)
{
roadLanePointsBuffer.Add(new LanePoints { value = roadLanePoints[point] });
}
//---------------------------------------------------
//Create this Road/Lane/Connection combo
ERLaneConnector[] laneConnectors = erConnectionEnd.GetLaneData(connectionIndexEnd, erLaneData.laneIndex);
for (int i = 0; i < laneConnectors.Length; i++)
{
var laneConnector = laneConnectors[i];
var endRoad = erConnectionEnd.GetConnectedRoad(laneConnector.endConnectionIndex, out connectedTo);
var roadIdentityEnd = RoadConnectionIdentity(endRoad.gameObject);
Entity connectionEntity = entityManager.CreateEntity(connectionEntityArchetype);
entityManager.SetComponentData(
connectionEntity,
new ConnectionDetails
{
ConnectionIdentity = connectionIdentityEnd,
LaneIndexStart = erLaneData.laneIndex,
LaneIndexEnd = laneConnector.endLaneIndex,
RoadIdentityStart = roadIdentity,
RoadIdentityEnd = roadIdentityEnd,
ConnectionIndexEnd = laneConnector.endConnectionIndex,
ConnectionIndexStart = connectionIndexStart
});
var connectionLanePointsBuffer = entityManager.GetBuffer<LanePoints>(connectionEntity);
for (int x = 0; x < laneConnector.points.Length; x++)
{
connectionLanePointsBuffer.Add(new LanePoints { value = laneConnector.points[x] });
}
}
//---------------------------------------------------
//Pick a connection and one of the output values to give to the cars that are about to be created
int randomValue = UnityEngine.Random.Range(0, laneConnectors.Length);
var laneConnect = laneConnectors[randomValue];
var exitRoad = erConnectionEnd.GetConnectedRoad(laneConnect.endConnectionIndex, out connectedTo);
nextLaneIndex = laneConnect.endLaneIndex;
nextRoadIdentity = RoadConnectionIdentity(exitRoad.gameObject);
connectionIndexEnd = laneConnect.endConnectionIndex;
connectionLanePoints = laneConnect.points.ToList();
allLanePoints.Clear();
allLanePoints.AddRange(roadLanePoints);
allLanePoints.AddRange(connectionLanePoints);
Array.Clear(roadLanePoints, 0, roadLanePoints.Length);
connectionLanePoints.Clear();
//Option to not fill every lane
int random = UnityEngine.Random.Range(0, 100);
if (random <= percentageLanesPopulated)
{
//Temp to ensure only one auto is made for this test
if (autoIdentity < 1)
{
Debug.Log("Lane count: " + allLanePoints.Count);
CreateAutoEntity(
allLanePoints,
nextLaneIndex,
nextRoadIdentity,
connectionIdentityEnd,
connectionIndexEnd);
}
}
}
}
allLanePoints.Clear();
connectionLanePoints.Clear();
}
Then the Auto entity and it’s road points is created:
private int autoIdentity = 0;
private void CreateAutoEntity(
List<Vector3> lanePoints,
int nextLaneIdentity,
int nextRoadIdentity,
int nextConnectionIdentity,
int connectionIndex)
{
Entity prefab = autoEntities[UnityEngine.Random.Range(0, autoEntities.Count)];
var entity = entityManager.Instantiate(prefab);
float speed = UnityEngine.Random.Range(speedMinimum, speedMaximum);
int currentIndex = UnityEngine.Random.Range(0, lanePoints.Count - vehicleLength);
Vector3 translation = lanePoints[currentIndex];
translation.y += heightOffset;
Vector3 destination = lanePoints[currentIndex + 1];
destination.y += heightOffset;
//float3 lookVector = destination - translation;
Vector3 lookVector = destination - translation;
Quaternion rotation = new Quaternion();
if (lookVector.sqrMagnitude > 0.01f)
{
rotation = Quaternion.LookRotation(lookVector);
}
entityManager.SetComponentData(entity,
new AutoDetails {
yOffset = heightOffset,
speed = speed });
entityManager.SetComponentData(entity,
new AutoPosition
{
CurrentPositionIndex = currentIndex,
Destination = destination,
LaneIndex = nextLaneIdentity,
RoadIdentity = nextRoadIdentity,
ConnectionIdentity = nextConnectionIdentity,
ConnectionIndex = connectionIndex
});
entityManager.SetComponentData(entity, new Translation { Value = translation });
entityManager.SetComponentData(entity, new Rotation { Value = rotation });
//TEMP for debugging
entityManager.SetComponentData(entity, new AutoIdentity { value = autoIdentity });
autoIdentity++;
Debug.Log("Lane points count: " + lanePoints.Count);
var lanePointsBuffer = entityManager.GetBuffer<AutoLanePoints>(entity);
for (int i = 0; i < lanePoints.Count; i++)
{
lanePointsBuffer.Add(new AutoLanePoints { value = lanePoints[i] });
}
Debug.Log("Buffer Count: " + lanePointsBuffer.Length);
}
Note: In the last lines above, the “lanePoints” AND “lanePointsBuffer” both show a count of 161, until the System runs, then it returns a value of zero.
protected override void OnUpdate()
{
Entities.WithAll<ERAutoTag>()
.ForEach((
DynamicBuffer<AutoLanePoints> autoLanePoints,
ref AutoDetails autoDetails,
ref AutoPosition autoPosition,
ref Translation translation,
ref Rotation rotation,
ref AutoIdentity ident) =>
{
Debug.Log("Ident: " + ident.value + " Points: " + autoLanePoints.Length);
//THE REST OF THE CODE HAS BEEN REMOVED FOR TESTING
}).Schedule();
}
When I run the code I get this: Imgur: The magic of the Internet
Notice that at first there are 161 values in the buffer, but as soon as the System runs it reports BOTH 0 and 160 values, and if you notice it shows exactly 3 times as many without values as with values. At no time am I clearing or change that buffer.
Again, ONLY the first Auto entity has this issue. If I remove the IF statement in limiting the number of autos created, the debug log only shows IDENTITY 0 with the issue.
FEELS so odd. So what other dumbass thing am i doing wrong?
Thanks for reading all this and if you have any, ANY thoughts, let me know.
Peace,
James