Hi guys, I have an environment with almost 400 cars and every car contains 9 sensors. Everytime when my car detect something i use return to avoid using another RayCast, but still I have problems: Code (CSharp): private void prioritySensors() { if (_currentWayPoint == null) return; if (Intersection) _intersectionAhead = false; _reverse = false; CarAhead = ""; _priority = false; _isCarAhead = false; FrontCenterSensorPriority = false; FrontLeftSensorPriority = false; FrontObliqueLeftSensorPriority = false; FrontRightSensorPriority = false; FrontObliqueRightSensorPriority = false; LeftSideSensorPriority = false; RightSideSeonsorPriority = false; BackLeftSensorPriority = false; BackRightSensorPriority = false; // dimensiunea senzorului va fi adaptata in functie de viteza float newFrontSensorsLength = 0; // speed 15 -------------- FrontSL // speed x -------------- newFrontSL if (CurrentSpeed > 100) newFrontSensorsLength = 40; else if (CurrentSpeed > 80) newFrontSensorsLength = 35; else if (CurrentSpeed > 60) newFrontSensorsLength = 30; else if (CurrentSpeed > 40) newFrontSensorsLength = 25; else if (CurrentSpeed > 30) newFrontSensorsLength = 20; else if (CurrentSpeed > 20) newFrontSensorsLength = 15; else if (CurrentSpeed > 15) newFrontSensorsLength = 10; else newFrontSensorsLength = 3; if (Intersection) newFrontSensorsLength += 2; // Stabilim dimensiunea senzorilor in intersectii float newFronSideSensorsLength = FrontSideSensorsLength; float newFrontObliqSensorsAngle = FrontObliqSensorsAngle; if (RoundAbout) newFronSideSensorsLength *= 1.5f; else if (Intersection && !GoRight) { newFronSideSensorsLength = 12; if (GoForward) { newFronSideSensorsLength = 8; newFrontObliqSensorsAngle = 5; } } float dim = FrontSideSensorsLength; RaycastHit hit = new RaycastHit(); Color colorSensor = new Color(); colorSensor = Color.green; Vector3 frontSensorsStartPosition = transform.position; frontSensorsStartPosition += transform.forward * FrontSensorsPosition.z; // are aceeasi directie ca si masina frontSensorsStartPosition += transform.up * FrontSensorsPosition.y; // se afla la aceeasi inaltime indiferent de pozitia masinii Vector3 sideSensorsStartPosition = transform.position; sideSensorsStartPosition += transform.forward * SideSensorsPosition.z; // are aceeasi directie ca si masina sideSensorsStartPosition += transform.up * SideSensorsPosition.y; // se afla la aceeasi inaltime indiferent de pozitia masinii Vector3 backObliqSensorsStartPosition = transform.position; backObliqSensorsStartPosition += transform.forward * (-1) * BackSensorsPosition.z; // are aceeasi directie ca si masina backObliqSensorsStartPosition += transform.up * BackSensorsPosition.y; // se afla la aceeasi inaltime indiferent de pozitia masinii RaycastHit[] hits; hits = Physics.RaycastAll(frontSensorsStartPosition, transform.forward, newFrontSensorsLength); // Front Center bool hited = false; if (hits.Length > 0) { foreach (var h in hits) { // reduc viteza in intersectii if (h.collider.gameObject.CompareTag("Intersection")) { _intersectionAhead = true; if (CurrentSpeed > 30) { _isCarAhead = true; return; } } if (h.collider.gameObject.CompareTag("Car")) { hit = h; hited = true; break; } } if (hited) { FrontCenterSensorPriority = true; //Debug.DrawLine(frontSensorsStartPosition, hit.point, colorSensor); CarAhead = hit.collider.gameObject.name; if (hit.collider.CompareTag("Player")) { _isCarAhead = true; return; } _priority = getPriority(hit.collider.gameObject, hit); _isCarAhead = !_priority; return; } } // Front Left frontSensorsStartPosition -= transform.right * FrontObliqSensorsPosition; dim = (Intersection && !GoRight) ? newFronSideSensorsLength : newFrontSensorsLength + 1; if (Physics.Raycast(frontSensorsStartPosition, transform.forward, out hit, dim)) { if (!hit.collider.CompareTag("WayPoint") && !hit.collider.CompareTag("NotForSensors") && !hit.collider.CompareTag("Intersection")) { //Debug.Log("FL Dim: " + dim + " NewLength" + newFrontSensorsLength + " Inter: " + newFronSideSensorsLength); FrontLeftSensorPriority = true; Debug.DrawLine(frontSensorsStartPosition, hit.point, colorSensor); CarAhead = hit.collider.gameObject.name; if (hit.collider.CompareTag("Player")) { _isCarAhead = true; return; } _priority = getPriority(hit.collider.gameObject, hit); _isCarAhead = !_priority; return; } } // Oblique Left dim = (Intersection && !GoRight) ? newFronSideSensorsLength : FrontSideSensorsLength; if (Physics.Raycast(frontSensorsStartPosition, Quaternion.AngleAxis(-newFrontObliqSensorsAngle, transform.up) * transform.forward, out hit, dim)) { if (!hit.collider.CompareTag("WayPoint") && !hit.collider.CompareTag("NotForSensors") && !hit.collider.CompareTag("Intersection")) { //Debug.Log("OL Dim: " + dim + " NewLength" + FrontSideSensorsLength + " Inter: " + newFronSideSensorsLength); FrontObliqueLeftSensorPriority = true; Debug.DrawLine(frontSensorsStartPosition, hit.point, colorSensor); CarAhead = hit.collider.gameObject.name; if (hit.collider.CompareTag("Player")) { _isCarAhead = true; return; } _priority = getPriority(hit.collider.gameObject, hit); _isCarAhead = !_priority; return; } } // Front Right frontSensorsStartPosition += 2 * transform.right * FrontObliqSensorsPosition; dim = (Intersection && !GoRight) ? newFronSideSensorsLength : newFrontSensorsLength + 1; if (Physics.Raycast(frontSensorsStartPosition, transform.forward, out hit, dim)) { if (!hit.collider.CompareTag("WayPoint") && !hit.collider.CompareTag("NotForSensors") && !hit.collider.CompareTag("Intersection")) { //Debug.Log("FR Dim: " + dim + " NewLength" + newFrontSensorsLength + " Inter: "+ newFronSideSensorsLength); FrontRightSensorPriority = true; Debug.DrawLine(frontSensorsStartPosition, hit.point, colorSensor); CarAhead = hit.collider.gameObject.name; if (hit.collider.CompareTag("Player")) { _isCarAhead = true; return; } _priority = getPriority(hit.collider.gameObject, hit); _isCarAhead = !_priority; return; } } // Oblique Right dim = (Intersection && !GoRight) ? newFronSideSensorsLength : FrontSideSensorsLength; if (Physics.Raycast(frontSensorsStartPosition, Quaternion.AngleAxis(FrontObliqSensorsAngle, transform.up) * transform.forward, out hit, dim)) { if (!hit.collider.CompareTag("WayPoint") && !hit.collider.CompareTag("NotForSensors") && !hit.collider.CompareTag("Intersection")) { //Debug.Log("OR Dim: " + dim + " NewLength" + FrontSideSensorsLength + " Inter: " + newFronSideSensorsLength); FrontObliqueRightSensorPriority = true; Debug.DrawLine(frontSensorsStartPosition, hit.point, colorSensor); CarAhead = hit.collider.gameObject.name; if (hit.collider.CompareTag("Player")) { _isCarAhead = true; return; } _priority = getPriority(hit.collider.gameObject, hit); _isCarAhead = !_priority; return; } } // RIGHT SIDE sideSensorsStartPosition += transform.right * SidePosition; if (!Intersection && (Mathf.Abs(_targetSteerAngle) > 7) || (Mathf.Abs(_dirAngle) > 10 && (_distance < 2))) { if (Physics.Raycast(sideSensorsStartPosition, Quaternion.AngleAxis(90, transform.up) * transform.forward, out hit, SideSensorsLength)) { if (!hit.collider.CompareTag("WayPoint") && !hit.collider.CompareTag("NotForSensors") && !hit.collider.CompareTag("Intersection")) { RightSideSeonsorPriority = true; Debug.DrawLine(sideSensorsStartPosition, hit.point, colorSensor); CarAhead = hit.collider.gameObject.name; if (hit.collider.CompareTag("Player")) { _isCarAhead = true; return; } _priority = getPriority(hit.collider.gameObject, hit); _isCarAhead = !_priority; return; } } } // LEFT SIDE sideSensorsStartPosition -= 2 * transform.right * SidePosition; if (!Intersection && (Mathf.Abs(_targetSteerAngle) > 7 || (Mathf.Abs(_dirAngle) > 10 && (_distance < 2)))) { if (Physics.Raycast(sideSensorsStartPosition, Quaternion.AngleAxis(-90, transform.up) * transform.forward, out hit, SideSensorsLength)) { if (!hit.collider.CompareTag("WayPoint") && !hit.collider.CompareTag("NotForSensors") && !hit.collider.CompareTag("Intersection")) { LeftSideSensorPriority = true; Debug.DrawLine(sideSensorsStartPosition, hit.point, colorSensor); CarAhead = hit.collider.gameObject.name; if (hit.collider.CompareTag("Player")) { _isCarAhead = true; return; } _priority = getPriority(hit.collider.gameObject, hit); _isCarAhead = !_priority; return; } } } // RIGHT OBLIQUE BACK if (GoRight && !Intersection && _distance < 3) { backObliqSensorsStartPosition += transform.right * BackObliqSensorsPosition; // Acest senzor se activeaza atunci cand masina isi schimba banda if (Physics.Raycast(backObliqSensorsStartPosition, Quaternion.AngleAxis(BackObliqSensorsAngle, transform.up) * transform.forward, out hit, BackObliqSensorsLength)) { //Debug.Log("RIGHT"); if (!hit.collider.CompareTag("WayPoint") && !hit.collider.CompareTag("NotForSensors") && !hit.collider.CompareTag("Intersection")) { BackRightSensorPriority = true; Debug.DrawLine(backObliqSensorsStartPosition, hit.point, colorSensor); CarAhead = hit.collider.gameObject.name; if (hit.collider.CompareTag("Player")) { _isCarAhead = true; return; } _priority = getPriority(hit.collider.gameObject, hit); _isCarAhead = !_priority; return; } } } // LEFT OBLIQUE BACK if (GoLeft && !Intersection && _distance < 3) { backObliqSensorsStartPosition -= 2 * transform.right * BackObliqSensorsPosition; if (Physics.Raycast(backObliqSensorsStartPosition, Quaternion.AngleAxis(-BackObliqSensorsAngle, transform.up) * transform.forward, out hit, BackObliqSensorsLength)) { //Debug.Log("LEFT"); if (!hit.collider.CompareTag("WayPoint") && !hit.collider.CompareTag("NotForSensors") && !hit.collider.CompareTag("Intersection")) { BackLeftSensorPriority = true; Debug.DrawLine(backObliqSensorsStartPosition, hit.point, colorSensor); CarAhead = hit.collider.gameObject.name; if (hit.collider.CompareTag("Player")) { _isCarAhead = true; return; } _priority = getPriority(hit.collider.gameObject, hit); _isCarAhead = !_priority; return; } } } }
Well, of the 90ms that FixedUpdate took that frame, only 9ms was your actual raycasting. Note that because the overall framerate was so low, Unity had to run FixedUpdate 5 times that frame. I'd be curious what the other 80ms in FixedUpdate was. Anyway, if you really want to improve FixedUpdate performance, the recommended approach is to use RaycastCommand to perform your raycasts as a job, which gets spread out over all threads. https://docs.unity3d.com/ScriptReference/RaycastCommand.html I use this approach, and it made a big difference in places where I'm doing lots of raycasting.
I got this: A Native Collection has not been disposed, resulting in a memory leak. It was allocated at C:\Users\zzava\Desktop\Licenta\TrafficSimulator\Assets\Scripts\CarAI\CarEngine.cs:451. Code (CSharp): var results = new NativeArray<RaycastHit>(1, Allocator.Temp); var commands = new NativeArray<RaycastCommand>(1, Allocator.Temp); Vector3 frontSensorsStartPosition = transform.position; frontSensorsStartPosition += transform.forward * FrontSensorsPosition.z; // are aceeasi directie ca si masina frontSensorsStartPosition += transform.up * FrontSensorsPosition.y; // se afla la aceeasi inaltime indiferent de pozitia masinii Vector3 sideSensorsStartPosition = transform.position; sideSensorsStartPosition += transform.forward * SideSensorsPosition.z; // are aceeasi directie ca si masina sideSensorsStartPosition += transform.up * SideSensorsPosition.y; // se afla la aceeasi inaltime indiferent de pozitia masinii Vector3 backObliqSensorsStartPosition = transform.position; backObliqSensorsStartPosition += transform.forward * (-1) * BackSensorsPosition.z; // are aceeasi directie ca si masina backObliqSensorsStartPosition += transform.up * BackSensorsPosition.y; // se afla la aceeasi inaltime indiferent de pozitia masinii commands[0] = new RaycastCommand(frontSensorsStartPosition, transform.forward); // Schedule the batch of raycasts JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle)); // Wait for the batch processing job to complete handle.Complete(); // Copy the result. If batchedHit.collider is null there was no hit RaycastHit batchedHit = results[0]; //RaycastHit[] hits; //hits = Physics.RaycastAll(frontSensorsStartPosition, transform.forward, newFrontSensorsLength); // Front Center bool hited = false; if (results.Length > 0) { foreach (var h in results) { // reduc viteza in intersectii if (h.collider.gameObject.CompareTag("Intersection")) { _intersectionAhead = true; if (CurrentSpeed > 30) { _isCarAhead = true; return; } } if (h.collider.gameObject.CompareTag("Car")) { hit = h; hited = true; break; } } if (hited) { FrontCenterSensorPriority = true; //Debug.DrawLine(frontSensorsStartPosition, hit.point, colorSensor); CarAhead = hit.collider.gameObject.name; if (hit.collider.CompareTag("Player")) { _isCarAhead = true; return; } _priority = getPriority(hit.collider.gameObject, hit); _isCarAhead = !_priority; return; } } // Dispose the buffers results.Dispose(); commands.Dispose();
Possibly similar to this? https://forum.unity.com/threads/sol...n-disposed-resulting-in-a-memory-leak.548929/ Is this happening frequently, or when you stop the game or change something? I dispose of my native arrays immediately after being done with them, but I also dispose of them in OnDestroy and OnDisable, just in case the job was running when I stopped the game or unloaded the scene.
I used return, that was the mistake. But now, can I use RaycastCommand instead RaycastAll ? I want that my raycast to seed two objects, intersection and car. And raycastCommand, doesn't have a maxim length? I want to use it for few meters.
RaycastCommand has a 'distance' property you can set, to control the length of the cast. I'm not sure the best approach to finding two hits, but my guess is it might make more sense to add pairs of RaycastCommands, one for the 'car' layer and one for the 'intersection' layer. Or the same thing, but ignoring the the car and intersection layers respectively. Alternatively, you could create a Job to do everything. RaycastCommand is a kind of job that Unity has created for convenience, but if it's not quite right for you then doing the complex processing with a custom Job would be the way to go. The point of Jobs is that they use all available processors to do the work.
IS better now? Code (CSharp): bool hited = false; #region Sensor - Front-Center // Front Center RaycastHit[] hits; hits = Physics.RaycastAll(frontSensorsStartPosition, transform.forward, newFrontSensorsLength); if (hits.Length > 0) { foreach (var h in hits) { // reduc viteza in intersectii if (h.collider.gameObject.CompareTag("Intersection")) { _intersectionAhead = true; if (CurrentSpeed > 30) { _isCarAhead = true; return; } } if (h.collider.gameObject.CompareTag("Car")) { hit = h; hited = true; break; } } if (hited) { FrontCenterSensorPriority = true; Debug.DrawLine(frontSensorsStartPosition, hit.point, colorSensor); CarAhead = hit.collider.gameObject.name; if (hit.collider.CompareTag("Player")) { _isCarAhead = true; return; } _priority = getPriority(hit.collider.gameObject, hit); _isCarAhead = !_priority; return; } } #endregion var results = new NativeArray<RaycastHit>(1, Allocator.Temp); var commands = new NativeArray<RaycastCommand>(1, Allocator.Temp); #region Sensor - Front Left if (!hited) { frontSensorsStartPosition -= transform.right * FrontObliqSensorsPosition; dim = (Intersection && !GoRight) ? newFronSideSensorsLength : newFrontSensorsLength + 1; commands[0] = new RaycastCommand(frontSensorsStartPosition, transform.forward, dim); JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle)); handle.Complete(); RaycastHit batchedHit = results[0]; if ((batchedHit.collider) && !batchedHit.collider.CompareTag("WayPoint") && !batchedHit.collider.CompareTag("NotForSensors") && !batchedHit.collider.CompareTag("Intersection")) { hited = true; FrontLeftSensorPriority = true; Debug.DrawLine(frontSensorsStartPosition, batchedHit.point, colorSensor); CarAhead = batchedHit.collider.gameObject.name; if (batchedHit.collider.CompareTag("Player")) _isCarAhead = true; else { _priority = getPriority(batchedHit.collider.gameObject, batchedHit); _isCarAhead = !_priority; } } } #endregion #region Sensor - Front Left Oblique if (!hited) { dim = (Intersection && !GoRight) ? newFronSideSensorsLength : FrontSideSensorsLength; commands[0] = new RaycastCommand(frontSensorsStartPosition, Quaternion.AngleAxis(-newFrontObliqSensorsAngle, transform.up) * transform.forward, dim); JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle)); handle.Complete(); RaycastHit batchedHit = results[0]; if ((batchedHit.collider) && (batchedHit.collider) && !batchedHit.collider.CompareTag("WayPoint") && !batchedHit.collider.CompareTag("NotForSensors") && !batchedHit.collider.CompareTag("Intersection")) { hited = true; FrontObliqueLeftSensorPriority = true; Debug.DrawLine(frontSensorsStartPosition, batchedHit.point, colorSensor); CarAhead = batchedHit.collider.gameObject.name; if (batchedHit.collider.CompareTag("Player")) _isCarAhead = true; else { _priority = getPriority(batchedHit.collider.gameObject, batchedHit); _isCarAhead = !_priority; } } } #endregion #region Sensor - Front Right if (!hited) { frontSensorsStartPosition += 2 * transform.right * FrontObliqSensorsPosition; dim = (Intersection && !GoRight) ? newFronSideSensorsLength : newFrontSensorsLength + 1; commands[0] = new RaycastCommand(frontSensorsStartPosition, transform.forward, dim); JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle)); handle.Complete(); RaycastHit batchedHit = results[0]; if ((batchedHit.collider) && !batchedHit.collider.CompareTag("WayPoint") && !batchedHit.collider.CompareTag("NotForSensors") && !batchedHit.collider.CompareTag("Intersection")) { hited = true; FrontRightSensorPriority = true; Debug.DrawLine(frontSensorsStartPosition, batchedHit.point, colorSensor); CarAhead = batchedHit.collider.gameObject.name; if (batchedHit.collider.CompareTag("Player")) _isCarAhead = true; else { _priority = getPriority(batchedHit.collider.gameObject, batchedHit); _isCarAhead = !_priority; } } } #endregion #region Sensor - Front Right Oblique if (!hited) { dim = (Intersection && !GoRight) ? newFronSideSensorsLength : FrontSideSensorsLength; commands[0] = new RaycastCommand(frontSensorsStartPosition, Quaternion.AngleAxis(FrontObliqSensorsAngle, transform.up) * transform.forward, dim); JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle)); handle.Complete(); RaycastHit batchedHit = results[0]; if ((batchedHit.collider) && !batchedHit.collider.CompareTag("WayPoint") && !batchedHit.collider.CompareTag("NotForSensors") && !batchedHit.collider.CompareTag("Intersection")) { hited = true; FrontObliqueRightSensorPriority = true; Debug.DrawLine(frontSensorsStartPosition, batchedHit.point, colorSensor); CarAhead = batchedHit.collider.gameObject.name; if (batchedHit.collider.CompareTag("Player")) _isCarAhead = true; else { _priority = getPriority(batchedHit.collider.gameObject, batchedHit); _isCarAhead = !_priority; } } } #endregion #region Sensor - Side Left if (!Intersection && (Mathf.Abs(_targetSteerAngle) > 7 || (Mathf.Abs(_dirAngle) > 10 && (_distance < 2)))) { if (!hited) { sideSensorsStartPosition -= transform.right * SidePosition; commands[0] = new RaycastCommand(sideSensorsStartPosition, Quaternion.AngleAxis(-90, transform.up) * transform.forward, SideSensorsLength); JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle)); handle.Complete(); RaycastHit batchedHit = results[0]; if ((batchedHit.collider) && !batchedHit.collider.CompareTag("WayPoint") && !batchedHit.collider.CompareTag("NotForSensors") && !batchedHit.collider.CompareTag("Intersection")) { hited = true; LeftSideSensorPriority = true; Debug.DrawLine(sideSensorsStartPosition, batchedHit.point, colorSensor); CarAhead = batchedHit.collider.gameObject.name; if (batchedHit.collider.CompareTag("Player")) _isCarAhead = true; else { _priority = getPriority(batchedHit.collider.gameObject, batchedHit); _isCarAhead = !_priority; } } } } #endregion #region Sensor - Side Right if (!Intersection && (Mathf.Abs(_targetSteerAngle) > 7) || (Mathf.Abs(_dirAngle) > 10 && (_distance < 2))) { if (!hited) { sideSensorsStartPosition += 2 * transform.right * SidePosition; commands[0] = new RaycastCommand(sideSensorsStartPosition, Quaternion.AngleAxis(90, transform.up) * transform.forward, SideSensorsLength); JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle)); handle.Complete(); RaycastHit batchedHit = results[0]; if ( (batchedHit.collider) && !batchedHit.collider.CompareTag("WayPoint") && !batchedHit.collider.CompareTag("NotForSensors") && !batchedHit.collider.CompareTag("Intersection")) { hited = true; RightSideSeonsorPriority = true; Debug.DrawLine(sideSensorsStartPosition, batchedHit.point, colorSensor); CarAhead = batchedHit.collider.gameObject.name; if (batchedHit.collider.CompareTag("Player")) _isCarAhead = true; else { _priority = getPriority(batchedHit.collider.gameObject, batchedHit); _isCarAhead = !_priority; } } } } #endregion #region Sensor - Back Left Oblique if (GoLeft && !Intersection && _distance < 3) { backObliqSensorsStartPosition -= 2 * transform.right * BackObliqSensorsPosition; if (!hited) { commands[0] = new RaycastCommand(backObliqSensorsStartPosition, Quaternion.AngleAxis(-BackObliqSensorsAngle, transform.up) * transform.forward, BackObliqSensorsLength); JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle)); handle.Complete(); RaycastHit batchedHit = results[0]; if ((batchedHit.collider) && !batchedHit.collider.CompareTag("WayPoint") && !batchedHit.collider.CompareTag("NotForSensors") && !batchedHit.collider.CompareTag("Intersection")) { hited = true; BackLeftSensorPriority = true; Debug.DrawLine(backObliqSensorsStartPosition, batchedHit.point, colorSensor); CarAhead = batchedHit.collider.gameObject.name; if (batchedHit.collider.CompareTag("Player")) _isCarAhead = true; else { _priority = getPriority(batchedHit.collider.gameObject, batchedHit); _isCarAhead = !_priority; } } } } #endregion #region Sensor - Back Right Oblique if (GoRight && !Intersection && _distance < 3) { if (!hited) { backObliqSensorsStartPosition += transform.right * BackObliqSensorsPosition; commands[0] = new RaycastCommand(backObliqSensorsStartPosition, Quaternion.AngleAxis(BackObliqSensorsAngle, transform.up) * transform.forward, BackObliqSensorsLength); JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle)); handle.Complete(); RaycastHit batchedHit = results[0]; if ((batchedHit.collider) && !batchedHit.collider.CompareTag("WayPoint") && !batchedHit.collider.CompareTag("NotForSensors") && !batchedHit.collider.CompareTag("Intersection")) { hited = true; BackRightSensorPriority = true; Debug.DrawLine(backObliqSensorsStartPosition, batchedHit.point, colorSensor); CarAhead = batchedHit.collider.gameObject.name; if (batchedHit.collider.CompareTag("Player")) _isCarAhead = true; else { _priority = getPriority(batchedHit.collider.gameObject, batchedHit); _isCarAhead = !_priority; } } } } #endregion // Dispose the buffers results.Dispose(); commands.Dispose();
No, that's probably not better. The whole point of RaycastCommand is that you can add LOTS of raycasts to a single call to RaycastCommand.ScheduleBatch, and those raycasts will be performed across all available threads. To me, it looks like you're just putting one RaycastCommand per batch, which wouldn't be likely to get your any better performance, and I imagine might even make things slower. I realize using RaycastCommand isn't super trivial. It might mean significantly changing the approach you've been taking. Right now it seems you go through each car, one at a time, and perform its raycasts, before moving on to the next car. To improve performance, you'll probably need to batch all of those cars into a single (or a small number of ) RaycastCommand.ScheduleBatch calls, and then loop through the results again after to evaluate all of the raycast hit results.
Now, if my car see something then I have a raycastCommand with one raycast, but if I add a lot of raycasts I will have a raycastCommand with a lot of raycasts, for me it seems worst.
That's not how RaycastCommand works. In your original post, your profiler results show that you performed more than 8000 raycasts in a single frame. All of those raycasts were performed on the main thread, meaning that all the other cores of your CPU didn't help out. Using RaycastCommands, you could potentially spread those 8000 raycasts out across all CPUs, so that they finish much faster. The challenge is writing your code in a way where you can batch up the raycasts into these jobs, run the job, and then evaluate the results after. Ideally you'd run a single RaycastCommand.ScheduleBatch per FixedUpdate, with all of the necessary RaycastCommands in it.
Yes. Well, not every frame, but every FixedUpdate. Or as often as you need to. In my case, I'm using raycasts to decide how much force to apply to a large number of rigidbodies, so I do the raycasting every FixedUpdate. I could probably get away with doing it every other FixedUpdate, and caching the results, but so far with RaycastCommands there aren't any performance issues doing it every FixedUpdate. Of course, if you don't need to do the raycast for a particular object in a particular FixedUpdate it would be best to avoid doing so.
Like I said, now you're calling RaycastCommand.ScheduleBatching about 4000 times per fixed update. You should be trying to call it once per fixed update. And again, if you want to try to get the performance improvements out of this, it will involved some restructuring of your code.
I don't understand very good. You say should I call Raycastcommand for all cars, or for every car ? In fixedUpdate I call RaycastCommand.ScheduleBatch just one time every frame for every car, that means 400 calls for 400 cars.
Ideally one RaycastCommand.ScheduleBatch per FixedUpdate. There's some overhead/cost to creating and executing each batch, so the more you include in the batch the better.
I think I understand what you say. Maybe should I check the result of the job with all raycasts instead of call a job, check, call another job, check. In my case I have only one call when the first sensor find something. Right ? JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle)); OR JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, sensorsCount, default(JobHandle)); ?
Yeah, that would generally be better. Schedule all of the raycasts into one batch, then evaluate them all afterwards. In my game, my basic approach is to loop over all of the rigidbodies I need to raycast for, and create a RaycastCommand. I then execute them all in one batch. Then I loop through all of the Rigidbodies again, checking the results to see if I need to do something with that rigidbody.
I don't think I can use this for cars, because every car has his own brain. I did this, is better? value 1 is good for this? JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle)); Code (CSharp): int sensorsCount = 10; var results = new NativeArray<RaycastHit>(sensorsCount, Allocator.Temp); var commands = new NativeArray<RaycastCommand>(sensorsCount, Allocator.Temp); // Sensor - Front-Center int carsLayerMask = 1 << 10; int intersectionsLAyerMask = 1 << 11; commands[0] = new RaycastCommand(frontSensorsStartPosition, transform.forward, newFrontSensorsLength, carsLayerMask); //cars commands[1] = new RaycastCommand(frontSensorsStartPosition, transform.forward, newFrontSensorsLength, intersectionsLAyerMask); // intersections //Sensor - Front Left frontSensorsStartPosition -= transform.right * FrontObliqSensorsPosition; dim = (Intersection && !GoRight) ? newFronSideSensorsLength : newFrontSensorsLength + 1; commands[2] = new RaycastCommand(frontSensorsStartPosition, transform.forward, dim); //Sensor - Front Left Oblique dim = (Intersection && !GoRight) ? newFronSideSensorsLength : FrontSideSensorsLength; commands[3] = new RaycastCommand(frontSensorsStartPosition, Quaternion.AngleAxis(-newFrontObliqSensorsAngle, transform.up) * transform.forward, dim); //Sensor - Front Right frontSensorsStartPosition += 2 * transform.right * FrontObliqSensorsPosition; dim = (Intersection && !GoRight) ? newFronSideSensorsLength : newFrontSensorsLength + 1; commands[4] = new RaycastCommand(frontSensorsStartPosition, transform.forward, dim); //Sensor - Front Right Oblique dim = (Intersection && !GoRight) ? newFronSideSensorsLength : FrontSideSensorsLength; commands[5] = new RaycastCommand(frontSensorsStartPosition, Quaternion.AngleAxis(FrontObliqSensorsAngle, transform.up) * transform.forward, dim); //Sensor - Side Left sideSensorsStartPosition -= transform.right * SidePosition; commands[6] = new RaycastCommand(sideSensorsStartPosition, Quaternion.AngleAxis(-90, transform.up) * transform.forward, SideSensorsLength); //Sensor - Side Right sideSensorsStartPosition += 2 * transform.right * SidePosition; commands[7] = new RaycastCommand(sideSensorsStartPosition, Quaternion.AngleAxis(90, transform.up) * transform.forward, SideSensorsLength); //Sensor - Back Left Oblique commands[8] = new RaycastCommand(backObliqSensorsStartPosition, Quaternion.AngleAxis(-BackObliqSensorsAngle, transform.up) * transform.forward, BackObliqSensorsLength); //Sensor - Back Right Oblique backObliqSensorsStartPosition += transform.right * BackObliqSensorsPosition; commands[9] = new RaycastCommand(backObliqSensorsStartPosition, Quaternion.AngleAxis(BackObliqSensorsAngle, transform.up) * transform.forward, BackObliqSensorsLength); JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle)); handle.Complete(); for (int i = 0; i < results.Length; ++i) { if (results[i].collider != null) { switch (i) { case 0:// Sensor - Front-Center (for cars) checkFrontCenterSensor(results[i], frontSensorsStartPosition); break; case 1:// Sensor - Front-Center (for intersection) checkFrontCenterSensor(results[i], frontSensorsStartPosition); break; case 2://Sensor - Front Left checkFrontLeftSensor(results[i], frontSensorsStartPosition); break; case 3://Sensor - Front Left Oblique checkFrontLeftObliqueSensor(results[i], frontSensorsStartPosition); break; case 4://Sensor - Front Right checkFrontRightSensor(results[i], frontSensorsStartPosition); break; case 5://Sensor - Front Right Oblique checkFrontRightObliqueSensor(results[i], frontSensorsStartPosition); break; case 6://Sensor - Side Left checkSideLeftSensor(results[i], sideSensorsStartPosition); break; case 7://Sensor - Side Right checkSideRightSensor(results[i], sideSensorsStartPosition); break; case 8: //Sensor - Back Left Oblique checkBackLeftObliquetSensor(results[i], backObliqSensorsStartPosition); break; case 9://Sensor - Back Right Oblique checkBackRightObliquetSensor(results[i], backObliqSensorsStartPosition); break; default: break; } } } // Dispose the buffers results.Dispose(); commands.Dispose();
Probably better than you had it before, but I'm really not sure how many raycasts you need to include in a batch before it starts being more efficient than doing individual raycasts. Maybe it's faster, but it's entirely possible that you won't see real gains unless you get the batch count down.
* And about this> JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle)); ? Value 1 is good ? *What do you mean: Maybe it's faster, but it's entirely possible that you won't see real gains unless you get the batch count down. ?