码迷,mamicode.com
首页 > 编程语言 > 详细

Unity3d游戏安装包 极限减少之 四分图、二分图 (NGUI向)

时间:2015-04-15 00:59:27      阅读:321      评论:0      收藏:0      [点我收藏+]

标签:unity3d   ngui   编辑器   

在这个酒香也怕巷子深,游戏不打广告不买用户不刷榜就会死的时代。每个游戏代理都想让CP提供的安装包越小越好,能99M绝对不要100M。但是游戏开发商们在一遍一遍踢出无用的资源,一点一点得把游戏包扣小,发现大小还是减不下来,该怎么办,这时只有拿美术资源开刀了。

我们来看下面两张图片,是从暗黑战神中抠出来的。 转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn

(PS:从解包安装包分析,暗黑战神已经用了此文所说的二分优化方法)

技术分享

转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn

技术分享

(PS:此图本只有一半,是我自己拼上了另外一半)

仔细看便会发现:               转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn

第一张图其实只要左上角 四分之一 就可以了,其它三部分可以复制然后反转就可以得到。

第二张图其实只要左边一半就可以了,右边同样可以复制然后Y轴旋转得到。

 转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn

那我们这样做,能节约很多资源吗?

第一张图大小为: 133KB  ,四分之一大小的图为:32KB。

第二张图大小为:216KB,一半大小为:56KB(坑爹呢,保存的时候分辨率不一样)

 

还不错哟!

我们在使用NGUI时,对于UISprite ,可以有多种填充方式,Simple、Tiled、Slice等,Tiled是让一张图片重复的显示去充满设置的屏幕大小。

这和我们的目的很接近,于是我们试一下Tiled。


技术分享


好像不太符合我们的要求呀。

好,那我们就动手修改NGUI 的UISprite 脚本吧。

打开UISprite.cs 首先我们来最常用的看Simple ,是如何把图片显示在屏幕上的。然后我们自己仿照Simple的流程来添加自己的图片显示方式。


首先我们在UISprite中搜索Simple、找到有一个枚举Type。

	public enum Type
	{
		Simple,
		Sliced,
		Tiled,
		Filled,
		Advanced,
                Quarter,
                Half,
	}


应该是在这里定义了Type.Simple,所以我们在UISprite上面才可以选择Simple。尝试添加Quarter(四分图)、Half(二分图)。然后返回Unity查看,添加成功如下图。


技术分享


然后顺着 Sample搜索到一个Switch Case ,是Type选择的处理函数,我们添加上Quarter、Half的处理函数。

protected void Fill (BetterList<Vector3> verts, BetterList<Vector2> uvs, BetterList<Color32> cols, Rect outer, Rect inner)
	{
		mOuterUV = outer;
		mInnerUV = inner;

		switch (type)
		{
			case Type.Simple:
			SimpleFill(verts, uvs, cols);
			break;

			case Type.Sliced:
			SlicedFill(verts, uvs, cols);
			break;

			case Type.Filled:
			FilledFill(verts, uvs, cols);
			break;

			case Type.Tiled:
			TiledFill(verts, uvs, cols);
			break;

			case Type.Advanced:
			AdvancedFill(verts, uvs, cols);
			break;

                        case Type.Quarter:
                        QuarterFill(verts, uvs, cols);
                        break;

                        case Type.Half:
                        HalfFill(verts, uvs, cols);
                        break;
		}
	}


然后我们来看Sample这一种图片显示方式的处理代码。

/// <summary>
	/// Regular sprite fill function is quite simple.
	/// </summary>

	void SimpleFill (BetterList<Vector3> verts, BetterList<Vector2> uvs, BetterList<Color32> cols)
	{
		Vector4 v = drawingDimensions;  //范围,即编辑器中UISprite的方框 Rect。
		Vector4 u = drawingUVs; //UV,即选中图片在图集中的位置。
		Color32 c = drawingColor; //在编辑器中设置的颜色 ColorTint。

		verts.Add(new Vector3(v.x, v.y));
		verts.Add(new Vector3(v.x, v.w));
		verts.Add(new Vector3(v.z, v.w));
		verts.Add(new Vector3(v.z, v.y));

		uvs.Add(new Vector2(u.x, u.y));
		uvs.Add(new Vector2(u.x, u.w));
		uvs.Add(new Vector2(u.z, u.w));
		uvs.Add(new Vector2(u.z, u.y));

		cols.Add(c);
		cols.Add(c);
		cols.Add(c);
		cols.Add(c);
	}

这一段代码做了什么呢?

首先添加了四个顶点,然后把纹理通过UV映射到这四个顶点形成的面上,就像给一张桌子铺上桌布一样。

我们来看下面两个坐标。

转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn

技术分享


顶点坐标以实际坐标为数值,纹理坐标以(0,1)为数值。

顶点坐标图中的方框,就是我们给UISprite设置的显示范围,纹理坐标中的方框,就是我们的纹理坐标。

Sample 这一种方式做的是:

把纹理坐标的1、2、3、4和顶点坐标的1、2、3、4对应起来,即把图片平铺到指定的范围。

 

那么现在来看我们的四分图。

取图一的左上角四分之一,对应到纹理坐标中。然后我们就把这四分之一的图,平铺到左边顶点坐标的左上角,然后平铺到右上角,右下角、左下角。

我们需要做什么?转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn

我们需要做的是,计算左上角那一块区域的坐标。

首先原来的顶点1要向上移动一半,然后顶点3要向左移动一半,然后顶点4要移动到原点。

