unity3d 获取脚本组件+高通AR,脚本中如何获取正在识别的图片的图片名

程序写累了,就来玩玩酷跑小游戏吧,嘿嘿。
雨松MOMO送你一首歌曲,嘿嘿。
Unity3D研究院之打开照相机与本地相册进行裁剪显示(三十三)
Unity3D研究院之打开照相机与本地相册进行裁剪显示(三十三)
围观42753次
编辑日期: 字体:
最近做项目需要用到这个功能,就是在Unity中调用Android本地相册或直接打开摄像机拍照并且裁剪一部分用于用户头像,今天研究了一下,那么研究出成果了MOMO一定要分享给大家。Unity与Android的交互还有谁不会?? 如果有不会的朋友请看MOMO之前的文章喔,这里有关交互的方式就不详细说明,主要将如何在Unity中打开摄像机、在Unity中打开本地相册,选一个照片后如何进行裁剪,最后将图片转换成Texture显示在U3D的世界当中。
首先看看Eclipse中的Android插件部分,我的包名是com.xys请大家与MOMO保持一致,Unity工程中也需要是这个包名噢。
UnityTestActivity.java 这个类是Unity的插件主类,在这里调用是打开摄像机 还是本地相册的方法。
1234567891011121314151617181920212223242526
package com.xys;&import android.content.Context;import android.content.Intent;import android.os.Bundle;import com.unity3d.player.UnityPlayerActivity;&public class UnityTestActivity extends UnityPlayerActivity {//public class UnityTestActivity extends Activity {& Context mContext = null;& @Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mContext = this; }& //Unity中会调用这个方法,用于区分打开摄像机 开始本地相册
public void TakePhoto(String str)
{ &&&&&&&& Intent intent = new Intent(mContext,WebViewActivity.class); &&&&&&&& intent.putExtra("type", str); &&&&&&&& this.startActivity(intent);
然后是WebViewActivity.java 这里主要处理用户打开摄像机或本地相册后如何进行裁剪图片,并且把裁剪的图片储存在本地文件中。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
package com.xys;&import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;&import com.unity3d.player.UnityPlayer;&import android.app.Activity;import android.content.Intent;import android.graphics.Bitmap;import android.net.Uri;import android.os.Bundle;import android.os.Environment;import android.provider.MediaStore;import android.view.KeyEvent;import android.widget.ImageView;&public class WebViewActivity extends Activity{&&&&&ImageView imageView = null;&&&&&&&public static final int NONE = 0;&&&&public static final int PHOTOHRAPH = 1;// 拍照&&&&public static final int PHOTOZOOM = 2; // 缩放&&&&public static final int PHOTORESOULT = 3;// 结果&&&&&&&public static final String IMAGE_UNSPECIFIED = "image/*";&&&&&&&public final static String FILE_NAME = "image.png";&&&&public final static String DATA_URL = "/data/data/";& @Override protected void onCreate(Bundle savedInstanceState) {&
super.onCreate(savedInstanceState);&
setContentView(R.layout.main);&
imageView = (ImageView) this.findViewById(R.id.imageID);&
String type = this.getIntent().getStringExtra("type");&
//在这里判断是打开本地相册还是直接照相
if(type.equals("takePhoto"))
&&Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);&&&&&&&&&&&&&&intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(Environment.getExternalStorageDirectory(), "temp.jpg")));&&&&&&&&&&&&&&startActivityForResult(intent, PHOTOHRAPH);
&&&&&& Intent intent = new Intent(Intent.ACTION_PICK, null);&&&&&&&&&&&&&& intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, IMAGE_UNSPECIFIED);&&&&&&&&&&&&&& startActivityForResult(intent, PHOTOZOOM);
}&&&&&}&&&&&&&@Override&&&&protected void onActivityResult(int requestCode, int resultCode, Intent data) {&&&&&&&&if (resultCode == NONE)&&&&&&&&&&&&return;&&&&&&&&// 拍照&&&&&&&&if (requestCode == PHOTOHRAPH) {&&&&&&&&&&&&//设置文件保存路径这里放在跟目录下&&&&&&&&&&&&File picture = new File(Environment.getExternalStorageDirectory() + "/temp.jpg");&&&&&&&&&&&&startPhotoZoom(Uri.fromFile(picture));&&&&&&&&}&&&&&&&&&&&if (data == null)&&&&&&&&&&&&return;&&&&&&&&&&&// 读取相册缩放图片&&&&&&&&if (requestCode == PHOTOZOOM) {&&&&&&&&&&&&startPhotoZoom(data.getData());&&&&&&&&}&&&&&&&&// 处理结果&&&&&&&&if (requestCode == PHOTORESOULT) {&&&&&&&&&&&&Bundle extras = data.getExtras();&&&&&&&&&&&&if (extras != null) {&&&&&&&&&&&&&&&&&&&Bitmap photo = extras.getParcelable("data");
&&&&&&&&imageView.setImageBitmap(photo);&&&&&&&&&&&&&&& try {&&&&&&&&&&&&
SaveBitmap(photo);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}&&&&&&&&&&&&}&&&&&&&&&&&}&&&&&&&&&&&super.onActivityResult(requestCode, resultCode, data);&&&&}&&&&&&&public void startPhotoZoom(Uri uri) {&&&&&&&&Intent intent = new Intent("com.android.camera.action.CROP");&&&&&&&&intent.setDataAndType(uri, IMAGE_UNSPECIFIED);&&&&&&&&intent.putExtra("crop", "true");&&&&&&&&// aspectX aspectY 是宽高的比例&&&&&&&&intent.putExtra("aspectX", 1);&&&&&&&&intent.putExtra("aspectY", 1);&&&&&&&&// outputX outputY 是裁剪图片宽高&&&&&&&&intent.putExtra("outputX", 300);&&&&&&&&intent.putExtra("outputY", 300);&&&&&&&&intent.putExtra("return-data", true);&&&&&&&&startActivityForResult(intent, PHOTORESOULT);&&&&}&&& public void SaveBitmap(Bitmap bitmap) throws IOException {&
FileOutputStream fOut = null;&
String path = "/mnt/sdcard/Android/data/com.xys/files";
&&//查看这个路径是否存在,
&&//如果并没有这个路径,
&&//创建这个路径
&&File destDir = new File(path);
&&if (!destDir.exists())
&&destDir.mkdirs();&
fOut = new FileOutputStream(path + "/" + FILE_NAME) ;
} catch (FileNotFoundException e) {
e.printStackTrace();
//将Bitmap对象写入本地路径中,Unity在去相同的路径来读取这个文件
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fOut);
fOut.flush();
} catch (IOException e) {
e.printStackTrace();
fOut.close();
} catch (IOException e) {
e.printStackTrace();
} }& @Override public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0)
&& //当用户点击返回键是 通知Unity开始在"/mnt/sdcard/Android/data/com.xys/files";路径中读取图片资源,并且现在在Unity中
&& UnityPlayer.UnitySendMessage("Main Camera","message",FILE_NAME);&
return super.onKeyDown(keyCode, event); }}
注解1:主要是路径”/mnt/sdcard/Android/data/com.xys/files”,如下图所示,我们在这里把文件保存在这个路径下。为什么要把图片2进制文件写在这里呢? 还记得以前MOMO给大家说过在Unity中访问Android或IOS本地2进制文件时用到的这个路径,
Application.persistentDataPath
该路径等价于 /mnt/sdcard/Android/data/com.xys/files ,当然后者的包名是对应的工程包名,这样在Unity中可以找到对应裁剪后的图片文件,并且显示在Unity中。
AndroidManifest.xml
这个文件也没什么好说的,大家看看吧。
123456789101112131415161718192021222324252627282930313233
&?xml version="1.0" encoding="utf-8"?&&manifest xmlns:android="/apk/res/android"&&&&package="com.xys"&&&&android:versionCode="1"&&&&android:versionName="1.0" &&&&&&&uses-sdk android:minSdkVersion="10" /&&&&&&&application&&&&&&&&android:icon="@drawable/ic_launcher"&&&&&&&&android:label="@string/app_name" &&&&&&&&&&activity&&&&&&&&&&&&android:name=".UnityTestActivity"&&&&&&&&&&&&android:label="@string/app_name" &&&&&&&&&&&&&&intent-filter&&&&&&&&&&&&&&&&&&action android:name="android.intent.action.MAIN" /&&&&&&&&&&&&&&&&&&&category android:name="android.intent.category.LAUNCHER" /&&&&&&&&&&&&&&/intent-filter&&&&&&&&&&/activity&&&&&&&& &activity&&&&&&&&&&&&android:name=".WebViewActivity"&&&&&&&&&&/activity&&&&&&/application&&&&&&&!-- 连接互联网的权限 --&&&&&&uses-permission android:name="android.permission.INTERNET" /&&&&&&!-- SDCard中创建与删除文件权限 --&&uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/&&!-- SDCard写入数据权限 --&&uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/&&/manifest&
然后把上面的Android工程打包做成插件放在Unity中。如下图所示,这个我的Unity工程中对应的路径。如果看不懂的朋友请看我之前的文章哈。
然后看Test.cs脚本,它直接挂在摄像机身上。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
using UnityEngine;using System.Collections;using System.IO;&public class Test : MonoBehaviour{ public GUISkin skin; Texture texture;& void Update () {&
if (Input.GetKeyDown(KeyCode.Escape) || Input.GetKeyDown(KeyCode.Home))&&
Application.Quit();&&
} }& void OnGUI() {
GUI.skin = skin;&
if(GUILayout.Button("打开手机相册"))
//调用我们制作的Android插件打开手机相册
AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");&&&&&&
AndroidJavaObject jo = jc.GetStatic&AndroidJavaObject&("currentActivity");&&&&&&&&
jo.Call("TakePhoto","takeSave");&
if(GUILayout.Button("打开手机摄像机"))
//调用我们制作的Android插件打开手机摄像机
AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");&&&&&&
AndroidJavaObject jo = jc.GetStatic&AndroidJavaObject&("currentActivity");&&&&&&&&
jo.Call("TakePhoto","takePhoto");&
if(texture != null)
//注意! 我们在这里绘制Texture对象,该对象是通过
//我们制作的Android插件得到的,当这个对象不等于空的时候
//直接绘制。
GUI.DrawTexture(new Rect(100,300,300,300),texture);
} }& void&&messgae(string str) {
//在Android插件中通知Unity开始去指定路径中找图片资源
StartCoroutine(LoadTexture(str));& }&&&IEnumerator LoadTexture(string name)&&{ //注解1 string path&&=&&"file://" + Application.persistentDataPath +"/" + name;& WWW www = new WWW(path); while (!www.isDone) {& } yield return www; //为贴图赋值 texture = www.texture;&&}}
注解1:请大家一定要注意这个路径的写法, 前面一定要加 “File://” 不然无法读取。OK说了这么多我们看看这个项目运行的效果,激动人心的时刻来临啦 嚯嚯嚯嚯!!!
1.首次进入的画面, 这里的图片是我刚刚从相册选择的
2.打开相册我们选择一张图片
3. 选择一张图片,我们进行裁剪
最后我们返回到Unity中界面。新的图片Unity已经完成读取,界面上已经修改成刚刚我裁剪的啦,哇咔咔。 怎么样,还不错啦? 哈哈后。这个做用户头像肯定给力 蛤蛤。
如果点击打开摄像机按钮,拍照完毕后会提示裁剪,裁减完毕返回到Unity界面中同样能看到效果。
最后MOMO将本篇博文的源码放出来,
源码包括Android的工程 与Unity的工程,雨松MOMO祝大家学习愉快,大家互相学习互相进步,加油哇咔咔,啦啦啦。
下载地址:
本文固定链接:
转载请注明:
雨松MOMO提醒您:亲,如果您觉得本文不错,快快将这篇文章分享出去吧 。另外请点击网站顶部彩色广告或者捐赠支持本站发展,谢谢!
作者:雨松MOMO
专注移动互联网,Unity3D游戏开发
如果您愿意花10块钱请我喝一杯咖啡的话,请用手机扫描二维码即可通过支付宝直接向我捐款哦。
您可能还会对这些文章感兴趣!Unity中获取手机图片 - 推酷
Unity中获取手机图片
项目开发笔记 (七)
很多APP中都会有个人信息,或者个人帐号 都会有设置头像功能,国内的很多APP更加是如此(很多人的帐号密码泄密,正是由于到处注册帐号,举个我当年密码泄漏的例子,在很多年的某一天 我在某个网吧的嘟嘟牛系统注册了一个帐号,当时毫无安全意识,直接用个人密码作为嘟嘟牛的密码,很多年后的今天 我在嘟嘟牛的用户数据库里找到了我当年的个人所有信息…我怎么会有嘟嘟牛的数据库?它有很多种途径能到我手里.A.黑客把嘟嘟牛黑掉,把数据库拿到地下交易市场卖,B.嘟嘟牛的DBA励志 顺带把数据库带出来等等..),言归正传,目前我在参与一个类APP项目的优化工作.使用Unity开发.也有这种..设置用户头像的需求
Unity Varsion: 5.x or 4.x
本文内容非纯干货,如果不想看可以直接下载Sample -
难点主要在几个地方:
Unity与iOS/Android原生代码之间的调用
iOS/Android 对摄像机的调用与图片截取
iOS/Android 对图片的IO操作
Unity与iOS/Android原生代码之间的调用
Unity对原生的调用支持相对还是很好的.也非常简单.
对于Android
主要的方法是通过获取主Activity对象,然后调用主Activity中的pubilc信息,举个栗子
AndroidJavaClass androidActivityClass = new AndroidJavaClass(&com.unity3d.player.UnityPlayer&);
m_NativeObj = androidActivityClass.GetStatic
(¤tActivity&);
m_NativeObj.Call(
&SettingAvaterFormMobile&,
// Java函数名
strObjectName,
// 传入的参数
strFuncName,
// 传入的参数
strFileName);
// 传入的参数
上面即调用主Activity上的SettingAvaterFormMobile函数.
Android原生代码要给Unity调用 还需要配置一些基本内容:
1.在Android项目的生成文件夹bin下命令行生成Jar包
在确认Android项目代码无误的情况下,到项目目录 bin\classes 下,打开命令行定位到这里,然后使用命令生成jar文件
jar -cvf xxx.jar * // xxx为文件名 可随意设置
2.Android项目需要取得原生jar包放到Unity项目文件夹 Assets\Plugins\Android\bin 目录(没有就自行创建) ,再取 AndroidManifest.xml,res文件夹 ,放到 Assets\Plugins\Android 文件夹下.如图:
3.对于Android项目源码包的获取,Unity4.x 和 5.x方法不一样,如果是Unity5 需要把项目目录 bin\classes 下编译的R.java生成文件删掉.
由于iOS开发可以OC与C/C++之间无缝调用,所以其实调用iOS原生函数 是通过调用C/C++函数中转的.方法非常简单.在C#脚本端声明一个C++函数,即可直接调用:
//-------------------------------------------------------------------------
[DllImport(&__Internal&)]
private static extern
void SettingAvaterFormiOS(string strObjectName, string strFuncName, string strFileName);
//-------------------------------------------------------------------------
#elif UNITY_IPHONE
SettingAvaterFormiOS(strObjectName, strFuncName, strFileName);
//-------------------------------------------------------------------------
若需要调用一个Android项目的NDK开发的C++函数,原理也是一样的.
iOS原生代码要给Unity调用 还需要配置一些基本内容:
把自行编写的iOS代码复制到Unity项目文件夹文件夹 Assets\Plugins\IOS\ 下(没有就自行创建),如图
iOS/Android 对摄像机的调用与图片截取
对于Andorid
Android打开照相机和打开相册选取照片非常简单,网上代码一吨:
// 打开摄像机获取图片
if(v.getId() == m_OpenCameraID)
eResult = CommonUtil.ENUM_RESULT.eResult_C
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(
MediaStore.EXTRA_OUTPUT,
Uri.fromFile(new File(Environment.getExternalStorageDirectory(), m_ImageFileName)));
m_contextAct.startActivityForResult(intent, eResult.ordinal());
// 打开相册选取图片
else if(v.getId() == m_GetPictureID)
eResult = CommonUtil.ENUM_RESULT.eResult_P
Intent intent = new Intent(Intent.ACTION_PICK, null);
intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, IMAGE_UNSPECIFIED);
m_contextAct.startActivityForResult(intent, eResult.ordinal());
iOS打开照相机和打开相册选取照片非常简单,网上代码也一吨:
//-------------------------------------------------------------------------
// 关键实现
- (void)showPicker:(UIImagePickerControllerSourceType)type
UIImagePickerController *picker = [[[UIImagePickerController alloc] init] autorelease];
picker.delegate =
picker.sourceType =
// 打开摄像机或者打开相册
picker.allowsEditing = YES;// 图片是否可编辑
if( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad )
Class popoverClass = NSClassFromString( @&UIPopoverController& );
if( !popoverClass )
_popoverViewController = [[popoverClass alloc] initWithContentViewController:picker];
[_popoverViewController setDelegate:self];
[_popoverViewController presentPopoverFromRect:CGRectMake( 0, 0, 128, 128 )
inView:UnityGetGLViewController().view
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
UIViewController *vc = UnityGetGLViewController();
[vc presentModalViewController:picker animated:YES];
//-------------------------------------------------------------------------
iOS/Android 对图片的IO操作
获取的图片文件,可大可小,我们不能直接传string回Unity,所以可以事先保存到本地目录下.最佳的目录是 Application.persistentDataPath .
对于Android
这个目录就是: &/mnt/sdcard/Android/data/& + packageID + &/files& .(packageID为APP包名)保存图片文件代码片段:
FileOutputStream fOut =
String strPackgeName = getApplicationInfo().packageN
String path = &/mnt/sdcard/Android/data/& + strPackgeName + &/files&;
File destDir = new File(path);
if (!destDir.exists())
destDir.mkdirs();
fOut = new FileOutputStream(path + &/& + m_ImageFileName) ;
catch (FileNotFoundException e)
e.printStackTrace();
pressFormat.PNG, 100, fOut);
fOut.flush();
catch (IOException e)
e.printStackTrace();
fOut.close();
catch (IOException e)
e.printStackTrace();
这个目录就是: Application/packageID/Documents .(packageID为APP包名)
NSString * DocumentsPath =
[NSHomeDirectory() stringByAppendingPathComponent:@&Documents&];
NSFileManager *fileManager =
[NSFileManager defaultManager];
[fileManager createDirectoryAtPath:DocumentsPath
withIntermediateDirectories:YES
attributes:nil
error:nil];
[fileManager createFileAtPath:[DocumentsPath stringByAppendingString:m_pstrFileName]
contents:imgData attributes:nil];
如此获取的图片就保存到了指定的目录中.这个时候只要告诉回调到Unity通知一下 即可.
设置了用户头像,一般都会有上传头像到服务器的功能,关于C#上传图片到服务器网上也也有一吨的版本,但是Unity官方文档中的是如下:
//-------------------------------------------------------------------------
IEnumerator __UploadPNG()
var bytes = m_texture2D.EncodeToPNG();
var form = new WWWForm();
form.AddField(&frameCount&, Time.frameCount.ToString());
form.AddBinaryData(&avatarPicture&, bytes, &avatar.png&, &image/png&);
// m_ImageUpDownURL URL上传接口
var w = new WWW(m_ImageUpDownURL, form);
if (!string.IsNullOrEmpty(w.error))
Debug.Log(w.error);
Debug.Log(&Finished Uploading Image&);
//-------------------------------------------------------------------------
http://blog.csdn.net/poem_qianmo/article/details/
/2013/07/shader-tutorial-1/
/Manual/SL-SurfaceShaders.html
http://http./CgTutorial/cg_tutorial_chapter05.html
http://blog.csdn.net/candycat1992/article/category/1782159
/archives/1493
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致

参考资料

 

随机推荐