Как проиграть звук из файла (не добавляя его в ассеты)

Общие вопросы о Unity3D

Как проиграть звук из файла (не добавляя его в ассеты)

Сообщение EIvanov 30 окт 2022, 17:37

Я понимаю, как загружать и проигрывать звуковые файлы из ассетов.
И в большинстве случаев такого функционала хватает. Загрузил файлы в ассеты, перетащил их в паблик поля и играй в коде.
Синтаксис:
Используется csharp
public class GameSoundsScript : MonoBehaviour
{
private AudioSource _audioSource;

public AudioClip _audioClip_1;
public AudioClip _audioClip_2;

void Start ()
{
_audioSource = GetComponent<AudioSource>();
}

public void PlaySound (int audioClipNumber)
{
if (audioClipNumber == 1) _audioSource.PlayOneShot(_audioClip_1);
}
}
 

Но у меня другая задача.

В моей игре пользователь может загружать свои звуковые файлы. То есть нужно проиграть звуковой файл, лежащий по определенному пути, например c:\...Assets\StreamingAssets\base\sounds\1.mp3
Как это сделать?
EIvanov
UNIт
 
Сообщения: 103
Зарегистрирован: 05 июл 2021, 17:23

Re: Как проиграть звук из файла (не добавляя его в ассеты)

Сообщение 1max1 30 окт 2022, 19:43

https://docs.unity3d.com/ScriptReferenc ... oClip.html
Работает не только для веб ресурсов, но и с обычным диском (должен, вроде как).
Аватара пользователя
1max1
Адепт
 
Сообщения: 5505
Зарегистрирован: 28 июн 2017, 10:51

Re: Как проиграть звук из файла (не добавляя его в ассеты)

Сообщение EIvanov 30 окт 2022, 22:09

1max1, спасибо с файлом на диске, под Windows, работает.
Правда 1 раз, то есть при повторном вызове возникает ошибка.
Я что то не освободил/удалил?

InvalidOperationException: Cannot get content from an unfinished UnityWebRequest object
UnityEngine.Networking.DownloadHandler.GetCheckedDownloader[T] (UnityEngine.Networking.UnityWebRequest www) (at <1abe9eafdcf148ab9a14dd434f1379a0>:0)
UnityEngine.Networking.DownloadHandlerAudioClip.GetContent (UnityEngine.Networking.UnityWebRequest www) (at <5ea14ebd042a43589259b3ce86393628>:0)
PlaySoundFromFile.PlaySound (System.String pathToSound, UnityEngine.AudioSource audioSource) (at Assets/Scripts/PlaySoundFromFile.cs:25)


Реализовал как то так
Синтаксис:
Используется csharp
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking; // UnityWebRequest


public static class PlaySoundFromFile
{

// Проиграть mp3 звук из файла.
public static void PlaySound(string pathToSound, AudioSource audioSource)
{
UnityWebRequest unityWebRequest = null;
AudioClip audioClip = null;
 
unityWebRequest = UnityWebRequestMultimedia.GetAudioClip(pathToSound, AudioType.MPEG); // AudioType.MPEG - звук в формате mp3.
unityWebRequest.SendWebRequest();

if (unityWebRequest.result == UnityWebRequest.Result.ConnectionError)
{
Debug.Log("Ошибка проигрывания звука "+unityWebRequest.error);
}
else
{
audioClip = DownloadHandlerAudioClip.GetContent(unityWebRequest); // 25 строка Вот тут ошибка.
}
audioSource.PlayOneShot(audioClip);  
 
}

}
EIvanov
UNIт
 
Сообщения: 103
Зарегистрирован: 05 июл 2021, 17:23

Re: Как проиграть звук из файла (не добавляя его в ассеты)

Сообщение DbIMok 02 ноя 2022, 19:26

потому что в примере по ссылке выше непонятные слова не зря написаны. там через yield return дожидаются результата запроса прежде чем выполнять тот код что ниже
правильный вопрос - половина ответа. учитесь формулировать вопросы понятно.
Новости > _Telegram чат @unity3d_ru (11.6k/4.8k online) > _Telegram канал @unity_news (4.7k подписчиков) > Телеграм тема > "Спасибо"
Аватара пользователя
DbIMok
Адепт
 
Сообщения: 6372
Зарегистрирован: 31 июл 2009, 14:05

