zoukankan      html  css  js  c++  java
  • Unity3d 截屏保存到相册,并且刷新相册

      要做一个截图的功能,并且玩家可以在相册中看到。

      做的时候遇到了三个问题:

      1、unity自带的截图API,Application.CaptureScreenshot在Android上不生效

      2、图片保存的路径获取

      3、保存的图片可以在手机的文件管理中找到,但是相册中没有。

      解决方案:

      1、这个问题查了半天没有说原因,大多数人都给出了新方案用 File.WriteAllBytes去实现,代码如下:

    IEnumerator CutImage(string name)
        {
            //图片大小  
            Texture2D tex = new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, true);
            yield return new WaitForEndOfFrame();
            tex.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0, true);
            tex.Apply();
            yield return tex;
            byte[] byt = tex.EncodeToPNG();
            string path = Application.persistentDataPath.Substring(0, Application.persistentDataPath.IndexOf("Android"));
            File.WriteAllBytes(path + "/Pictures/Screenshots/" + name, byt);
        }

      2、关于路径Application中有四种路径(可自行百度),我们需要的是保存到截图专用的路径Pictures中,代码参考上面最后两行,也可将最后一样的Pictures/Screenshots(截图路径)可以替换/DCIM/Camera/(相册路径)。这样可以避免删掉游戏后图片消失。

      3、关于刷新相册,网上大多数人给的方案为调用java中的MediaScannerConnection.scanFile(百度上很多,这里不细说)。但是因为我们需要热更这个功能,所以必须在unity上去实现。

    后来一个大佬提了一个建议,用反射。代码如下

        //刷新图片,显示到相册中
        void ScanFile(string[] path)
        {
            using (AndroidJavaClass PlayerActivity = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
            {
                AndroidJavaObject playerActivity = PlayerActivity.GetStatic<AndroidJavaObject>("currentActivity");
                using (AndroidJavaObject Conn = new AndroidJavaObject("android.media.MediaScannerConnection", playerActivity, null))
                {
                    Conn.CallStatic("scanFile", playerActivity, path, null, null);
                }
            }
        }

      在unity中实现刷新相册,算是自己独立解决的一个问题,小小的有成就感。

    完整代码如下

    using UnityEngine;
    using System.Collections;
    using System;
    using System.IO;
    
    public class CaptureScreenshotMgr: MonoBehaviour
    {
    
        /// <summary>
        /// 保存截屏图片,并且刷新相册(Android和iOS)
        /// </summary>
        /// <param name="name">若空就按照时间命名</param>
        public void CaptureScreenshot(string name = "")
        {
            string _name = "";
            if (string.IsNullOrEmpty(name))
            {
                _name = "Screenshot_" + GetCurTime() + ".png";
            }
            //编辑器下
            //string path = Application.persistentDataPath + "/" + _name;
            //Application.CaptureScreenshot(path, 0);
            //EDebug.Log("图片保存地址" + path);
    
    
            //Android版本
            StartCoroutine(CutImage(_name));
            EDebug.Log("图片保存地址" + _name);
    
        }
        //截屏并保存
        IEnumerator CutImage(string name)
        {
            //图片大小  
            Texture2D tex = new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, true);
            yield return new WaitForEndOfFrame();
            tex.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0, true);
            tex.Apply();
            yield return tex;
            byte[] byt = tex.EncodeToPNG();
            string path = Application.persistentDataPath.Substring(0, Application.persistentDataPath.IndexOf("Android"));
            File.WriteAllBytes(path + "/Pictures/Screenshots/" + name, byt);
            string[] paths = new string[1];
            paths[0] = path;
            ScanFile(paths);
        }
        //刷新图片,显示到相册中
        void ScanFile(string[] path)
        {
            using (AndroidJavaClass PlayerActivity = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
            {
                AndroidJavaObject playerActivity = PlayerActivity.GetStatic<AndroidJavaObject>("currentActivity");
                using (AndroidJavaObject Conn = new AndroidJavaObject("android.media.MediaScannerConnection", playerActivity, null))
                {
                    Conn.CallStatic("scanFile", playerActivity, path, null, null);
                }
            }
        }
        /// <summary>
        /// 获取当前年月日时分秒,如201803081916
        /// </summary>
        /// <returns></returns>
        string GetCurTime()
        {
            return DateTime.Now.Year.ToString() + DateTime.Now.Month.ToString() + DateTime.Now.Day.ToString()
                + DateTime.Now.Hour.ToString() + DateTime.Now.Minute.ToString() + DateTime.Now.Second.ToString();
        }
    }

    备注:本来这些方法是静态的,StartCoroutine无法在静态中调用,我们是自己封装成了静态,为了读者方便就改成非静态方法,这里大家可以自行封装。

      

    
    
    
  • 相关阅读:
    《那些年啊,那些事——一个程序员的奋斗史》——94
    《那些年啊,那些事——一个程序员的奋斗史》——95
    《玩转.NET Micro Framework 移植基于STM32F10x处理器》前言
    《玩转.NET Micro Framework 移植基于STM32F10x处理器》资源汇总
    《那些年啊,那些事——一个程序员的奋斗史》——96
    《玩转.NET Micro Framework 移植基于STM32F10x处理器》微软中国.NET Micro Framework项目组工程师所作之序
    《那些年啊,那些事——一个程序员的奋斗史》——91
    《那些年啊,那些事——一个程序员的奋斗史》——93
    分享多年美工工作收集的小工具和经验
    C# 3.0的一些新特性
  • 原文地址:https://www.cnblogs.com/lihangppz/p/8530351.html
Copyright © 2011-2022 走看看