void Update() { // Clamp values maxPoints = Mathf.Clamp(maxPoints, 2, 32767); // Set asynchronous available values if (billboardTransform != null) { _billboardTransformPosition = billboardTransform.position; } // Early out if no particles exist yet if (playgroundSystem == null || !playgroundSystem.IsReady() || playgroundSystem.IsSettingParticleCount() || playgroundSystem.IsSettingLifetime() || playgroundSystem.particleCache == null || playgroundSystem.particleCache.Length == 0) { return; } // Reset trails if a crucial state is changed if (_currentParticleCount != playgroundSystem.particleCount || _currentParticleMinLifetime != playgroundSystem.lifetimeMin || _currentParticleMaxLifetime != playgroundSystem.lifetime || _localSpace != (playgroundSystem.shurikenParticleSystem.simulationSpace == ParticleSystemSimulationSpace.Local)) { ResetTrails(); } // Set calculation matrix if this is local space if (_localSpace) { _localMatrix.SetTRS(playgroundSystem.particleSystemTransform.position, playgroundSystem.particleSystemTransform.rotation, playgroundSystem.particleSystemTransform.lossyScale); } // Check material if (material != _materialCache) { SetMaterial(material); } // Remove any trails that has ended if (_isDoneThread) { for (int i = 0; i < _trails.Count; i++) { if (_trails[i].trailPoints != null && _trails[i].trailPoints.Count > 1 && _trails[i].trailPoints[_trails[i].trailPoints.Count - 1] != null && _trails[i].CanRemoveTrail()) { RemoveTrail(i); i--; if (i < 0) { i = 0; } continue; } } } // Consume the particle birth queue while (_birthQueue.Count > 0) { AddTrail(_birthQueue.Dequeue()); } // Update all trail meshes and their render settings for (int i = 0; i < _trails.Count; i++) { ParticlePlaygroundTrail trail = _trails[i]; // Set shadow casting/receiving trail.trailRenderer.receiveShadows = receiveShadows; #if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 trail.trailRenderer.castShadows = castShadows; #else trail.trailRenderer.shadowCastingMode = shadowCastingMode; #endif if (_isDoneThread) { trail.UpdateMesh(); } } // Finally calculate all trails if (multithreading) { if (_isDoneThread) { _calculationStartTime = Application.isPlaying? Time.time : Time.realtimeSinceStartup; _isDoneThread = false; PlaygroundC.RunAsync(() => { lock (_locker) { if (_isDoneThread) { return; } CalculateTrail(); _isDoneThread = true; } }); } } else { _calculationStartTime = Application.isPlaying? Time.time : Time.realtimeSinceStartup; CalculateTrail(); } }
void Update() { // Clamp values maxPoints = Mathf.Clamp(maxPoints, 2, 32767); // Set asynchronous available values if (billboardTransform != null) { _billboardTransformPosition = billboardTransform.position; } // Early out if no particles exist yet if (playgroundSystem == null || !playgroundSystem.IsReady() || playgroundSystem.IsSettingParticleCount() || playgroundSystem.IsSettingLifetime() || playgroundSystem.particleCache == null || playgroundSystem.particleCache.Length == 0) { return; } // Reset trails if a crucial state is changed if (_currentParticleCount != playgroundSystem.particleCount || _currentLoopValue != playgroundSystem.loop || _currentParticleMinLifetime != playgroundSystem.lifetimeMin || _currentParticleMaxLifetime != playgroundSystem.lifetime || _localSpace != (playgroundSystem.shurikenParticleSystem.simulationSpace == ParticleSystemSimulationSpace.Local)) { ResetTrails(); } // Set calculation matrix if this is local space if (_localSpace) { _localMatrix.SetTRS(playgroundSystem.particleSystemTransform.position, playgroundSystem.particleSystemTransform.rotation, playgroundSystem.particleSystemTransform.lossyScale); } // Check material if (material != _materialCache) { SetMaterial(material); } // Consume the particle birth queue while (_isDoneThread && _birthQueue.Count > 0) { // Reuse or create new trails bool canReuseTrail = trails.Count > 0 && _trailReuseQueue.Count > 0; int reuseQueuePeekValue = canReuseTrail? _trailReuseQueue.Peek() : 0; if (canReuseTrail && (reuseQueuePeekValue < 0 || reuseQueuePeekValue > trails.Count - 1 || !trails[reuseQueuePeekValue].IsQueuedForReuse())) { _trailReuseQueue.Dequeue(); canReuseTrail = false; } if (canReuseTrail) { ReuseTrail(_trailReuseQueue.Dequeue(), _birthQueue.Dequeue()); } else { CreateTrail(_birthQueue.Dequeue()); } } // Remove any trails that has ended if (_isDoneThread) { for (int i = 0; i < trails.Count; i++) { if (trails[i].trailPoints != null && trails[i].trailPoints.Count > 1 && trails[i].trailPoints[trails[i].trailPoints.Count - 1] != null && trails[i].CanRemoveTrail()) { if (!trails[i].IsQueuedForReuse()) { _trailReuseQueue.Enqueue(i); trails[i].QueueForReuse(); } } } } // Update all trail meshes and their render settings for (int i = 0; i < trails.Count; i++) { ParticlePlaygroundTrail trail = trails[i]; // Set shadow casting/receiving trail.trailRenderer.receiveShadows = receiveShadows; #if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 trail.trailRenderer.castShadows = castShadows; #else trail.trailRenderer.shadowCastingMode = shadowCastingMode; #endif if (_isDoneThread && !trail.IsQueuedForReuse()) { trail.UpdateMesh(); } } // Check if there's any event listeners _hasTrailPointEventListener = trailPointEvent != null; // Check that the calculation delegate is assigned if (_trailsCalculationAction == null) { _trailsCalculationAction = CalculationDelegate; } _calculationStartTime = Application.isPlaying? Time.time : Time.realtimeSinceStartup; // Finally calculate all trails if (multithreading) { if (_isDoneThread) { _isDoneThread = false; PlaygroundC.RunAsync(_trailsCalculationAction); } } else { _isDoneThread = false; _trailsCalculationAction(); } }