Это
IEnumerator SetFrame()
{
yield return new WaitForSeconds(0.3f);
encoder.AddFrame(tex);
encoder.AddSamples(audioBuffer);
if (recordingButtonHasBeenPressed)
{
yield return StartCoroutine(SetFrame());
}
}
является рекурсивным вызовом, когда вы снова yield return
повторяете ту же процедуру (которая внутренне yield return
снова повторяет ту же процедуру и c), поэтому она ожидает, пока все вложенные подпрограммы не будут закончено => Так что в какой-то момент вы получите StackOverflow!
Это определенно закрытый никогда не заканчивается, в то время как l oop
using (var audioBuffer = new NativeArray<float>(sampleFramesPerVideoFrame, Allocator.Temp))
{
do
{
encoder.AddFrame(tex);
encoder.AddSamples(audioBuffer);
} while (recordingButtonHasBeenPressed);
}
в пределах l oop значение recordingButtonHasBeenPressed
не будет никогда изменено, и Unity / ваше приложение сразу же зависнет навсегда!
То, что вы хотели бы сделать вместо этого, было бы сопрограммой типа
IEnumerator SetFrame()
{
// initially wait once
yield return new WaitForSeconds(0.3f);
// simply continue to execute the routine until the record shall be stopped
while(recordingButtonHasBeenPressed)
{
encoder.AddFrame(tex);
encoder.AddSamples(audioBuffer);
// yield the next frames for 0.3 seconds before checking
// recordingButtonHasBeenPressed again
yield return new WaitForSeconds(0.3f);
}
}
Тогда вам даже не нужно будет активно останавливать это. Все, что вам нужно сделать, это запустить его, а затем, чтобы прервать, просто установите recordingButtonHasBeenPressed
в false
.
Сделайте это управляемым событием
Теперь, в общем, вместо использования Update
и флага нескольких контроллеров bool
с, вы сразу же начинаете сбрасывать снова, когда здесь вызывается метод, я бы предпочел сделать весь код управляемым событиями и один раз вызвать когда кнопка вызывается. Это предотвратит случайное выполнение параллельных подпрограмм и улучшит чтение и поддержку всего этого.
Я не знаю ваш полный код, но он может выглядеть примерно так:
public void RecordVideo_OnClick()
{
// invert the toggle flag
videoIsRecording = !videoIsRecording;
// depending on the new flag value chose the sprite
videoRecordButton.image.sprite = videoIsRecording ? videoButtonIsRecordingSprite : videoButtonIsNotRecordingSprite;
if (!videoIsRecording)
{
_myRecorderSc.StopRecording();
}
else
{
_myRecorderSc.StartRecoring();
}
}
и тогда в скрипте рекордера вам понадобится только
public void StartRecording()
{
if(!recording)
{
StartCoroutine(RecorderRoutine);
}
}
public void StopRecording()
{
recording = false;
}
// flag to interrupt running record
private bool recording;
private IEnumerator RecorderRoutine()
{
// Just in case prevent concurrent routines
if(recording) yield break;
recording = true;
// initialize your file
CreateVideoBasicFile();
// initially wait once
yield return new WaitForSeconds(0.3f);
using (var encoder = new MediaEncoder(encodedFilePath, videoAttr, audioAttr))
using (var audioBuffer = new NativeArray<float>(sampleFramesPerVideoFrame, Allocator.Temp))
{
// simply continue to execute the routine until the record shall be stopped
while(recording)
{
encoder.AddFrame(tex);
encoder.AddSamples(audioBuffer);
// yield the next frames for 0.3 seconds before checking
// recordingButtonHasBeenPressed again
yield return new WaitForSeconds(0.3f);
}
}
recording = false;
}