Re: Как проиграть звук из файла (не добавляя его в ассеты)

Сообщение EIvanov 02 ноя 2022, 22:23

потому что в примере по ссылке выше непонятные слова не зря написаны

И как мне проиграть звук?
В коде выше много того, что мне не нужно.
StartCoroutine - не работает без MonoBehaviour. MonoBehaviour не работает со статическими классами.
IEnumerator - интерфейс, как я понял предполагающий много значений - звуков. У меня 1 звук.
void Start() - мне не нужен.
Я пока даже не представляю как писать обёртку к классу MyBehaviour.

Мой код работает, но только 1 раз.
Неужели нельзя просто отчистить объекты, поля?

Вообще странная логика - в любом ОП чтение файла, звука, чего угодно - 3 строки кода, без Coroutine, IEnumerator и т.д.
EIvanov
UNIт
 
Сообщения: 103
Зарегистрирован: 05 июл 2021, 17:23

Re: Как проиграть звук из файла (не добавляя его в ассеты)

Сообщение 1max1 02 ноя 2022, 22:46

При старте сцены ты можешь один раз закешировать файлы, потом использовать их напрямую.
Аватара пользователя
1max1
Адепт
 
Сообщения: 5505
Зарегистрирован: 28 июн 2017, 10:51

Re: Как проиграть звук из файла (не добавляя его в ассеты)

Сообщение DbIMok 02 ноя 2022, 23:36

EIvanov писал(а):StartCoroutine - не работает без MonoBehaviour

да
EIvanov писал(а):MonoBehaviour не работает со статическими классами.

работать может. не может быть сам статическим
EIvanov писал(а):void Start() - мне не нужен.

это для того чтобы он в примере сработал. не нужен - не беда, это не важно
EIvanov писал(а):Неужели нельзя просто отчистить объекты, поля?

можно, конечно
EIvanov писал(а):IEnumerator - интерфейс, как я понял предполагающий много значений - звуков

нет, это способ организации корутин
EIvanov писал(а):в любом ОП чтение файла, звука, чего угодно - 3 строки кода

чтение файла - да. загрузка из сети в любом языке потребует ожидания окончания.
в юнити можно подождать в корутине, в Update или async-await
правильный вопрос - половина ответа. учитесь формулировать вопросы понятно.
Новости > _Telegram чат @unity3d_ru (11.6k/4.8k online) > _Telegram канал @unity_news (4.7k подписчиков) > Телеграм тема > "Спасибо"
Аватара пользователя
DbIMok
Адепт
 
Сообщения: 6372
Зарегистрирован: 31 июл 2009, 14:05

Re: Как проиграть звук из файла (не добавляя его в ассеты)

Сообщение EIvanov 03 ноя 2022, 00:25

загрузка из сети в любом языке потребует ожидания окончания

Нет. Это не верно даже исходя из логики. Окончания чего?
Потоковое видео, асинхронная загрузка, ошибки сервера...

Скрытый текст:
PHP
Просто - смотрите 1 строка кода. Без корутинов и прочего. Что под капотом - другой вопрос.
Синтаксис:
  1. $file = file_get_contents('http://www.example.com/', false, $context); 


Чуть сложнее
Синтаксис:
  1. $ch = curl_init('https://example.com'); 
  2. //curl_setopt..... 
  3. $html = curl_exec($ch); 
  4. curl_close($ch); 


