当前位置:   article > 正文

05_Unity动态加载图片资源

unity动态加载图片

零、前言

本文归纳了Unity中加载图片资源的常用方法,包括url和本地路径的加载。

一、www加载

在工具类中封装如下方法:

一般是放在单例中,如:GameManager

public void LoadTexture(Image obj, string path)
{
    // Application.dataPath + "/Resources/Image/Guide1.png"
    string finalPath = Application.dataPath + "/Resources/" + path;
    print("final " + finalPath);
    StartCoroutine(ILoadTexture(obj, finalPath));
}

public void LoadTextureUrl(Image obj, string url)
{
    StartCoroutine(ILoadTexture(obj, url));
}

IEnumerator ILoadTexture(Image obj, string url)
{
    double startTime = (double)Time.time;
    //请求WWW
    WWW www = new WWW(url);

    yield return www;
    if (www != null && string.IsNullOrEmpty(www.error))
    {
        //获取Texture
        Texture2D texture = www.texture;
            //创建Sprite
        Sprite sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f));
        startTime = (double)Time.time - startTime;
        Debug.Log("www加载用时 : " + startTime);
        obj.sprite = sprite;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

加载本地图片:

  1. 创建一个Image物体

创建UI.Image物体

  1. 在本地存放一张图片,Guide1.png

放置在: Resources/Image/Guide1.png 路径下

放置的位置

  1. 在物体上挂接一个测试脚本
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.UI;
 
public class Test : MonoBehaviour {
    void Start () {
        Image img = GetComponent<Image>();
        // 此处调用,上面的LoadTexture方法
        GameManager.instance.LoadTexture(img, "Image/Guide1.png");
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  1. 执行前:

执行前

  1. 执行后:

执行后

加载url

  1. 还是刚刚的Image
  2. 脚本变成:
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.UI;
 
public class Test : MonoBehaviour {
    void Start () {
        Image img = GetComponent<Image>();
        // 此处调用,上面的LoadTexture方法
        GameManager.instance.LoadTextureUrl(img, "https://docs.unity3d.com/uploads/Main/ShadowIntro.png");
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  1. 表现效果和上面的一致
  2. 缺点是速度比较慢,运行时间大约0.4s

二、UnityWebReqeust

现在官方建议是采用UnityWebReqeust

参考代码如下

public IEnumerator LoadTexture2D(string path)
{
    UnityWebRequest request = UnityWebRequestTexture.GetTexture(path);
    yield return request.SendWebRequest();

    if (request.isHttpError || request.isNetworkError)
    {  }
    else
    {
        // 这个是物体身上的组件Image
        Image img = GetComponent<Image>();

        var texture = DownloadHandlerTexture.GetContent(request);
        Sprite sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f));
        img.sprite = sprite;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

本地加载

StartCoroutine(LoadTexture2D(Application.dataPath + "/Resources/Image/Guide1.png"));
  • 1

url加载

StartCoroutine(LoadTexture2D("https://docs.unity3d.com/uploads/Main/ShadowIntro.png"));
  • 1

三、以IO的形式加载

private void LoadByIo(string path)
{
    // 目标
    Image img = GetComponent<Image>();

    double startTime = (double)Time.time;
    //创建文件读取流
    FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read);
    //创建文件长度缓冲区
    byte[] bytes = new byte[fileStream.Length];
    //读取文件
    fileStream.Read(bytes, 0, (int)fileStream.Length);

    //释放文件读取流
    fileStream.Close();
    //释放本机屏幕资源
    fileStream.Dispose();
    fileStream = null;

    //创建Texture
    int width = 300;
    int height = 372;
    Texture2D texture = new Texture2D(width, height);
    texture.LoadImage(bytes);

    //创建Sprite
    Sprite sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f));
    image.sprite = sprite;

    startTime = (double)Time.time - startTime;
    Debug.Log("IO加载" + startTime);

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

四、优化方案

前两种方案均使用到了协程,最后一种方案用到了IO。

优劣分析:

  • 协程的接口封装更完善,使用更简洁。缺点是协程无法将texture作为返回值return回去。
  • IO加载需要自己写读写代码,偏底层一些。优点是可以return,return后交给使用的人自行处理,更加灵活。

下面提出一种协程的优化方案:

首先,为什么需要优化?
原因是使用封装的接口,不应该把Image传递进去,也不应该将Image和texture强绑定起来。而是获得目标texture,如何处置则交给使用的人。
因此解决方案是传递一个回调函数,在texture加载完成后执行回调。

参考代码如下:

public RawImage imageBox;
void Start()
{
    StartCoroutine(LoadTexture2D("/icon.png", (value) => imageBox.texture = value));
}

public IEnumerator LoadTexture2D(string url, Action<Texture2D> taskCompletedCallBack)
{
    UnityWebRequest request = UnityWebRequestTexture.GetTexture(Application.persistentDataPath + url);
    yield return request.SendWebRequest();

    if (request.isHttpError || request.isNetworkError)
    { }
    else
    {
        var texture = DownloadHandlerTexture.GetContent(request);
        taskCompletedCallBack(texture);
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

五、其他

仅本地加载的办法,类似加载其他资源

1、Resources文件夹下加载

  inside = Resources.Load("inside") as Texture;//Resources夹下动态加载
  • 1

2、Assets文件夹下加载

AssetsManager.Load("Assets/_Sprites/Setting/" + index + ".png", (sprite) =>

        {

            img.sprite = sprite;

        });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

六、结语

你学废了吗?


关注我,一起进步吧~

点个赞叭~

参考文档:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/103539
推荐阅读
相关标签
  

闽ICP备14008679号