要做一個截圖的功能,並且玩家可以在相冊中看到。
做的時候遇到了三個問題:
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無法在靜態中調用,我們是自己封裝成了靜態,為了讀者方便就改成非靜態方法,這里大家可以自行封裝。