使用 Unity3D 和 Vuforia 的 Android 4.1.2 上的相机是黑色的

Camera is black on Android 4.1.2 with Unity3D and Vuforia

我工作的公司正在使用 vuforia(版本 5.x)和 Unity3D(版本 5.3.5f1 个人)集成构建一个 android 应用程序。

在最新的 android 设备中,相机打开正常,但我们在三星 Galaxy S2(4.1.2) 等旧设备中遇到问题。当设备通过 vuforia 打开相机时,屏幕是黑色的,如果我们尝试拍照,图像也明显是黑色的。

我的activity只是实例化统一播放器,就像下面的代码:

public class MainActivity extends AppCompatActivity {

protected UnityPlayer mUnityPlayer;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    getWindow().setFormat(PixelFormat.RGBX_8888); // <--- This makes xperia play happy
    mUnityPlayer = new UnityPlayer(this);
    setContentView(mUnityPlayer);
    mUnityPlayer.requestFocus();
}

public void onImageSaved(final String path) {
    final Intent intent = new Intent(MainActivity.this, CameraPreviewActivity.class);
    final Bundle bundle = new Bundle();
    bundle.putString("IMAGE_PATH", path);
    intent.putExtras(bundle);
    startActivity(intent);
}

public void onImageSavedError(final String message) {
    UnityPlayer.currentActivity.runOnUiThread(new Runnable() {

        @Override
        public void run() {
            Log.e("Teste", message);
        }
    });
}

// Quit Unity
@Override protected void onDestroy ()
{
    mUnityPlayer.quit();
    super.onDestroy();
}

// Pause Unity
@Override protected void onPause()
{
    super.onPause();
    mUnityPlayer.pause();
}

// Resume Unity
@Override protected void onResume()
{
    super.onResume();
    mUnityPlayer.resume();
}

// This ensures the layout will be correct.
@Override public void onConfigurationChanged(Configuration newConfig)
{
    super.onConfigurationChanged(newConfig);
    mUnityPlayer.configurationChanged(newConfig);
}

// Notify Unity of the focus change.
@Override public void onWindowFocusChanged(boolean hasFocus)
{
    super.onWindowFocusChanged(hasFocus);
    mUnityPlayer.windowFocusChanged(hasFocus);
}

// For some reason the multiple keyevent type is not supported by the ndk.
// Force event injection by overriding dispatchKeyEvent().
@Override public boolean dispatchKeyEvent(KeyEvent event)
{
    if (event.getAction() == KeyEvent.ACTION_MULTIPLE)
        return mUnityPlayer.injectEvent(event);
    return super.dispatchKeyEvent(event);
}

// Pass any events not handled by (unfocused) views straight to UnityPlayer
@Override public boolean onKeyUp(int keyCode, KeyEvent event)     { return mUnityPlayer.injectEvent(event); }
@Override public boolean onKeyDown(int keyCode, KeyEvent event)   { return mUnityPlayer.injectEvent(event); }
@Override public boolean onTouchEvent(MotionEvent event)          { return mUnityPlayer.injectEvent(event); }
/*API12*/ public boolean onGenericMotionEvent(MotionEvent event)  { return mUnityPlayer.injectEvent(event); }

@Override
public void onBackPressed() {
    finish();
}

}

vuforia负责打开相机并开始跟踪图像目标,而unity3D会渲染带有动画的3D图像并负责拍照。

在 unity 项目中,我们开发了一个拍照按钮和一个将图像保存在 android 目录中的功能。它的脚本是用C#写的,实现如下:

IEnumerator TakeSnapshot()
{
    yield return new WaitForEndOfFrame();
    Texture2D snap = new Texture2D(Screen.width,Screen.height);
    Camera camera = Camera.current;

    if (rotation != null)
    {
        camera.transform.rotation = rotation.Value;
    }

    if (position != null)
    {
        camera.transform.position = position.Value;
    }

    camera.Render();
    RenderTexture.active = camera.targetTexture;
    snap.ReadPixels(new Rect(0,0,Screen.width,Screen.height),0,0);
    snap.Apply();
    RenderTexture.active = null;

    byte[] bytes = snap.EncodeToJPG();
    DestroyObject(snap);

    string path = Application.persistentDataPath + "/MyAppPath/";
    if(!System.IO.Directory.Exists(path)){
        System.IO.Directory.CreateDirectory(path);
    }

    string filename = fileName(Convert.ToInt32(snap.width), Convert.ToInt32(snap.height));
    path = path + filename;
    System.IO.File.WriteAllBytes(path, bytes);

    using (var actClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
    {
        var jo = actClass.GetStatic<AndroidJavaObject>("currentActivity");

        if (jo == null) {
            Debug.Log ("jo is null");
        } else {
            jo.Call("onImageSaved", path);
        }
    }
}

这个 post 的主要目标是尝试理解为什么摄像头在较旧的设备上工作正常,但只在较旧的设备上是黑色的。我还想强调 openGL 可能不是问题,因为我已经使用 sinogen 5.1 在三星 Galaxy S2 等旧设备上测试了该应用程序。 当前导出的 unity 项目的 openGL 版本是 openGL2。 提前致谢。

试试这个代码:

public string deviceName;
WebCamTexture wct;
void Start ()
{
    WebCamDevice[] devices = WebCamTexture.devices;
    deviceName = devices[0].name;
    wct = new WebCamTexture(deviceName, 400, 300, 12);
    GetComponent<Renderer> ().material.mainTexture = wct;
    wct.Play();
}