Unity 使用中使用FairyGUI遇到的坑

首先!首先!首先!

首先,我们由于历史问题,项目用的UI编辑器不是大众使用的GUI或者NGUI, 而是使用不知道算不算小众的FairyGUI,这个UI系统使用挺方便的,也提供了很多UI编码的案例,至少从直接使用来说方便了不少。

但是!但是!但是!

可能用到这个UI编辑器的不是那么多,项目上遇到的问题在网上百度出来的结果很少,基本自己断点查找bug。

最后!最后!最后!

我这个从没写过几次技术博客的人,要写这篇技术贴的原因是:昨晚加班到四五点钟查找BUG回到屋里,发现由于没有关好自己卧室的门,室友养的猫进我屋里尿了我一床,所以不得不马上更换棉被,才取睡觉!

1.关于在FairyGUI中使用Unity项目里的Sprite问题

在FairyGUI中使用Unity的Sprite需要使用控件GLoader来装载Sprite.官方给予的使用方法是

//Unity, 这里加载的是路径为Assets/Resources/demo/aimage的一个贴图
aLoader.url = “demo/aimage”;

如果Sprite是在一个Sprite图集中,则需要重写自己的GLoader类,

class MyGLoader  : GLoader
{
    override protected function LoadExternal()
    {
        /*
        开始外部载入,地址在url属性
        载入完成后调用OnExternalLoadSuccess
        载入失败调用OnExternalLoadFailed
        注意:如果是外部载入,在载入结束后,调用OnExternalLoadSuccess或OnExternalLoadFailed前,
        比较严谨的做法是先检查url属性是否已经和这个载入的内容不相符。
        如果不相符,表示loader已经被修改了。
        这种情况下应该放弃调用OnExternalLoadSuccess或OnExternalLoadFailed。
        */
    }
    override protected function FreeExternal(NTexture texture)
    {
        //释放外部载入的资源
    }
}

并且注册自己的GLoader

UIObjectFactory.SetLoaderExtension(typeof(MyGLoader));

但是这里并没有告诉我们该怎样具体加载Sprite.
实际上只需要自己查找到Sprite载入就行

		protected override void LoadExternal()
        {
        	// 这里使用成员变量url查找Sprite载入即可
            if (url.Length > 0)
            {
            	Sprite tSprite= Resources.Load<Sprite>(url);
             	this.onExternalLoadSuccess(new NTexture(tSprite));
            }

            this.onExternalLoadFailed();
        }

但是如果Sprite是在一个图集中,图片就显示不正确了。
查找了很久才发现FairyGUI使用的图集和Unity中使用的图集Y轴相反,需要重新计算Rect才能正确加载。即

protected override void LoadExternal()
 {
	if (url.Length > 0)
     {
     	Sprite[] tSprites= Resources.LoadAll<Sprite>(url);
     	Sprite tSprite = tSprites[0];
     	// 这里需要将Y轴反转
	     Rect tShowRect = new Rect(tSprite.textureRect.x, tSprite.texture.height - tSprite.textureRect.y - tSprite.textureRect.height, 
	     								tSprite.textureRect.width, tSprite.textureRect.height);
         this.onExternalLoadSuccess(new NTexture(tSprite.texture, tShowRect));
     }
 }

基本上这样子就解决了GLoader使用Unity的Sprite 问题。

2.使用Sprite Atlas打包图集遇到的问题

由于美术给予的图片都是单个的图片,并没有将打包成为一张图片,所以需要程序自行打包。在多次询问谷哥和度娘以后,才知道Unity有个新的图集打包插件Sprite Atlas很好使用
1.创建Sprite Atlas:创建Sprite Atlas
2.选择需要打包的图片或者图片所在的文件夹(这里会将文件夹内的图片和子文件夹内的图片一起打包)
也可以打包预制体
选择需要打包的图片或者图片所在的文件夹

3.设置在编辑器模式下也可以使用打包功能

设置在编辑器模式下也可以使用打包功能
这里就已经完成图集打包了。

一切似乎都很完美,图片显示,打包都有了。

但是!但是!但是

图集+Gloader显示图片后,图片显示不出来了,
查了很久才知道

// 获取精灵在其纹理上使用的矩形。如果这个精灵被紧紧地打包在一个地图集中,则引发一个异常。
textureRect	  Get the rectangle this sprite uses on its texture. Raises an exception if this sprite is tightly packed in an atlas.

我TM一万匹草泥马奔过,这TM也是我昨晚查了一晚上,Debug了好久查找怎么正确获取textureRect,或者说能正常显示图片。

我发现如果要显示图片可以使用GGraph:

// FairyGUI官方给予的案例
GGraph holder = new GGraph();
holder.SetSize(100, 100);
holder.DrawRect(...);
aComponent.AddChild(holder);
holder.SetNativeObject(aSprite);

但是这里装载的aSprite是一个GameObject对象,相当于我创建了一个GameObject挂载到了FairyGUI上。
这里我不可能1.将所有的GLoader改成GGraph吧,2.为每张需要用到的图片创建GameObject吧。
后来根据官方的案例发现可以,

Texture2D tTx2D = Resources.Load<Texture2D>(strPath);
this.onExternalLoadSuccess(new NTexture(tTx2D));

但是这里加载的Texture2D是整个图片,如果是图片中的某块区域(图集中的一张图片)则无法正常显示。

最后我发现,在创建Sprite Atlas时,取消勾选Tight Packing(取消紧凑打包),属性textureRect就可以正常获取了。
取消紧凑打包

  • 5
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
Unity 使用 proto,需要先安装 Google 的 protobuf 工具。然后在 Unity 项目导入相关的 proto 文件,使用 protoc 编译器生成对应的 C# 类代码。在 Unity ,可以通过这些 C# 类来序列化和反序列化 proto 数据。 具体的步骤如下: 1. 下载并安装 protobuf 工具,包括 protoc 编译器和 C# 支持库。 2. 在 Unity 创建一个 C# 类来表示你的 proto 数据结构。 3. 在 Unity 导入 proto 文件,使用 protoc 编译器生成对应的 C# 类代码。 4. 在 Unity 使用生成的 C# 类来序列化和反序列化 proto 数据。 以下是一个简单的示例代码,演示了如何在 Unity 使用 proto: ```csharp using System.Collections; using System.Collections.Generic; using UnityEngine; using Google.Protobuf; public class ProtoTest : MonoBehaviour { void Start() { // 创建一个 proto 数据结构 var msg = new MyMessage { Id = 1, Name = "ProtoTest", Values = { 1, 2, 3 } }; // 将 proto 数据序列化成二进制数据 var bytes = msg.ToByteArray(); // 将二进制数据反序列化成 proto 数据 var newMsg = MyMessage.Parser.ParseFrom(bytes); // 输出 proto 数据的内容 Debug.Log($"Id: {newMsg.Id}, Name: {newMsg.Name}, Values: {string.Join(", ", newMsg.Values)}"); } } // 定义一个 proto 数据结构 message MyMessage { int32 Id = 1; string Name = 2; repeated int32 Values = 3; } ``` 注意:在使用 proto 时,需要保证 Unity 和服务器端使用相同的 proto 文件和版本,否则可能会出现兼容性问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值