开启辅助访问
 找回密码
 注册帐号

扫一扫,访问微社区

教程分享

关注:577

当前位置:游戏蛮牛 技术专区 教程分享

查看: 1173|回复: 0

[基础知识] Unity热更新之C#反射动态获取类属性及方法

[复制链接]  [移动端链接]
7日久生情
3558/5000
排名
2615
昨日变化
2

1393

主题

1398

帖子

3558

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
132510
好友
17
蛮牛币
26218
威望
0
注册时间
2015-12-24
在线时间
276 小时
最后登录
2017-2-21
发表于 2016-9-7 14:24:43 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?注册帐号

x
  如果我们要为发布出去的游戏更新一些功能,但又不想让用户重新下载整个游戏包,只让他下载我们更新的资源包,用assetBundle打包资源的方式是可以的,但其中有个最大的例外,那就是脚本。

  虽然assetBundle支持直接将脚本或者DLL打包在内,但没有经过unity编译的话,assetBundle中的脚本是访问不到unity总工程中的脚本的,因为他们已经完全分离在了两个程序集,用C#加载程序集的方式导入DLL的话是可行的,但即便如此,想要在assetBundle脚本与unity总工程脚本之间进行通信也还是会出现问题的。

  例如我从assetBundle打包的DLL中取出的一个类NewlyAdded.cs,把他add到场景某一物体之上后,想要获取到场景物体Player上的Control.cs脚本中的float变量Health,然后再调用他的方法MassHealing(float health)。

  按照正常方式:

  [csharp] view plain copy 在CODE上查看代码片派生到我的代码片

  //NewlyAdded.cs

  GameObject _player = GameObject.Find("Player").gameObject;

  float _f = _player.GetComponent<Control>().Health;

  _player.GetComponent<Control>().MassHealing(100.0f);

  如果这样做的话,我的NewlyAdded.cs脚本在发布DLL的时候就无法编译通过,因为在这段代码里他找不到Control这个类,那么只有将Control.cs也放到一起打包,这样的话虽然编译通过成功发布成DLL了,但打包成assetBundle发到客户端运行的时候你会发现GetComponent<Control>()取到的是一个奇怪的类,事实上因为被分离在了两个程序集外的原因他这里所取到的是在发布NewlyAdded.cs 的DLL那个工程里的Control类,就算本地有同名类,他是不会替换的。

  解决这个问题的话,可以用到C#的反射:

  [csharp] view plain copy 在CODE上查看代码片派生到我的代码片

  //NewlyAdded.cs

  float _f;

  //取Player上的所有脚本

  MonoBehaviour[] monos = GameObject.Find("Player").GetComponents<MonoBehaviour>();

  for (int i = 0; i < monos.Length; i++)

  {

  //筛选出其中的Control脚本

  if (monos.GetType().ToString().EndsWith("Control"))

  {

  //获取Health字段的值

  _f = (float)monos.GetType().GetField("Health").GetValue(monos);

  //执行其公有方法MassHealing

  monos.GetType().GetMethod("MassHealing", BindingFlags.Public).

  Invoke(null, new System.Object[] { 100.0f});

  break;

  }

  }

  这样的话,在编译的时候就可以完全的通过。

1.png


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册帐号

本版积分规则

快速回复 返回顶部 返回列表