具体的过程就到代码中实现吧。

    /// <summary>
    /// 四分图手法;
    /// </summary>
    /// <param name="verts"></param>
    /// <param name="uvs"></param>
    /// <param name="cols"></param>
    protected void QuarterFill(BetterList<Vector3> verts, BetterList<Vector2> uvs, BetterList<Color32> cols)
    {
        Vector4 v = drawingDimensions;
        Vector4 u = drawingUVs;
        Color32 c = drawingColor;

        Debug.LogError("QuarterFill drawingDimensions=" + drawingDimensions);
        Debug.LogError("QuarterFill drawingUVs=" + drawingUVs);

        //计算宽高;
        float width = v.z - v.x;
        float height = v.w - v.y;
        Debug.Log("QuarterFill width=" + width + " height=" + height);

        //左上角顶点;
        verts.Add(new Vector3(v.x, v.y+height/2));
        verts.Add(new Vector3(v.x, v.w));
        verts.Add(new Vector3(v.z - width / 2, v.w));
        verts.Add(new Vector3(v.z - width / 2, v.y+height/2));


        uvs.Add(new Vector2(u.x, u.y));
        uvs.Add(new Vector2(u.x, u.w));
        uvs.Add(new Vector2(u.z, u.w));
        uvs.Add(new Vector2(u.z, u.y));

        cols.Add(c);
        cols.Add(c);
        cols.Add(c);
        cols.Add(c);

        //左下角顶点;
        verts.Add(new Vector3(v.x, v.y));
        verts.Add(new Vector3(v.x, v.w - height / 2));
        verts.Add(new Vector3(v.z - width / 2, v.w - height / 2));
        verts.Add(new Vector3(v.z - width / 2, v.y));

        //绕X轴反转坐标 1和2交换 3和4交换;
        uvs.Add(new Vector2(u.x, u.w));
        uvs.Add(new Vector2(u.x, u.y));
        uvs.Add(new Vector2(u.z, u.y));
        uvs.Add(new Vector2(u.z, u.w));

        cols.Add(c);
        cols.Add(c);
        cols.Add(c);
        cols.Add(c);

        //右下角顶点;
        verts.Add(new Vector3(v.x+width/2, v.y));
        verts.Add(new Vector3(v.x+width/2, v.w-height/2));
        verts.Add(new Vector3(v.z, v.w-height/2));
        verts.Add(new Vector3(v.z, v.y));

        //将左下角UV绕Y轴旋转   1和4交换 2和3交换;
        uvs.Add(new Vector2(u.z, u.w));
        uvs.Add(new Vector2(u.z, u.y));
        uvs.Add(new Vector2(u.x, u.y));
        uvs.Add(new Vector2(u.x, u.w));

        cols.Add(c);
        cols.Add(c);
        cols.Add(c);
        cols.Add(c);

        //右上角顶点;
        verts.Add(new Vector3(v.x+width/2, v.y + height / 2));
        verts.Add(new Vector3(v.x+width/2, v.w));
        verts.Add(new Vector3(v.z, v.w));
        verts.Add(new Vector3(v.z, v.y + height / 2));

        //将左上角按Y轴旋转,1和4交换 2和3交换;
        uvs.Add(new Vector2(u.z, u.y));
        uvs.Add(new Vector2(u.z, u.w));
        uvs.Add(new Vector2(u.x, u.w));
        uvs.Add(new Vector2(u.x, u.y));

        cols.Add(c);
        cols.Add(c);
        cols.Add(c);
        cols.Add(c);

    }

    /// <summary>
    /// 二分图手法;
    /// </summary>
    /// <param name="verts"></param>
    /// <param name="uvs"></param>
    /// <param name="cols"></param>
    protected void HalfFill(BetterList<Vector3> verts, BetterList<Vector2> uvs, BetterList<Color32> cols)
    {
        Vector4 v = drawingDimensions;
        Vector4 u = drawingUVs;
        Color32 c = drawingColor;

        Debug.LogError("HalfFill drawingDimensions=" + drawingDimensions);
        Debug.LogError("HalfFill drawingUVs=" + drawingUVs);

        //计算宽高;
        float width = v.z - v.x;
        float height = v.w - v.y;
        Debug.Log("HalfFill width=" + width + " height=" + height);

        //左边顶点;
        verts.Add(new Vector3(v.x, v.y));
        verts.Add(new Vector3(v.x, v.w));
        verts.Add(new Vector3(v.z - width / 2, v.w));
        verts.Add(new Vector3(v.z - width / 2, v.y));


        uvs.Add(new Vector2(u.x, u.y));
        uvs.Add(new Vector2(u.x, u.w));
        uvs.Add(new Vector2(u.z, u.w));
        uvs.Add(new Vector2(u.z, u.y));

        cols.Add(c);
        cols.Add(c);
        cols.Add(c);
        cols.Add(c);

        //右边顶点;
        verts.Add(new Vector3(v.x + width / 2, v.y));
        verts.Add(new Vector3(v.x + width / 2, v.w));
        verts.Add(new Vector3(v.z, v.w));
        verts.Add(new Vector3(v.z, v.y));

        //将左边按Y轴旋转,1和4交换 2和3交换;
        uvs.Add(new Vector2(u.z, u.y));
        uvs.Add(new Vector2(u.z, u.w));
        uvs.Add(new Vector2(u.x, u.w));
        uvs.Add(new Vector2(u.x, u.y));

        cols.Add(c);
        cols.Add(c);
        cols.Add(c);
        cols.Add(c);

    }
    

最后来看看效果  转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn

技术分享


工程下载:

http://pan.baidu.com/s/1i3IN3CT



Unity3d游戏安装包 极限减少之 四分图、二分图 (NGUI向)

标签:unity3d   ngui   编辑器   

原文地址:http://blog.csdn.net/huutu/article/details/45050065

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!