模擬粒子系統(ParticleSystem.Simulate)
using UnityEngine; using UnityEditor; [ExecuteInEditMode] public class MyWindow : EditorWindow { private GameObject _curEffect; private float _curValue = 0; private float _preTime; private bool _isRun; private float _totalTime = 3.0f; private ParticleSystem[] _psList = null; [MenuItem("Window/My Window")] static void Init() { MyWindow window = (MyWindow)EditorWindow.GetWindow(typeof(MyWindow)); window.Show(); } void OnEnable() { _preTime = Time.realtimeSinceStartup; EditorApplication.update += EditorUpdate; } void Disable() { EditorApplication.update -= EditorUpdate; } void OnGUI() { GameObject obj = EditorGUILayout.ObjectField("object", _curEffect, typeof(GameObject)) as GameObject; if (obj != _curEffect) { _curEffect = obj; if (_curEffect != null) { _psList = _curEffect.GetComponentsInChildren<ParticleSystem>(true); } else { _psList = null; } } float value = EditorGUILayout.Slider("value", _curValue, 0, _totalTime); if (value != _curValue) { _curValue = value; foreach (ParticleSystem ps in _psList) { ps.Simulate(0, false, true); ps.time = 0; ps.Play(); } for (float i = 0.0f; i < _curValue; i += 0.02f) { SimsimulateParticlesForDeltaTime(0.02f); } } if (GUILayout.Button("播放")) { if (_psList != null) { foreach (ParticleSystem ps in _psList) { ps.time = 0; ps.Play(); } } _preTime = Time.realtimeSinceStartup; _isRun = true; _curValue = 0; } } /* // 有問題,用curTime用模擬就有問題 void SimsimulateParticlesForTotoleTime(float curTime) { if (_curEffect != null) { ParticleSystem[] psList = _curEffect.GetComponentsInChildren<ParticleSystem>(true); foreach (ParticleSystem ps in psList) { ps.Play(); ps.time = 0; ps.Simulate(curTime, false, true); } } } */ // DeltaTime,去模擬不會有問題 void SimsimulateParticlesForDeltaTime(float deltaTime) { if (_psList != null) { foreach (ParticleSystem ps in _psList) { ps.Simulate(deltaTime, false, false); } } } void EditorUpdate() { if (_isRun) { float deltaTime = Time.realtimeSinceStartup - _preTime; _preTime = Time.realtimeSinceStartup; _curValue += deltaTime; if (_curValue >= _totalTime) { _curValue = 0; _isRun = false; Debug.Log("Finish"); } SimsimulateParticlesForDeltaTime(deltaTime); //SimsimulateParticlesForTotoleTime(_curValue); } SceneView.RepaintAll(); GameViewRepaint(Camera.main); } private void GameViewRepaint(Camera camera) { if (camera) { Rect cameraRect = new Rect(0, 0, UnityEngine.Screen.width, UnityEngine.Screen.height); Rect cameraOriginalRect = camera.pixelRect; camera.pixelRect = cameraRect; camera.Render(); camera.pixelRect = cameraOriginalRect; } } }
The function documentation states:
function Simulate (deltaTime : float) : void
That is, the function parameter is a time delta, a step in time. It is not a certain moment in time.
Physical simulations work based on discrete steps in time. And the stability of many simulations (or rather the error within a simulation) is directly related to the size of a time step you take.
In your code, you're taking increasingly large steps in time. While single particles might put up with that for a while, given a sufficiently large step they might start to become unstable.
Most likely your problem will be resolved by taking a number of fixed time steps of a relatively small size.
public float initTime;
public ParticleEmitter partEmitter;
// Use this for initialization
public float deltaTime = 0.1f;
void Start () {
for (float i = 0.0f; i < initTime; i += deltaTime) {
partEmitter.Simulate(deltaTime);
}
}
I have taken your 0.1f here (a tenth of a second), but this might have to be even somewhat lower.
注意:ParticleSystem.Simulate 的第1個引數,傳入的是DeltaTime。