重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
这篇文章给大家介绍基于JSBinding+SharpKit如何分析Delegate,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。
创新互联建站长期为数千家客户提供的网站建设服务,团队从业经验10年,关注不同地域、不同群体,并针对不同对象提供差异化的产品和服务;打造开放共赢平台,与合作伙伴共同营造健康的互联网生态环境。为伊美企业提供专业的网站设计、成都网站建设,伊美网站改版等技术服务。拥有十多年丰富建站经验和众多成功案例,为您定制开发。
以 NGUI 的 UIEventListener 为例:
有一个类:
using SharpKit.JavaScript; using UnityEngine; using System.Collections; [JsType(JsMode.Clr,"../StreamingAssets/JavaScript/SharpKitGenerated/z_temp/test0610.javascript")] public class test0610 : MonoBehaviour { public UIButton btn; void Start () { // 在此注册回调 UIEventListener.Get(btn.gameObject).onClick = this.OnClick; // (*) } void OnClick(GameObject go) { Debug.Log("onclick "); } }
这个类有一个 public UIButton btn; 变量,可以在 Inspector 里赋值。我们用这个类来响应 btn 的点击事件。重点就是第12行。
生成的JS如下:
1 if (typeof(JsTypes) == "undefined") 2 var JsTypes = []; 3 var test0610 = { 4 fullname: "test0610", 5 baseTypeName: "UnityEngine.MonoBehaviour", 6 assemblyName: "SharpKitProj", 7 Kind: "Class", 8 definition: { 9 ctor: function (){ 10 this.btn = null; 11 UnityEngine.MonoBehaviour.ctor.call(this); 12 }, 13 Start: function (){ 14 UIEventListener.Get(this.btn.get_gameObject()).onClick = $CreateDelegate(this, this.OnClick); // (*) 15 }, 16 Update: function (){ 17 }, 18 OnClick: function (go){ 19 UnityEngine.Debug.Log$$Object("onclick "); 20 } 21 } 22 }; 23 JsTypes.push(test0610);
看 JS代码 第14行,将 onClick 赋值为 $CreateDelegate 的返回值
$CreateDelegate 的作用是返回一个函数,具体可以看 jsclr.javascript 文件里这个函数的定义。这里不讨论这个函数的实现细节,只要知道他返回一个函数就可以了。这个函数传到 C# 后就变成一个ID。
当然,如果要让这段JS可以正常执行,当然要将 UIEventListener 配置到 JSBindingSettings.classes 数组让他导出,来看一下 onClick 这个字段的C#代码:
1 public static UIEventListener.VoidDelegate UIEventListener_onClick_GetDelegate_member2_arg0(CSRepresentedObject objFunction) 2 { 3 if (objFunction == null || objFunction.jsObjID == 0) 4 { 5 return null; 6 } 7 UIEventListener.VoidDelegate action = (go) => 8 { 9 JSMgr.vCall.CallJSFunctionValue(0, objFunction.jsObjID, go); 10 }; 11 return action; 12 } 13 static void UIEventListener_onClick(JSVCall vc) 14 { 15 if (vc.bGet) { 16 UIEventListener _this = (UIEventListener)vc.csObj; 17 var result = _this.onClick; 18 JSMgr.vCall.datax.setObject((int)JSApi.SetType.Rval, result); 19 } 20 else { 21 UIEventListener _this = (UIEventListener)vc.csObj; 22 _this.onClick = JSDataExchangeMgr.GetJSArg(()=>{ 23 if (JSApi.isFunctionS((int)JSApi.GetType.Arg)) 24 return UIEventListener_onClick_GetDelegate_member2_arg0(JSApi.getFunctionS((int)JSApi.GetType.Arg)); 25 else 26 return (UIEventListener.VoidDelegate)vc.datax.getObject((int)JSApi.GetType.Arg); 27 }) 28 ; 29 } 30 }
第22行在赋值 onClick 字段。因为 onClick 是 Delegate,所以赋值也要给他一个 Delegate,这个 Delegate 是由函数 UIEventListener_onClick_GetDelegate_member2_arg0 返回的(第1行)。
第24行首先调用 JSApi.getFunctionS(..) 获取 JS 函数 ID。CSRepresentedObject 只是对 JS 对象的一个封装而已。UIEventListener_onClick_GetDelegate_member2_arg0 拿到这个函数ID后,
构造了一个 UIEventListener.VoidDelegate 类型的 Delegate ,最终赋值给了 UIEventListener.onClick。
以上是比较简单的情况:将 JS 函数存储在 C#。
再来看一种情况,将 C# 函数存储在 JS。
// C#
1 TweenEasingCallback func = TweenEasingFunctions.GetFunction(this.EaseType ); 2 3 transform.TweenPosition() 4 .SetEndValue( transform.position + ( Vector3.right * 9f ) ) 5 .SetDelay( 0.5f, false ) 6 .SetDuration( 1.33f ) 7 .SetEasing( func ) 8 .SetLoopType( TweenLoopType.Loop ) 9 .Play();
// JS代码
1 var func = DaikonForge.Tween.TweenEasingFunctions.GetFunction(this.EaseType); // get a delegate from C# (1) 2 TweenTransformExtensions.TweenPosition$$Transform(this.get_transform()) 3 .SetEndValue(UnityEngine.Vector3.op_Addition(this.get_transform().get_position(), (UnityEngine.Vector3.op_Multiply$$Vector3$$Single(UnityEngine.Vector3.get_right(), 9)))) 4 .SetDelay$$Single$$Boolean(0.5, false) 5 .SetDuration(1.33) 6 .SetEasing(func) // give back to C# (2) 7 .SetLoopType(1) 8 .Play();
这种情况下也是要事先将 TweenEasingFunctions 配置到 JSBindingSettings.classes,让他导出,JS才可以使用。
// TweenEasingFunctions.GetFunction 的绑定代码:
1 static bool TweenEasingFunctions_GetFunction__EasingType(JSVCall vc, int argc) 2 { 3 int len = argc; 4 if (len == 1) 5 { 6 DaikonForge.Tween.EasingType arg0 = (DaikonForge.Tween.EasingType)JSApi.getEnum((int)JSApi.GetType.Arg); 7 JSMgr.vCall.datax.setObject((int)JSApi.SetType.Rval, DaikonForge.Tween.TweenEasingFunctions.GetFunction(arg0)); 8 } 9 10 return true; 11 }
可以看到,当 JS 从 C# 获得一个 delegate 时,会调用 JSDataExchange.setObject 函数。
这里不贴出 setObject 的具体代码,请查看源代码。
在 setObject 函数中,会判断,如果这个对象是个 delegate,那么就创建一个 JSRepresentedObject 对象返回给 JS,同时保存这2者的对应关系。
JSRepresentedObject 的定义在 StreamingAssets/JavaScript/SharpKit/myclrhandler.javascript 最前面。
那么,JS拿到这个对象后,是无法使用的。因为他是C#这边的函数。他只能把这个东西再还给C#。请看上面JS代码标记 (2) 那一句。当他返回给C#时,C#可以根据之前存储的对应关系找到 Delegate。
关于基于JSBinding+SharpKit如何分析Delegate就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。