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

扫一扫,访问微社区

开发者专栏

关注:1810

当前位置:游戏蛮牛 技术专区 开发者专栏

__________________________________________________________________________________
开发者干货区版块规则:

  1、文章必须是图文形式。(至少2幅图)
      2、文章字数必须保持在1500字节以上。(编辑器右下角有字数检查)
      3、本版块只支持在游戏蛮牛原创首发,不支持转载。
      4、本版块回复不得无意义,如:顶、呵呵、不错......【真的会扣分的哦】
      5、......
__________________________________________________________________________________
查看: 783|回复: 4

[伊利丹·怒风] Unity3D 批量纹理修改总结(下)--土八路法

[复制链接]  [移动端链接]
排名
1622
昨日变化
7

52

主题

295

帖子

2023

积分

Rank: 9Rank: 9Rank: 9

UID
35466
好友
18
蛮牛币
3208
威望
0
注册时间
2014-7-21
在线时间
664 小时
最后登录
2017-8-17

专栏作家

发表于 2017-7-31 08:56:05 | 显示全部楼层 |阅读模式

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

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

x
本帖最后由 wind2006 于 2017-7-31 08:56 编辑

背景

通过AssetBunlderBuilder打包学习寻找资料时候的意外的收获,之所以叫做“土八路法”,因为路子很野,可以说简单,粗暴和直接了当解决问题。符合我们绝大多数男人的口味,当然也在我们苦苦学习 打包众多Assets原生API的同时,犹如一股清流,让人耳目一新。

好了不卖关子了,这个方法其实是一位前辈(由于时间久远忘记记录网址了这里就不发了)发现的,我只是剽窃来应用在“批量纹理修改”上,原理是这样:“我发现一个很有意思的现象,就是图片的Editor属性是和meta文件实时保持一致的”。这样我们通过修改Meata文件就可以对应修改sprite或者texture纹理的属性了,这样当我们有大量的资源需要修改和设置的时候就可以自己写一个工具进行批量修改了。当然更进一步修改meta文件,也可以不使用编辑器功能。我们直接写一个winform程序,甚至不需要启动Unity3d就可以实现对于资源的批量修改。Meta文件和Asset 纹理的属性对应关系图,看图更清楚。实际上不怎么需要了解系统Asset API 就可以对映到相关Meta配置项目。

2.png

3.png

实现

光说不干没有说服力,下面列出实现相关的功能代码:

1、Editor菜单扩展函数入口及文件遍历函数

