上一篇文章我们学习了Unity向Android发送消息,如果Android又能给Unity回馈消息那么这就玩美了。恰好Unity for Andoid 和 IOS一样都是可以相互与Unity发送与接收消息,这篇文章MOMO就和大家好好聊聊Android向Unity发送消息的方法。在读本片博文之前,建议大家读一下我上一篇文章Unity3D研究院之打开Activity与调用JAVA代码传递参数(十八),有关数据打包方面在上一篇中已经说的很清楚,这里就不再赘述。
我们在项目中创建两个Activity一个是主Activity一个是新打开的Activity和内容方面与上一篇文章类似。
UnityTestActivity.java 主Activity ,提供一个接口方法StartActivity(),它是由Unity中调用
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 {
/** Called when the activity is first created. */
Context mContext = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mContext = this;
}
public void StartActivity0(String name)
{
Intent intent = new Intent(mContext,TestActivity0.class);
intent.putExtra("name", name);
this.startActivity(intent);
}
}
接着是TestActivity.java 打开这个界面后,程序将在这里向Unity发送消息。
package com.xys;
import com.unity3d.player.UnityPlayer;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class TestActivity0 extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TextView text = (TextView)this.findViewById(R.id.textView1);
text.setText(this.getIntent().getStringExtra("name"));
final EditText edit = (EditText)this.findViewById(R.id.edit);
Button close = (Button)this.findViewById(R.id.button0);
close.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//注释1
UnityPlayer.UnitySendMessage("Main Camera","messgae",edit.getText().toString());
TestActivity0.this.finish();
}
});
}
}
需要在程序头引入包import com.unity3d.player.UnityPlayer; 因为向Unity发送消息的静态方法写在这里。
注释1:意思是点击发送按钮后,程序将向Unity发送消息。UnityPlayer.UnitySendMessage() 参数1表示发送游戏对象的名称,参数2表示对象绑定的脚本接收该消息的方法,参数3表示本条消息发送的字符串信息,这个方法与IOS发送消息的方式非常相像。
接着,我们打开Unity工程将Android插件打包好复制在Unity工程当中,详细打包过程请看上一章,将脚本Test.cs绑定在Main Camera对象中,此时由于UnityPlayer.UnitySendMessage()方法发送消息给MainCamera对象,所以需要在Main Camera对象绑定的脚本中去接收这个消息,也就是说要在Test.cs脚本中接收。
(图片比较大,点击后浏览大图)
下面我们看看Test.cs脚本
using UnityEngine;
using System.Collections;
public class Test : MonoBehaviour
{
//请输入一个字符串
private string stringToEdit = "Please enter a string";
void Update ()
{
//点击手机返回键关闭应用程序
if (Input.GetKeyDown(KeyCode.Escape) ¦¦ Input.GetKeyDown(KeyCode.Home) )
{
Application.Quit();
}
}
void OnGUI()
{
//绘制一个输入框接收用户输入
stringToEdit = GUILayout.TextField (stringToEdit, GUILayout.Width(300),GUILayout.Height(100));
//一个提交按钮
if(GUILayout.Button("commit",GUILayout.Height(50)))
{
//注解1
using (AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
{
using( AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity"))
{
//调用Android插件中UnityTestActivity中StartActivity0方法,stringToEdit表示它的参数
jo.Call("StartActivity0",stringToEdit);
}
}
}
}
//注解2
void messgae(string str)
{
stringToEdit = str;
}
}
注解1:让代码放置在using中是为了告诉垃圾回收站及时的回收垃圾,建议这样来写代码。AndroidJavaClass表示一个java类,AndroidJavaObject表示一个java对象,在上一章已经明确说明。另外还有一些其它的方法,比如调用静态方法等,都在API中写的很清楚,大家可以查阅学习。
注解2:刚刚调用的方法UnityPlayer.UnitySendMessage()参数2为”message”,所以程序将调用 Main Camera对象的Test.cs脚本的message方法,参数为Android传递过来的。最后在这里修改了stringToEdit变量刷新了屏幕的UI。
打开程序后将启动Unity画面,如上图在这里我们写了输入框接收用户的键盘输入,最后用户点击commit按钮程序将打开Android的Activity,并且将字符串“Please enter a string”做为参数传递给了新Activity。
如上图所示,在新打开的Activity中已经看到Please enter a string字符串已经显示在界面当中,在布局文件中同样写了Android的高级控件 输入框与按钮,在输入框中输入字符串“xuanyusong”(任意输入),点击保存按钮将把”xuanyusong”刚刚输入的字符串传递给Unity。
如上图所示,此时在Unity中字符串“xuanyusong”已经显示在输入框中,那么这样就比较完美了实现发送与接收消息。希望大家继续支持雨松MOMO程序研究院。
源码下载地址:http://vdisk.weibo.com/s/abEoV
- 本文固定链接: https://www.xuanyusong.com/archives/676
- 转载请注明: 雨松MOMO于 雨松MOMO程序研究院 发表





求助啊,主Activity中的StartActivity方法找不到。logcat报错说在UnityPlayerNativeActivity中找不到StartActivity,导致点击按钮之后没办法切换到安卓部分
请问另一种方式是什么呢
MOMO大神,我将一个第三方SDK工程以依赖库的形式导入我写的工程。打包的res复制SDK工程目录下的,AndroidManisest.xml也按要求写好的。但是我通过接口打开sdk工程的界面的时候却完全没有反应,正常至少有一个“加载中”的提示。求解啊?(我用eclipse导出的SPK没有问题)
解决了(⊙o⊙)…
你是怎么弄的
雨松,现在我将Untiy导入到Android中,界面上有按钮,在Untiy的内容未加载完之前按钮可以点击,但当画面加载完毕之后按钮就失效了。这大概是什么原因呢?
雨松MOMO 求助啊…点按钮后程序崩溃了应该是在 setContentView( R.layout.main ) 这里出错了错误信息是 android.content.res.Resources$NotFoundException: Resource ID #0x7f030017搞了好久还是不懂为什么“`
我也出现同样的问题 郁闷
已经解决 参考地址:http://bbs.csdn.net/topics/390832295http://forum.unity3d.com/threads/resource-not-found.81943/
我也遇到这个问题了..头痛死去, 你给网址已经打不开了………求助呀
思路就是 要通过代码动态获取资源 而不是用R获取资源 猜测是unity3d导出的时候资源路径变了 所以原来的R对应的资源地址无效了
请教一个问题,我在u3d中用startActivity打开一个Android的activity A,然后在A中再打开u3d的一个window,然后再返回到A。除了UnityPlayer.UnitySendMessage然后再finish掉A,还有没有别的办法,因为从u3d中回来的时候A的状态没有了。
如何让这两个activity里的东西同时运行啊?也就是说深度集成
一定要把C#脚本放到游戏物体上么?只把第一个参数设置为目标游戏物体的名字,脚本放在别的游戏物体上有没有道理啊?求解答啊
不是很懂UnitySendMessage()的第一个参数: 如果C#脚本是在一个DLL库里(不知道它将会被挂载到哪个Game Object),是否就不能接收接收Android消息了?
请教,u3d做android都是直接打包成apk,但是如果导出成eclipse工程(因为很多代码需要在activity这层增加)再打包apk,用这篇文章的实例会出现包名重复的问题,不知道如何解决。。
为什么会出现 “Caused by: java.lang.UnsatisfiedLinkError: Native method not found: com.unity3d.player.UnityPlayer.UnitySendMessage:…”这样的错误呢?应该怎么解决呢?查了好久都没有查到
这篇文章附件里,android代码都被打成jar了,如果android代码一起放出来下载就方便了
MOMO大想請問一下while(true){//is : an InputStream buf: an byte array//fos : an outputstream//progress total : int if (is == null) break; int numRead = is.read(buf); if (numRead <= 0) { break; } fos.write(buf, 0, numRead); this.progress = numRead; Log.d(“progress”, String.valueOf((float)this.progress * 100.0D / this.total) “%”); call(String.valueOf((float)this.progress * 100.0D / (float)this.total));}上述是其中unity透過plugin傳送給android java code來指明下載東西的其中一個function的部份code 下面是call function 使用unitysendmessage 傳送給unity 告知現在讀取進度public void call(String message) { UnityPlayer.UnitySendMessage(“mGameObject”, “CallUnityFromJAVA”, message); }然而在adb logcat會發現執行完許多log.d 到100%之後才會顯示unity 的 CallUnityFromJAVA function ,並且跟之前log.d 一樣 也是多個。所以想請問一下是否有辦法呼叫到的時候就去在unity上show出 而不是執行完讀取後才一次SHOW出來呢
MOMO大想請問一下while(true){//is : an InputStream buf: an byte array//fos : an outputstream//progress total : int if (is == null) break; int numRead = is.read(buf); if (numRead <= 0) { break; } fos.write(buf, 0, numRead); this.progress += numRead; Log.d(“progress”, String.valueOf((float)this.progress * 100.0D / this.total) + “%”); call(String.valueOf((float)this.progress * 100.0D / (float)this.total));}上述是其中unity透過plugin傳送給android java code來指明下載東西的其中一個function的部份code 下面是call function 使用unitysendmessage 傳送給unity 告知現在讀取進度public void call(String message) { UnityPlayer.UnitySendMessage(“mGameObject”, “CallUnityFromJAVA”, message); }然而在adb logcat會發現執行完許多log.d 到100%之後才會顯示unity 的 CallUnityFromJAVA function ,並且跟之前log.d 一樣 也是多個。所以想請問一下是否有辦法呼叫到的時候就去在unity上show出 而不是執行完讀取後才一次SHOW出來呢
问一下unity可以传参到网页中,但是网页传到unity怎么都不成功是怎么回事呢
这个不清楚哈, 我没做过网页的。。。
使用unity调用易宝支付的android插件,打开易宝支付后unity被关闭了,不知道是什么原因?
查一下LOG看看什么错误? 如果它用了多线程 就得用另一种方式来做。
这篇文章,我学到了很多,帮我解决了一个难题,但是应用的时候遇到另外一个问题,我通过Unity与安卓通信,启动外部的pdf浏览器,但是如果连续启动30次,即使我不打开任何pdf文件,程序也会死机,using我也用了,但是内存还是逐渐的减少,请问这是为什么啊?
补充一下,我本身项目的内存占用比较多,但是只要不启动外部的pdf浏览器,肯定不会死机,调用的外部代码也只是用来启动一个pdf浏览器浏览我指定的文件,经过测试,即使我不打开任何一个文件,30次左右的连续操作也会死机,困惑了很久了,MOMO,帮帮忙
再补充一下,pdf浏览器,我用了EZ,也试了Adobe reader和WPS, 都是一样的结果,所以我排除了浏览器的问题。
不好意思啊PDF 这个我也没做过的。。
这个问题就比较大了, 首先你需要排查 到底是untiy吃内存 还是 android插件吃内存。。然后在一点点把吃内存的地方释放掉。。 仔细检查代码吧。。。
其实偷偷在这里学了很多 一直在偷学哈。。今天出来感谢下。。我的ios 还有androi开发都是从这里学会的
过奖啦。。 娃哈哈
雨凇哥,我unity调用android的时候,首先出现一个白页面,然后才出现unity3d的logo,然后才加载的第一个场景的,请问我不想出现那个白页面有办法么?麻烦MOMO了~~~
你说的空白页 是不是 android 的那个?就是 带应用名称 小logo的那个? 那个东西去不掉的。 你可以自己创建一个不带插件的Android 工程。也会带那个。 官方的demo也带那个的。。。
出现错误JNI: Unable to find method id for ‘StartActivity0’UnityEngine.AndroidJavaObject:Call(String, Object[])Test:OnGUI() (at Assets/Test.cs:33),请问momo怎么解决?
仔细检查一下步骤, 中间那块可能出错了。。
恩,谢谢momo,在unity里面会出现这种错误,但是导到手机里就可以了,不知道为啥,哈哈
unity肯定会有这个错误了=, 是白色字提示的吧? 因为运行环境不一样噢。。。
哦,原来如此,谢谢啦MOMO