草庐IT

Unity Sprite 切割图集并且获得任一子图(sprite/Texture)

John Lio 2023-04-12 原文

首先,Unity中的Sprite Editor 可以将一张大图切割成多个sprite。然而如果想要从这么多切割好的子sprite获取某一个sprite 要如何操作呢?本篇文章总结了两个方法以获取图集中的某个子图。

一. 切割图集

  1. 这一步,使用Unity的SpriteEditor切割你的图集,如果不会使用SpriteEditor请参考这篇文章:Unity的2D图集处理,并切割出一张张小图片_0完美对称0的博客-CSDN博客_unity裁剪图片在我们找资源的时候,有时候会遇到那种把一堆图片放进一张png图片里面的情况,在做2D游戏的时候,我们往往需要将里面的一块块小图片切割出来使用,那么问题就来了,怎么切割呢,现在我们提供一张小图片,给大家演示一下:那么我们现在把图片导入到Unity中,选中图片你会看到左边的Inspector界面然后,选择Texture Type类型为Advanced,如下面左图:将Read/Wrihttp://blog.csdn.net/hongyouwei/article/details/45011315

二. 从切割好的图集中获取某一子图

1. 方法一:将切割好的sprite 转成 png 文件,并且存放在一个新建的文件夹中。然后使用一个List 记录这个文件夹中所有png文件的路径,需要返回哪一个图片,就通过AssetDatabase 来获取这一个图片。代码如下:

 //将分割好的sprite转换成Texture 并且返回一个texture文件 
    public static Texture2D GetChildTexture(Texture2D image, int num)
    {
        List<string> paths = new List<string>();//存放所有转化的png文件路径

        string rootPath = Path.GetDirectoryName(AssetDatabase.GetAssetPath(image));//获取路径名称  
        string path = rootPath + "/" + image.name + ".PNG";//图片路径名称  
        //Debug.Log(path);

        TextureImporter texImp = AssetImporter.GetAtPath(path) as TextureImporter;//获取图片入口  


        AssetDatabase.CreateFolder(rootPath, image.name);//创建文件夹

        foreach (SpriteMetaData metaData in texImp.spritesheet)//遍历小图集  
        {
            Texture2D myimage = new Texture2D((int)metaData.rect.width, (int)metaData.rect.height);


            //abc_0:(x:2.00, y:400.00, width:103.00, height:112.00)  
            for (int y = (int)metaData.rect.y; y < metaData.rect.y + metaData.rect.height; y++)//Y轴像素  
            {
                for (int x = (int)metaData.rect.x; x < metaData.rect.x + metaData.rect.width; x++)
                    myimage.SetPixel(x - (int)metaData.rect.x, y - (int)metaData.rect.y, image.GetPixel(x, y));
            }


            //转换纹理到EncodeToPNG兼容格式  
            if (myimage.format != TextureFormat.ARGB32 && myimage.format != TextureFormat.RGB24)
            {
                Texture2D newTexture = new Texture2D(myimage.width, myimage.height);
                newTexture.SetPixels(myimage.GetPixels(0), 0);
                myimage = newTexture;
            }

            var pngData = myimage.EncodeToPNG();
            string output_path = rootPath + "/" + image.name + "/" + metaData.name + ".PNG";//子图片输出路径
            File.WriteAllBytes(output_path, pngData); //输出子PNG图片

            paths.Add(output_path);

            // 刷新资源窗口界面  
            AssetDatabase.Refresh();
        }

        Texture2D output_image = AssetDatabase.LoadAssetAtPath<Texture2D>(paths[num]);
        Debug.Log(output_image.name);

        return output_image;
    }

2. 方法二: 直接获取切割好的sprite图集中的所有子sprite, 返回某一sprite。代码如下:

AssetDatabase.LoadAllAssetsAtPath(): 在编辑器模式下load 资源

Resources.LoadAll<T>() : 加载的资源必须放在Resources文件夹下

AssetBundle 动态加载资源的话,需要先给资源create AssetBundle, 然后再使用相关方法批量Load 资源。

//返回一个子sprite
    public static Sprite GetChildSprite(Texture2D image, int num)
    {

        string rootPath = Path.GetDirectoryName(AssetDatabase.GetAssetPath(image));//获取路径名称  
        string path = rootPath + "/" + image.name + ".PNG";//图片路径名称

        Object[] sprites = AssetDatabase.LoadAllAssetsAtPath(path);
        //Object[] sprites = Resources.LoadAll<Sprite>(path);


        Sprite output_sprite = (Sprite)sprites[num];

        Debug.Log(output_sprite.name);

        return output_sprite;
    }

三. 调用函数

可以扩展编辑器来调用GetChildTexture()的函数,因为这个方法涉及到在编辑器下转化sprite -> Texture。GetChildSprite() 方法会返回一个Sprite,具体情况具体分析。

[MenuItem("Assets/SpriteSlicer/SpriteSlice")]
    public static void SpliceSprite()
    {
        Texture2D input_image = Selection.activeObject as Texture2D;
        Texture2D output_image = GetChildTexture(input_image, 10);

        Sprite output_image2 = GetChildSprite(input_image,15);
    
    }

总结

本文探究了在Unity编辑器模式下如何切割图集,并且获得图集中的某一sprite。动态加载sprite需要使用AssetBundle加载,本文暂时并未实现,持续更新中。

* 使用了 using UnityEditor 的脚本只能发在Editor文件夹下。不然会有报错。

