当前位置: 代码迷 >> JavaScript >> Unity3D -day03(js、C#互调)
  详细解决方案

Unity3D -day03(js、C#互调)

热度:937   发布时间:2013-10-06 18:25:14.0
Unity3D --day03(js、C#互调)

网上有类似调用的例子,是这么说的:JS文件必须是在 "StandardAssets"、 "Pro StandardAssets“和 "Plugins"这三个目录中的任何一个里,而CS文件不能与JS文件在一个目录中,原因是,这三个目录里的脚本被最先编译,"Editor"目录里的稍后编译,其他的脚本最后编译。如果在一个目录下则CS文件无法读取JS里的方法,也就无法编译通过了。而JS调用CS方法则无此限制。


问题:js代码里调用C#方法

function OnGUI(){
if(GUI.Button (new Rect(100,170,200,100),"c >> js")){
var cs  = GameObject.Find("Main Camera").GetComponent("CS_test");
var s :String = cs.Call();
Debug.Log(s);
}
}
function Call() : String{
return "from js";
}

此时,C#代码必须要先被编译,就是将C#放入到Plugins文件夹中先编译出来后被js调用。


问题:c#调用js方法

using UnityEngine;
using System.Collections;


public class CS_test : MonoBehaviour {
void OnGUI(){
if(GUI.Button (new Rect(100,70,200,100),"c >> js")){
JS_test js = (JS_test)GameObject.Find ("Main Camera").GetComponent("JS_test");
string s = js.Call();
Debug.Log(s);
}
}
public string Call(){
return "from CS";
}
}

此时,这个js要先被编译,js放在Standard Assets文件夹中先编译后被C#调用。


问题:可是如果js和c#同时互相调用,就会出现矛盾,不知道哪个先编译,存在一个先编译,一个后编译的问题,这样就出现矛盾了。


http://zhaolongchn.blog.163.com/blog/static/19065850420124293495168/

Unity中C#代码和JavaScript代码互相调用(方法一)  

目前在项目中自己写的代码都用C#,但有时候从网上下载到的代码是用Javascript,如果只是绑定到GameObject上使用的倒还好,有什么修改也可以直接修改脚本代码。但有时候需要在自己写的C#代码中调用这些下载的Javascript代码时,问题出现了。

 

编译时总是报告无法找到这些Javascript脚本,在Script Execution Order中指定脚本编译顺序也没有用。还是在Unity文档中找到了解决方法:http://unity3d.com/support/documentation/ScriptReference/index.Script_compilation_28Advanced29.html

 

脚本的编译过程分四步:

1. 编译所有 ”Standard Assets”, “Pro Standard Assets” or “Plugins” 目录下的代码

2. 编译所有“Standard Assets/Editor”, “Pro Standard Assets/Editor” or “Plugins/Editor” 目录下的代码

3. 编译除了上面列出来的目录和Editor目录之外的所有代码

4. 编译Editor目录下的代码

 

这样的话,如果你希望某个Javascript能被其他脚本引用,那么把它放到第一组的某个目录里,然后把要使用它的代码放在第三组的某个目录里就好了。

同样,如果希望某个C#代码能被其他Javascript脚本引用,也必须把这个C#脚本放到第一组的某个目录里,Javascript代码放到第三组的某个目录里。

 

需要注意的是,代码一旦放在第一组目录中,它们一定是最先被编译的,所以它们将不可能直接引用其他组的脚本,但是可以通过SendMessage方式间接引用,可能会有一些效率方面的损失。这也造成了一个结果,两个非同种语言编写的脚本之间不能互相引用,否则无法区分出应该让哪个脚本优先编译。

 

另外一点是,第一组目录中的脚本一旦重新编译,会使得第三组目录中的所有代码也重新编译,这将会增加总的编译时间。所以,对于可能会经常变动的代码,尽量不要放到第一组目录中去,除非它们因为被其他脚本引用的原因不得不放到这里。

 

编辑器(Editor)相关的代码编译顺序及引用规则与此类似,只不过目录在第二组和第四组中定义。

Unity中C#代码和JavaScript代码互相调用(方法二)  

根据C#的反射原理,进行代码互掉,代码文件要导包System.Reflection;
C#调用JavaScript代码:
C#写的三个方法:

public static System.Object getField(Component script, string fieldName) { 
    FieldInfo fieldInfo = script.GetType().GetField(fieldName); 
    System.Object obj = fieldInfo.GetValue(script); 
    return obj; 

 
public static void setField(Component script, string fieldName, System.Object value) { 
    FieldInfo fieldInfo = script.GetType().GetField(fieldName); 
    fieldInfo.SetValue(script, value); 

 
public static  System.Object invokeMethod(Component script, string methodName, System.Object[] param) { 
    MethodInfo methodInfo = script.GetType().GetMethod(methodName); 
    System.Object obj = methodInfo.Invoke(script, param); 
    return obj; 


JavaScript调用C#代码:

JavaScript写的三个方法:

public static function getField(script : Component, fieldName : String) : System.Object{ 
    var fieldInfo : FieldInfo = script.GetType().GetField(fieldName); 
    var obj : System.Object = fieldInfo.GetValue(script); 
    return obj; 

 
public static function setField(script : Component, fieldName : String, value : System.Object) { 
    var fieldInfo : FieldInfo = script.GetType().GetField(fieldName); 
    fieldInfo.SetValue(script, value); 

 
public static function invokeMethod(script : Component, methodName : String, param : System.Object[]) : System.Object{ 
    var methodInfo : MethodInfo = script.GetType().GetMethod(methodName); 
    var obj : System.Object = methodInfo.Invoke(script, param); 
    return obj;