You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity打包后从本地指定目录加载并转换纹理为Texture的方法

Unity加载本地图片并转换为Texture2D赋值给场景对象

没问题,我来帮你搞定这个!既然你已经通过对话框选中文件并复制到Application.persistentDataPath了,接下来只需要把本地文件转换成Texture2D,再赋值给平面的材质就行。下面是具体的实现方案,包含同步/异步两种方式,还有实际开发中的注意事项:

核心步骤:读取文件并转换为Texture2D

Unity的Texture2D.LoadImage()方法非常实用,它可以直接读取jpg、png等格式的字节流并自动生成纹理,不需要手动指定图片格式,省了很多麻烦。

1. 同步加载(适合小图片)

如果你的图片尺寸不大,同步加载足够用,代码简单直接:

using UnityEngine;
using System.IO;

public class TextureLoader : MonoBehaviour
{
    public GameObject targetPlane; // 拖拽场景中的平面对象到Inspector面板

    public void LoadTexture(string localFilePath)
    {
        if (!File.Exists(localFilePath))
        {
            Debug.LogError("文件不存在,请检查路径是否正确!");
            return;
        }

        // 读取本地文件的字节数据
        byte[] imageBytes = File.ReadAllBytes(localFilePath);
        // 创建临时Texture2D,初始尺寸随便填,LoadImage会自动调整为图片实际尺寸
        Texture2D texture = new Texture2D(2, 2);
        
        // 将字节数据加载为纹理
        if (texture.LoadImage(imageBytes))
        {
            // 优化纹理显示效果(可选)
            texture.filterMode = FilterMode.Bilinear; // 开启平滑过滤
            texture.wrapMode = TextureWrapMode.Clamp; // 边缘不重复拉伸

            // 给平面的材质赋值纹理
            Renderer planeRenderer = targetPlane.GetComponent<Renderer>();
            if (planeRenderer != null)
            {
                planeRenderer.material.mainTexture = texture;
            }
            else
            {
                Debug.LogError("目标平面缺少Renderer组件,请添加后重试!");
                Destroy(texture); // 销毁无用纹理避免内存浪费
            }
        }
        else
        {
            Debug.LogError("图片格式不支持,请确认是jpg/png等常见图像格式!");
            Destroy(texture);
        }
    }
}

2. 异步加载(推荐大图片)

如果图片尺寸较大,同步加载会导致主线程卡顿,建议用异步方式读取:

using UnityEngine;
using System.IO;
using System.Threading.Tasks;

public class AsyncTextureLoader : MonoBehaviour
{
    public GameObject targetPlane;
    private bool isTextureLoaded = false;
    private Texture2D loadedTexture;

    public async void LoadTextureAsync(string localFilePath)
    {
        if (!File.Exists(localFilePath))
        {
            Debug.LogError("文件不存在,请检查路径是否正确!");
            return;
        }

        try
        {
            // 异步读取文件字节,不阻塞主线程
            byte[] imageBytes = await File.ReadAllBytesAsync(localFilePath);
            
            // 纹理创建操作必须在主线程执行,这里先在后台加载字节,再回到主线程处理
            await Task.Run(() => 
            {
                loadedTexture = new Texture2D(2, 2);
                if (loadedTexture.LoadImage(imageBytes))
                {
                    loadedTexture.filterMode = FilterMode.Bilinear;
                    loadedTexture.wrapMode = TextureWrapMode.Clamp;
                    isTextureLoaded = true;
                }
                else
                {
                    Debug.LogError("图片加载失败,请检查文件完整性!");
                    Destroy(loadedTexture);
                }
            });
        }
        catch (System.Exception e)
        {
            Debug.LogError($"加载纹理时出错:{e.Message}");
        }
    }

    // 在Update中处理主线程的材质赋值
    private void Update()
    {
        if (isTextureLoaded && loadedTexture != null)
        {
            Renderer planeRenderer = targetPlane.GetComponent<Renderer>();
            if (planeRenderer != null)
            {
                planeRenderer.material.mainTexture = loadedTexture;
            }
            else
            {
                Debug.LogError("目标平面缺少Renderer组件!");
                Destroy(loadedTexture);
            }
            isTextureLoaded = false;
        }
    }
}

关键注意事项

  • 权限问题:在移动端(Android/iOS),需要申请读取外部存储的权限。Android 13+需要READ_MEDIA_IMAGES权限,iOS需要开启Photo Library访问权限。
  • 内存管理:当不再需要该纹理时,一定要调用Destroy(texture)释放内存,避免内存泄漏。如果是频繁切换纹理,建议用对象池复用Texture2D。
  • 纹理格式优化:如果需要更好的性能,可以在加载后转换纹理格式,比如texture.ConvertToTextureFormat(TextureFormat.RGBA32),根据目标平台选择合适的格式(比如移动端用ETC2格式)。
  • 材质赋值细节:如果用的是URP/HDRP管线,材质的主纹理属性可能叫_BaseMap而不是mainTexture,可以用planeRenderer.material.SetTexture("_BaseMap", texture)来赋值。

调用示例

假设你已经把选中的图片复制到了Application.persistentDataPath下的selected_image.jpg,调用方式如下:

string texturePath = Path.Combine(Application.persistentDataPath, "selected_image.jpg");
// 同步加载
GetComponent<TextureLoader>().LoadTexture(texturePath);
// 或者异步加载
GetComponent<AsyncTextureLoader>().LoadTextureAsync(texturePath);

内容的提问来源于stack exchange,提问作者wkwoczak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 09:55:40