#c# #unity3d #vuforia #hololens
#c# #unity-игровой движок #vuforia #hololens
Вопрос:
Я пытаюсь сделать снимок через Hololens с помощью моего скрипта PhotoCapture unity. Я хочу использовать движок Vuforia ARCamera, чтобы иметь возможность видеть реальность одновременно с созданным мной AR-GUI (для будущей функциональности).
Основная ошибка, которую я получаю, это:
Не удалось сделать снимок (hr = 0xC00D3704)
Почему это происходит? Как мне это исправить?
Синглтон FocusManager не был инициализирован. UnityEngine.Отладка: утверждение (логическое значение, строка) HoloToolkit.Единство.Singleton`1:AssertIsInitialized() (в Assets/HoloToolkit/Common/Scripts/Singleton.cs:51) HoloToolkit.Единство.CanvasHelper:Start() (в Assets/HoloToolkit/Utilities/Scripts/CanvasHelper.cs:30)
также возникает ошибка при запуске сцены unity, но раньше у меня ее не было…
Это код, который я использую, размещенный на ARCamera (я также опробовал камеру смешанной реальности со сценарием поведения vuforia, и он не выдал вторую ошибку). Также я хочу извиниться перед человеком, у которого позаимствован этот код, потому что я не помню ссылку на ваш сайт.
public class PhotoCaptureExample : MonoBehaviour
{
PhotoCapture photoCaptureObject = null;
Texture2D targetTexture = null;
public string path = "";
CameraParameters cameraParameters = new CameraParameters();
void Start()
{
}
void Update()
{
if (Input.GetKeyDown("k"))
{
Debug.Log("k was pressed");
Resolution cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();
targetTexture = new Texture2D(cameraResolution.width, cameraResolution.height);
// Create a PhotoCapture object
PhotoCapture.CreateAsync(false, delegate (PhotoCapture captureObject)
{
photoCaptureObject = captureObject;
cameraParameters.hologramOpacity = 0.0f;
cameraParameters.cameraResolutionWidth = cameraResolution.width;
cameraParameters.cameraResolutionHeight = cameraResolution.height;
cameraParameters.pixelFormat = CapturePixelFormat.BGRA32;
// Activate the camera
photoCaptureObject.StartPhotoModeAsync(cameraParameters, delegate (PhotoCapture.PhotoCaptureResult result)
{
// Take a picture
photoCaptureObject.TakePhotoAsync(OnCapturedPhotoToMemory);
});
});
}
}
string FileName(int width, int height)
{
return string.Format("screen_{0}x{1}_{2}.png", width, height, DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss"));
}
void OnCapturedPhotoToMemory(PhotoCapture.PhotoCaptureResult result, PhotoCaptureFrame photoCaptureFrame)
{
// Copy the raw image data into the target texture
photoCaptureFrame.UploadImageDataToTexture(targetTexture);
Resolution cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();
targetTexture.ReadPixels(new Rect(0, 0, cameraResolution.width, cameraResolution.height), 0, 0);
targetTexture.Apply();
byte[] bytes = targetTexture.EncodeToPNG();
string filename = FileName(Convert.ToInt32(targetTexture.width), Convert.ToInt32(targetTexture.height));
//save to folder under assets
File.WriteAllBytes(Application.dataPath "/Snapshots/" filename, bytes);
Debug.Log("The picture was uploaded");
// Deactivate the camera
photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
}
void OnStoppedPhotoMode(PhotoCapture.PhotoCaptureResult result)
{
// Shutdown the photo capture resource
photoCaptureObject.Dispose();
photoCaptureObject = null;
}
}
Кажется, что я не могу добраться до OnCapturedPhotoToMemory
или если он уже прерывается вызовом метода. Повторная попытка прямо сейчас, код иногда вообще не регистрирует, что я нажал k
…
Любая помощь приветствуется!!
Комментарии:
1. Как был настроен FocusManager? это действительно unityscript? для меня это выглядит как обычный c #
2. честно говоря, я понятия не имею, что такое FocusManager и откуда он взялся: S Раньше он не отображался, но мог возникнуть, когда я вернулся к ARCamera из holotoolkits mixedRealityCamera… Это C #, но разве это несовместимо со скриптом unity (скриптом, созданным в unity)?
3. О, sry, я получил неправильный тег!!!
4. Хорошо, но он сообщает вам, что focusmanager не был настроен, это, кажется, первый пункт ошибки?
5. @BugFinder Да. После ошибки происходит 3 вызова
FocusManager.AssertIsInitialized();
одного из методов SimpleSinglePointerSelector private void Start(). Один в методе CanvasHelper private void Start(). И еще один в CanvaseditorExtention, чтобы проверить, «есть ли у нас менеджер фокусировки в нашей сцене». Я не касался ни одного из них.
Ответ №1:
Проблема в том, что Vuforia VuforiaBehaviour
на камере имеет доступ к реальному оборудованию камеры устройства => пока что ничто другое не может его использовать.
Для исправления этого вы могли бы использовать специальную камеру для Vuforia (просто где-нибудь поместите новый игровой объект, например, VuforiaCamera
в сцену и прикрепите к нему Camera
компонент, а также VuforiaBehaviour
a).
Для камеры Vuforia установлено Culling Mask
значение Nothing
(мы ничего не визуализируем с помощью этой камеры) и Depth
, например, -2
(более высокие значения отображаются сверху -> поместите это позади всех других камер).
Вы должны это сделать, потому что в противном случае Vuforia автоматически добавит его к основной камере (которую мы не хотим отключать, потому что тогда мы ничего не увидим). При ручном добавлении изображения в сцену Vuforia автоматически использует его вместо этого.
Везде в вашей сцене, где вам нужна камера, вы, конечно, используете оригинальную камеру из Holo-Took (вашу обычную MainCamera
). Проблема, на которую вы не можете полностью положиться Camera.main
в скриптах, потому что во время выполнения VuforiaBehaviour
также автоматически помечается его Camera
как MainCamera
… (-_-) Vuforia … таким образом, дополнительно я всегда отключал и включал VuforiaBehaviour
вместе с GameObject, но, возможно, уже достаточно только отключить и включить GameObject. По крайней мере, при запуске игры это должно быть отключено, я думаю, до тех пор, пока не будет завершено все, на что полагается Camera.main
.
Тогда вы можете просто отключить тот, VuforiaCamera
на котором есть VuforiaBehaviour
.
VuforiaBehaviour.Instance.gameObject.SetActive(false);
// Note: that part I'm just inventing since I did it different
// using reference etc. I hope vuforia does not destroy the Instance
// OnDisable .. otherwise you would need the reference instead of using Instance here
// but maybe it is already enough to just enable and disable the GameObject
VuforiaBehaviour.Instance.enabled = false;
Благодаря этому камера устройства стала «свободной», и PhotoCapture теперь может ее использовать.
PhotoCapture.StartPhotoModeAsync(....
Если затем вам снова понадобится камера для vuforia, сначала остановите фотосъемку
PhotoCapture.StopPhotoModeAsync(..
и затем, после того, как он остановился при обратном вызове, повторно включите ARCamera
(объект с VuforiaBehaviour
) и VuforiaBehaviour
снова.
Что-то вроде
private void Awake()
{
var cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();
targetTexture = new Texture2D(cameraResolution.width, cameraResolution.height);
// Create a PhotoCapture object
PhotoCapture.CreateAsync(false, captureObject =>
{
photoCaptureObject = captureObject;
cameraParameters.hologramOpacity = 0.0f;
cameraParameters.cameraResolutionWidth = cameraResolution.width;
cameraParameters.cameraResolutionHeight = cameraResolution.height;
cameraParameters.pixelFormat = CapturePixelFormat.BGRA32;
});
}
private void Update()
{
// if not initialized yet don't take input
if (photoCaptureObject == null) return;
if (Input.GetKeyDown("k"))
{
Debug.Log("k was pressed");
VuforiaBehaviour.Instance.gameObject.SetActive(false);
// Activate the camera
photoCaptureObject.StartPhotoModeAsync(cameraParameters, result =>
{
if (result.success)
{
// Take a picture
photoCaptureObject.TakePhotoAsync(OnCapturedPhotoToMemory);
}
else
{
Debug.LogError("Couldn't start photo mode!", this);
}
});
}
}
private static string FileName(int width, int height)
{
return $"screen_{width}x{height}_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.png";
}
private void OnCapturedPhotoToMemory(PhotoCapture.PhotoCaptureResult result, PhotoCaptureFrame photoCaptureFrame)
{
// Copy the raw image data into the target texture
photoCaptureFrame.UploadImageDataToTexture(targetTexture);
Resolution cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();
targetTexture.ReadPixels(new Rect(0, 0, cameraResolution.width, cameraResolution.height), 0, 0);
targetTexture.Apply();
byte[] bytes = targetTexture.EncodeToPNG();
string filename = FileName(Convert.ToInt32(targetTexture.width), Convert.ToInt32(targetTexture.height));
//save to folder under assets
File.WriteAllBytes(Application.streamingAssetsPath "/Snapshots/" filename, bytes);
Debug.Log("The picture was uploaded");
// Deactivate the camera
photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
}
private void OnStoppedPhotoMode(PhotoCapture.PhotoCaptureResult result)
{
// Shutdown the photo capture resource
photoCaptureObject.Dispose();
photoCaptureObject = null;
VuforiaBehaviour.Instance.gameObject.SetActive(true);
}
Однако исключение также может быть связано с этой проблемой.
Комментарии:
1. Итак, у меня должно быть 2 камеры; одна описанная выше и одна основная камера?
2. ДА. Камере Vuforia вообще не нужно двигаться. Он используется только для доступа к реальной камере устройства.
3. Я все еще не до конца понимаю. Итак, у меня есть maincamera с тегом MainCamera, и у меня есть ARCamera со сценарием на ней с компонентами камеры и поведения vuforia? Установлен ли скрипт на нужную камеру? На какую камеру должен указывать холст?
4. Я добавил свою настройку. Я заметил, что на самом деле я в своем скрипте дополнительно включаю и отключаю
VuforiaBehaviour
сам, но это не должно иметь значения. На всех canvas и т.д., Где бы вам ни понадобилась камера, вы продолжаете использовать «обычную» главную камеру, как и раньше.. вы только добавляете дополнительную ARCamera с настройками, как на добавленном рисунке5. Я все еще получаю
Failed capturing photo (hr = 0xC00D3704)
ошибку. Я пытался использовать толькоVuforiaBehaviour.Instance.gameObject.SetActive(false);
, а затем толькоVuforiaBehaviour.Instance.enabled = false;
, а затем оба из них, они действуют одинаково, так что, вероятно, не имеет значения, какой из них использовать в моем случае 🙂 Они были добавлены в start() (чтобы убедиться, что он не включен с самого начала), доphotoCaptureObject.StartPhotoModeAsync
и в конце вOnStoppedPhotoMode
. Извините за медлительность, но чего я не понимаю?