JS-AJAX-JQUERY
Синтаксис:
  1. $.ajax({ 
  2. url: '/index.php', /* Куда отправить запрос */ 
  3. method: 'get', /* Метод запроса (post или get) */ 
  4. dataType: 'html', /* Тип данных в ответе (xml, json, script, html). */ 
  5. data: {text: 'Текст'}, /* Данные передаваемые в массиве */ 
  6. success: function(data){ /* функция которая будет выполнена после успешного запроса. */ 
  7. alert(data); /* В переменной data содержится ответ от index.php. */ 
  8. }); 


DELPHI
Синтаксис:
  1. try 
  2. hURL := InternetOpenURL(hSession, PChar(fileURL), nil, 0, 0, 0); 
  3. try 
  4. AssignFile(f, FileName); 
  5. Rewrite(f,1); 
  6. repeat 
  7. InternetReadFile(hURL, @Buffer, SizeOf(Buffer), BufferLen); 
  8. BlockWrite(f, Buffer, BufferLen); 
  9. until 
  10. BufferLen = 0; 
  11. CloseFile(f); 
  12. Result := True; 
  13. finally 
  14. InternetCloseHandle(hURL); 


Почему в Unity так нельзя - загадка.
Написал обертку для MonoBehaviour (который в туториале) - не работает потому что...нельзя создавать экземпляры класса MonoBehaviour.
И что теперь делать? Мне MonoBehaviour не нужен. Чтобы его вызвать нужно создать экземпляр класса. Статикой он быть не может.
Это через какую пень-колоду нужно вызвать обычный звуковой файл?
EIvanov
UNIт
 
Сообщения: 103
Зарегистрирован: 05 июл 2021, 17:23

Re: Как проиграть звук из файла (не добавляя его в ассеты)

Сообщение 1max1 03 ноя 2022, 04:07

Ты не можешь считывать мгновенно данные из сети, это факт и данность. Почему юнити решили запихнуть чтение из сети и с диска в 1 метод - хз, тут только смирится и прочитать про шаблон синглтон чтобы использовать статику и монобехи одновременно.
Аватара пользователя
1max1
Адепт
 
Сообщения: 5505
Зарегистрирован: 28 июн 2017, 10:51

Re: Как проиграть звук из файла (не добавляя его в ассеты)

Сообщение DbIMok 03 ноя 2022, 15:48

в общем, если хочется не зависеть от монобеха, то как-то так
Синтаксис:
Используется csharp
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Networking;

public class Downloader {
    public static async void DownloadAndPlay(AudioSource audioSource, string pathToSound) {
        var unityWebRequest = UnityWebRequestMultimedia.GetAudioClip(pathToSound, AudioType.MPEG);
        unityWebRequest.SendWebRequest();
        while (!unityWebRequest.isDone) await Task.Yield();
        if (unityWebRequest.result != UnityWebRequest.Result.Success) {
            Debug.LogWarning($"{unityWebRequest.error}: {pathToSound}");
            return;
        }
        var audioClip = DownloadHandlerAudioClip.GetContent(unityWebRequest);
        if (audioSource.isPlaying) audioSource.Stop();
        audioSource.PlayOneShot(audioClip);  
    }
}

[RequireComponent(typeof(AudioSource))]
public class Test : MonoBehaviour {
    Rect rectPlay = new Rect(5, 5, 100, 20);
    AudioSource audioSource;
    void Start() {
        audioSource = GetComponent<AudioSource>();
    }
    void OnGUI() {
        if (GUI.Button(rectPlay,"Play")) {
            Downloader.DownloadAndPlay(audioSource,
                @"https://ruo.morsmusic.org/load/662655886/Shpongle_-_When_Shall_I_be_Free_(musmore.com).mp3");
                //@"C:\Music\Shpongle\2005 - Nothing Lasts But Nothing Is Lost\09 - When Shall I Be Free.mp3");
        }
    }
}
 
правильный вопрос - половина ответа. учитесь формулировать вопросы понятно.
Новости > _Telegram чат @unity3d_ru (11.6k/4.8k online) > _Telegram канал @unity_news (4.7k подписчиков) > Телеграм тема > "Спасибо"
Аватара пользователя
DbIMok
Адепт
 
Сообщения: 6372
Зарегистрирован: 31 июл 2009, 14:05

Re: Как проиграть звук из файла (не добавляя его в ассеты)

Сообщение EIvanov 03 ноя 2022, 22:05

Ты не можешь считывать мгновенно данные из сети, это факт и данность.

Мы не можем мгновенно считывать данные откуда угодно. На всё надо время. Всё относительно.
Скорость чтения данных зависит от объема данных, пропускной способности канала, интерфейса (протокола, условий-помехи-доступность и т.д.).
Например, по устаревшему интерфейсу IDE максимальная скорость 150 MБ/с.
SATA 3 — 600 Мб/с.
Оптоволокно - от 1Гбитс до 44,2 Тбит/с.
Да в том же юнити загружаются не все сцены сразу. А на сцене - не все объекты сразу.

DbIMok Сегодня, 15:48

в общем, если хочется не зависеть от монобеха, то как-то так

Спасибо, работает. Сам бы я такое не написал.
EIvanov
UNIт
 
Сообщения: 103
Зарегистрирован: 05 июл 2021, 17:23


Вернуться в Общие вопросы

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 12