[C#] 纯文本查看 复制代码
// 设置文件夹内所有文件assetbundle的名字(修改meta文件)  
[MenuItem(\"Tools/SetImageAssetMetaByDictionary\")]
static void OnSetImageAssetMetaByDictionary()
{
    string path = AssetDatabase.GetAssetPath(Selection.activeObject);

    string dataPath = Application.dataPath;
    int assetIndex = dataPath.IndexOf(\"Assets\", StringComparison.Ordinal);
    dataPath = dataPath.Substring(0, assetIndex);

    string directoryPath = string.Empty;

    var fullPath = Path.Combine(dataPath, path); // Application.dataPath + \"/\" + versionDir;//+ \"/\";
    //如果选中的是文件夹中的文件,则选择此文件的文件夹
    if (fullPath.IndexOf(\".\") > 0)
    {
        FileInfo fi = new FileInfo(fullPath);
        directoryPath = fi.DirectoryName;
    }
    else
    {
        directoryPath = fullPath;
    }
    string dirAssetBundleName = \"\";
    List<string> assetNames = new List<string>();
    if (Directory.Exists(directoryPath))
    {
        assetIndex = 0;
        var dir = new DirectoryInfo(directoryPath);
        var files = dir.GetFiles(\"*\", SearchOption.AllDirectories);

        Dictionary<string, string> alterDictionary = new Dictionary<string, string>();
        alterDictionary.Add(\"assetBundleName\", \"Armor17\");
        alterDictionary.Add(\"spritePackingTag\", \"Armor17\");
        alterDictionary.Add(\"spritePixelsToUnits\", \"1\");

        alterDictionary.Add(\"alignment\", \"1\");
        alterDictionary.Add(\"spritePivot\", \" {x: 0, y: 1}\");
    
        for (var i = 0; i < files.Length; ++i)
        {
            var fileInfo = files[i];
            EditorUtility.DisplayProgressBar(\"设置Image Meta\", \"正在设置Image Meta中...\", 1f * i / files.Length);
            if (fileInfo.Name.EndsWith(\".png.meta\") || fileInfo.Name.EndsWith(\".jpg.meta\") || fileInfo.Name.EndsWith(\".tga.meta\"))
            {
                DoSetAssetBundleName(fileInfo.FullName, alterDictionary);
            }
        }
        EditorUtility.ClearProgressBar();
    }

  
    //刷新编辑器  
    AssetDatabase.Refresh();
    Debug.Log(\"AssetBundle打包完毕\");
}

  

这个函数主要的功能是三个,通过[MenuItem("Tools/SetImageAssetMetaByDictionary")]特性进行编辑器工具栏菜单的扩展和定义入口;通过Unity3d 原生路径API结合C# 文件系统IO操作遍历所有我们所需要的批量修改纹理图片文件(纹理文件以文件夹为单位,这部分的主要内容在上篇已经详细说明了,这篇不再赘述),通过Dictionary Key-value的形式定义我们需要修改的纹理属性。

2、Meta文件修改函数

[C#] 纯文本查看 复制代码
static void DoSetAssetBundleName(string path, Dictionary<string, string> alterDictionary)
{
    path = path.Replace(\"\\\", \"/\");


    StreamReader fs = new StreamReader(path);
    List<string> ret = new List<string>();
    string line;
    while ((line = fs.ReadLine()) != null)
    {
        line = line.Replace(\"\n\", \"\");

        foreach (var x in alterDictionary)
        {
            if (line.IndexOf(x.Key) != -1)
            {
                line = string.Format(\"  {0}: {1}\", x.Key, x.Value);

            }
        }

        ret.Add(line);
    }
    fs.Close();

    File.Delete(path);

    StreamWriter writer = new StreamWriter(path + \".tmp\");
    foreach (var each in ret)
    {
        writer.WriteLine(each);
    }
    writer.Close();

    File.Copy(path + \".tmp\", path);
    File.Delete(path + \".tmp\");
}

  

 

这个函数不难,就两个功能:一个就是逐行读取Meta文件内容,发现我们需要修改的属性时候就行就进行替换修改;二是需要注意的这里修改Meta文件需求先删除再创建,无法直接修改(可能是编译器打开着的原因,这个也是前辈文章中提示的我没有验证,不管用何种方式能修改Meta文件即可);

至此,土八路法也介绍完了,是不是充满着奇技淫巧,开个玩笑。

总结

下面我们来总结下3种方法的优略

正规军法1:通过Unity3d Editor 扩展导入Asset API实现纹理导入时的定制批量修改;

正规军发2:通过Unity3d Editor 循环遍历需要修改的Asset进行批量修改;

土八路法3:通过修改纹理图片Meta文件;

正规军法1:导入回调法,主要优点是简单统一,所有导入的纹理自动修改,批量修改文件于无形之间,自动化程度很高。缺点是自动化程度太高造成不可控,比如如果一个游戏中既有纹理又有3d纹理,还需要区别对待修改代码。实际在我看来这种Unity3d提供的API有些鸡肋,华而不实;

正规军发2:菜单扩展,自定义选择纹理使用原生API进行自定义批量修改。这种方法成为正规军法才是名至实。可以完全自定义选择和修改纹理的属性,扩展性也很强,但前提是你对Unity3d原生的Asset相关API要比较熟悉;

土八路法3:应该是最非常飘逸的一种方法和思路,灵活到在不了解Asset相关API,不打开Unity3d的情况就可以完成批量纹理资源的修改,特别是在混沌中学习Unity3d 系统Asset API时,给我们打开了另一扇门。但是“重剑无锋,大巧不工。”的道理大家应该都懂,抗日主要还是要靠国军。
最后,说下一基础知识的积累还是很重要的,希望本文对大家有用。


回复

使用道具 举报

5熟悉之中
872/1000
排名
9626
昨日变化
141

4

主题

690

帖子

872

积分

Rank: 5Rank: 5

UID
209186
好友
0
蛮牛币
1456
威望
0
注册时间
2017-3-1
在线时间
100 小时
最后登录
2017-8-17
发表于 2017-7-31 10:11:02 | 显示全部楼层
先实现,再考虑优化改进

回复 支持 反对

使用道具 举报

3偶尔光临
233/300
排名
6798
昨日变化
63

1

主题

40

帖子

233

积分

Rank: 3Rank: 3Rank: 3

UID
56245
好友
0
蛮牛币
653
威望
0
注册时间
2014-11-18
在线时间
58 小时
最后登录
2017-8-16
发表于 2017-7-31 10:24:28 | 显示全部楼层
这是强大!

回复

使用道具 举报

4四处流浪
378/500
排名
12900
昨日变化
275

1

主题

282

帖子

378

积分

Rank: 4

UID
234498
好友
0
蛮牛币
1435
威望
0
注册时间
2017-7-27
在线时间
51 小时
最后登录
2017-8-17
发表于 2017-8-3 08:57:00 来自Mobile--- | 显示全部楼层
感谢分享

回复

使用道具 举报

4四处流浪
365/500
排名
9499
昨日变化
5

0

主题

209

帖子

365

积分

Rank: 4

UID
146677
好友
7
蛮牛币
1746
威望
0
注册时间
2016-4-25
在线时间
78 小时
最后登录
2017-8-16
QQ
发表于 2017-8-7 22:09:44 | 显示全部楼层
直接快捷方便

回复

使用道具 举报

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

本版积分规则

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