有关Unity Sprite 切割图集并且获得任一子图(sprite/Texture)的更多相关文章

  1. ruby - 无法在 60 秒内获得稳定的 Firefox 连接 (127.0.0.1 :7055) - 2

    我使用的是Firefox版本36.0.1和Selenium-Webdrivergem版本2.45.0。我能够创建Firefox实例,但无法使用脚本继续进行进一步的操作无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055)错误。有人能帮帮我吗? 最佳答案 我遇到了同样的问题。降级到firefoxv33后一切正常。您可以找到旧版本here 关于ruby-无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055),我们在StackOverflow上找到一个类

  2. ruby - 当你有一个没有参数的 case 语句并且 when 子句是 lambda 时会发生什么? - 2

    这段代码没有像我预期的那样执行:casewhen->{false}then"why?"else"ThisiswhatIexpect"end#=>"why?"这也不是casewhen->(x){false}then"why?"else"ThisiswhatIexpect"end#=>"why?"第一个then子句在两种情况下都被执行,这意味着我提供给when子句的lambda没有被调用。我知道无论when子句的主题是什么,都应该调用大小写相等运算符===。我想知道当没有为case提供参数时,===的另一边会发生什么。我在想它可能是nil,但它不可能是:->{false}===nil#=>

  3. ruby - 我可以从 Ruby 中的系统调用中获得连续输出吗? - 2

    当您在Ruby脚本中使用系统调用时,您可以像这样获得该命令的输出:output=`ls`putsoutput这就是thisquestion是关于。但是有没有办法显示系统调用的连续输出?例如,如果您运行此安全复制命令,以通过SSH从服务器获取文件:scpuser@someserver:remoteFile/some/local/folder/...它显示随着下载进度的连续输出。但是这个:output=`scpuser@someserver:remoteFile/some/local/folder/`putsoutput...不捕获该输出。如何从我的Ruby脚本中显示正在进行的下载进度?

  4. ruby-on-rails - Rspec 测试属于并且有很多 - 2

    我正在运行rspec测试以确保两个模型通过has_many和belongs_to相互关联。下面是我的测试。describe"testingforhasmanylinks"dobeforedo@post=Post.new(day:"Day1",content:"Test")@link=Link.new(post_id:@post.id,title:"google",url:"google.com")endit"inthepostmodel"do@post.links.first.url.should=="google.com"endend测试告诉我url是一个未定义的方法。我的测试有什么

  5. ruby - 如何获得随机的 0 和 1 数字 - 2

    所以基本上是为了好玩,我试图生成一列数字(7位数字只有0和1)我的代码很短:a=rand(0000000-1111111)b=220a1=rand(0000000-1111111)a2=rand(0000000-1111111)a3=rand(0000000-1111111)a4=rand(0000000-1111111)a5=rand(0000000-1111111)whileb!=0putsaputsa2putsa3putsa4putsa5end我的问题是,不是生成随机的0和1列,而是所有,而是使用了数字。 最佳答案 这是惯用的

  6. ruby-on-rails - Rails 和 Rake 命令挂起并且什么都不做 - 2

    我不知道为什么,但是当我在我的Rails项目中运行rake命令时,没有任何反应。railsserver什么也不做。有什么建议吗? 最佳答案 你可以在开头添加一个“ruby-rtracer”以查看它卡在哪里。 关于ruby-on-rails-Rails和Rake命令挂起并且什么都不做,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/3657296/

  7. ruby - 如何获得带有 SSL 客户端证书的 HTTPS 请求以与 Ruby EventMachine 一起使用? - 2

    我正在尝试使用RubyEventMachine访问使用SSL证书身份验证的HTTPSWeb服务,但我没有让它工作。我编写了以下简单代码块来对其进行端到端测试:require'rubygems'require'em-http'EventMachine.rundourl='https://foobar.com/'ssl_opts={:private_key_file=>'/tmp/private.key',:cert_chain_file=>'/tmp/ca.pem',:verify_peer=>false}http=EventMachine::HttpRequest.new(url).g

  8. ruby-on-rails - 是否有一个库可以自动进行 CSS spriting? - 2

    CSSSpriting确实可以提高性能,但它并不是最容易阅读和维护的东西。是否有任何工具可以让我单独对图像进行编码,然后将它们聚合起来并用正确的蒙太奇子集替换HTML?我特别考虑RubyonRails插件,但如果有其他语言的包,我很乐意移植它。 最佳答案 SmartSprites试一试。 关于ruby-on-rails-是否有一个库可以自动进行CSSspriting?,我们在StackOverflow上找到一个类似的问题: https://stackoverf

  9. ruby-on-rails - 如果我有一个来自收费的 Stripe token ,我如何获得它的收费 ID? - 2

    现在我正在使用我的Rails应用程序成功收费,但我想获取有关交易的某些详细信息,例如商品购买的描述和信用卡的最后四位数字,以显示给用户他们的收据页面。我一直在查看文档,但实际上没有任何内容可以解释如何为应用提供token并取回charge_id,然后我可以使用它来获取有关费用的其他信息的哈希值。任何帮助都是巨大的。谢谢! 最佳答案 Stripe在对费用创建调用的响应中返回费用ID。如果您使用的是Ruby库,则可以执行以下操作来获取ID:require"stripe"Stripe.api_key=''charge=Stripe::Ch

  10. ruby - 如何在 Ruby 的 OptionParser 中只获得长选项? - 2

    我在Ruby(test.rb)中有这么简单的代码:#!/usr/bin/envrubyrequire'optparse'OptionParser.newdo|option|option.on("--sort","Sortdata")doputs"--sortpassed"endend.parse!然后我运行它:./test.rb-s并得到:--sortpassed我错过了什么吗?我希望唯一的--sort(长)选项有效,而不是短选项。如何获取? 最佳答案 我在optparse.rb的第1378-1380行中找到了导致此行为的代码:#i

随机推荐