[英]Execute 2 methods c++ and c# at same time Unity
I have exported my native code in c++ into a dll and imported it in ac# script in unity. 我已经将c ++中的本机代码导出到一个dll中,并统一地以ac#脚本导入了它。 The C++ code reproduces music from a wav file.
C ++代码从wav文件再现音乐。 In the scene in unity I have a human head that can be rotated pressing the arrow keys.
在统一的场景中,我有一个可以按箭头键旋转的人头。 What I want to do is to synchronise both methods.
我想做的是同步两种方法。 I want to reproduce the music at the same time that I rotate the head because in a future,the music will change depending on the head rotation.
我想在旋转头部的同时再现音乐,因为将来音乐会根据头部旋转而改变。
For the moment, when I run the Unity game, the music starts playing and once its done, I can start playing rotating the humans head. 目前,当我运行Unity游戏时,音乐开始播放,音乐播放完毕后,我就可以开始旋转人类的头部了。 Not before.
没过
Here is my code: 这是我的代码:
Audio.h: Audio.h:
#pragma once
#include <iostream>
#define EXPORT __declspec(dllexport)
extern "C" {
EXPORT void initialize(std::string soundFilePaths[]);
EXPORT void setSourcePosition(std::string soundFilePath, float x, float y, float z);
EXPORT void play();
EXPORT void stop();
EXPORT void setListenerRotation(float x, float y, float z);
}
class Audio {
public:
static Audio& instance() { // Singleton
static Audio INSTANCE;
return INSTANCE;
}
void initialize(std::string soundFilePaths[]);
void setSourcePosition(std::string soundFilePath, float x, float y, float z);
void play();
void stop();
void setListenerRotation(float x, float y, float z);
~Audio();
private:
Audio();
};
Audio.cpp: Audio.cpp:
#include "Buffer.h"
#include "MonoSample.h"
#include "AudioDevice.h"
#include "Audio.h"
#include <windows.h>
#include <mmsystem.h>
#include <thread>
#include <stdio.h>
#include <conio.h>
#define NUMCHANNELS 2
#define OUTBUFSIZE 1024
#define CREATEWAVFILE true
extern "C" {
void initialize(const char *soundFilePaths[], bool continuous) {
Audio::instance().initialize(soundFilePaths,continuous);
}
void setSourcePosition(const char *soundFilePath, float x, float y, float z) {
Audio::instance().setSourcePosition(soundFilePath, x, y, z);
}
void play() {
Audio::instance().play();
}
void stop() {
Audio::instance().stop();
}
void setListenerRotation(float x, float y, float z) {
Audio::instance().setListenerRotation(x, y, z);
}
}
float degree;
int numCanals;
Buffer channel[NUMCHANNELS]; // Input buffer
unsigned char buffer[OUTBUFSIZE]; // Ouput buffer
wavHdr header, *pheader;
FILE* outFile; // Create output ( wave format) file
AudioDevice ad;
Audio::Audio()
{
}
Audio::~Audio()
{
}
void Audio::initialize(const char *soundFilePaths[], bool continuous)
{
char nom[20];
for (int i = 0; i < NUMCHANNELS; i++)
{
sprintf(nom, "%02d.wav", i + 1);
string fitxer(nom);
string path = WAVBASEPATH + fitxer;
if (!channel[i].openFile(path, i)) //obre i llegeix bytes (fread)
{
/*cout << "ERROR [" << i + 1 << "]";*/
ExitProcess(1);
}
}
int inSampleRate = channel[0].getHeader().samplesPerSec;
int inSampleLen = channel[0].getHeader().bitsPerSample;
int inNumberOfCn = channel[0].getHeader().numOfChan;
ad.iniAudioDevice(inSampleRate, inSampleLen, 2);
ad.setVolume50p();
}
void Audio::setSourcePosition(const char *soundFilePath, float x, float y, float z)
{
}
void Audio::play()
{
while (1)
{
long readBytes;
readBytes = channel[0].ReadInputBufferBlock(buffer, OUTBUFSIZE, channel, NUMCHANNELS, 1, false);
if (readBytes > 0)
{
ad.writeAudio((LPSTR)buffer, sizeof(buffer));
}
else
break;
}
}
void Audio::stop()
{
while (ad.waveFreeBlockCount < BLOCK_COUNT)
Sleep(10);
ad.closeAudioDevice();
}
Here is the C# script in Unity: 这是Unity中的C#脚本:
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine;
public class AudioPlugin : MonoBehaviour
{
public AudioContainer[] audioContainers;
public Transform headGeometry;
public float rotationSpeed = 50;
public float maxYRotation = 90;
public float minYRotation = -90;
float _currentYRotation;
void Start()
{
_currentYRotation = headGeometry.transform.rotation.eulerAngles.y;
string[] filePaths = GetAllFilePathsFromClips();
AudioPluginConnection.Initialize(filePaths);
AudioPluginConnection.Play();
}
void Update()
{
TurnHeadWithInput();
UpdateListenerRotation();
UpdateSoundPositions();
}
void OnDestroy()
{
AudioPluginConnection.Stop();
}
void TurnHeadWithInput()
{
float horizontal = Input.GetAxis("Horizontal");
horizontal *= Time.deltaTime * rotationSpeed;
_currentYRotation = Mathf.Clamp(_currentYRotation + horizontal, minYRotation, maxYRotation);
Vector3 eulerAngles = headGeometry.rotation.eulerAngles;
eulerAngles.y = _currentYRotation;
headGeometry.rotation = Quaternion.Euler(eulerAngles);
}
void UpdateListenerRotation()
{
Vector3 eulerAngles = headGeometry.rotation.eulerAngles;
AudioPluginConnection.SetListenerRotation(eulerAngles.x, eulerAngles.y, eulerAngles.y);
}
void UpdateSoundPositions()
{
foreach (AudioContainer container in audioContainers)
{
Vector3 position = container.source.position;
AudioPluginConnection.SetSourcePosition(container.filePath, position.x, position.y, position.z);
}
}
string[] GetAllFilePathsFromClips()
{
List<string> audioFilePaths = new List<string>();
foreach (AudioContainer container in audioContainers)
{
audioFilePaths.Add(container.filePath);
}
return audioFilePaths.ToArray();
}
}
[System.Serializable]
public class AudioContainer
{
public AudioClip clip;
public Transform source;
//Dont forget, that you have to copy the Audio Folder in the
//Unity Editor to the *_Data Folder in your builded Project!!! Quan construim projecte
public string filePath { get { return Application.dataPath + "/Audio/" + clip.name + ".wav"; } }
}
public class AudioPluginConnection
{
[DllImport("AudioPlugin", EntryPoint = "test")]
public static extern int Test();
[DllImport("AudioPlugin", EntryPoint = "initialize")]
public static extern void Initialize(string[] soundFilePaths);
[DllImport("AudioPlugin", EntryPoint = "setSourcePosition")]
public static extern void SetSourcePosition(string soundFilePath, float x, float y, float z);
[DllImport("AudioPlugin", EntryPoint = "play")]
public static extern void Play();
[DllImport("AudioPlugin", EntryPoint = "stop")]
public static extern void Stop();
[DllImport("AudioPlugin", EntryPoint = "setListenerRotation")]
public static extern void SetListenerRotation(float x, float y, float z);
}
I think I need to create a parallel thread to the main one in unity to be able to do both actions but I am not sure and I dont know how. 我想我需要统一创建一个与主线程的并行线程,以便能够执行这两项操作,但是我不确定,我也不知道如何做。
The function AudioPluginConnection.play() is the one that reproduces the sound and the function TurnHeadWithInput() the one which rotates the head. 函数AudioPluginConnection.play()是一个再现声音的函数,而函数TurnHeadWithInput()是一个旋转头部的函数。
My goal is to be able that while pressing the buttons that rotates the head, the music sounds as well. 我的目标是能够在按下旋转头部的按钮的同时发出音乐。 In a future, depending on the head rotation, I will apply an algorithm to the samples of the wav file and reproduce it.
将来,根据磁头旋转情况,我将对wav文件的样本应用一种算法并对其进行重现。
Thank you in advance 先感谢您
You are correct, you do need to create a separate thread and run your c++ functions from that thread. 没错,您确实需要创建一个单独的线程并从该线程运行c ++函数。 I'd recommend a few sources to learn from about threading: Bunny83 from Unity Answers responded here about a few important things about threading in Unity.
我建议从中学习一些有关线程的资料:Unity Answers的Bunny83在这里回答了有关Unity中线程的一些重要事项。
Threading is not implemented in Unity but in C# so I'd reccomend reading the MSDN tutorial on threading here 线程不是在Unity中实现的,而是在C#中实现的,因此我建议在这里阅读有关线程的MSDN教程
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.