使用 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();
}
我工作的公司正在使用 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();
}