千家信息网

基于JSBinding+SharpKit如何分析Delegate

发表于:2024-11-16 作者:千家信息网编辑
千家信息网最后更新 2024年11月16日,这篇文章给大家介绍基于JSBinding+SharpKit如何分析Delegate,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。以 NGUI 的 UIEventListener
千家信息网最后更新 2024年11月16日基于JSBinding+SharpKit如何分析Delegate

这篇文章给大家介绍基于JSBinding+SharpKit如何分析Delegate,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

以 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     else26         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就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

0