Unity3D 实用技巧 - 快速实现截图功能,留下精彩瞬间

因项目需要实现截图小功能,博主汇总调研信息。介绍了截图常用方式,如全屏、Texture2D、相机截图,调用系统API,给出核心代码及设置方法;还说明了生成指定内容带透明背景通道截图的步骤,最后提供GitHub项目工程地址供深度学习。
最近由于项目的需要,实现截图的小功能,实践中发现可达到效果的方式还是蛮多的,所以小编把调研过程中的信息汇总起来,与大家共同学习哈! 第一部分:截图的常用方式 - 全屏截图、Texture2D截图、相机截图方式 1、虽然实现方式比较多,但是里面的代码确实是比较简洁,都是调用系统自带的API。小编这边直接就上核心代码。ScreenCaptureController.cs 组件
    
using System ; using System . Collections ; using System . Collections . Generic ; using System . IO ; using UnityEngine ; using UnityEngine . UI ; public class ScreenCaptureController : MonoBehaviour { public Button button1 ; public Button button2 ; public Button button3 ; public Camera mainCamera ; public Camera extraCamera ; void Start ( ) { button1 . onClick . AddListener ( delegate { CaptureFunc ( GetPath ( ) ) ; } ) ; button2 . onClick . AddListener ( delegate { StartCoroutine ( Texture2DCapture ( GetPath ( ) ) ) ; } ) ; button3 . onClick . AddListener ( delegate { CameraCapture ( GetPath ( ) ) ; } ) ; } /// <summary> /// Unity自带的截屏功能,保存当前画面 /// </summary> /// <param name="filePath"></param> public void CaptureFunc ( string filePath ) { ScreenCapture . CaptureScreenshot ( filePath ) ; Debug . Log ( "全屏截图文件路径保存在" + filePath ) ; //刷新unity目录 RefreshResource ( ) ; } /// <summary> /// 普通截屏 /// </summary> /// <param name="filePath"></param> /// <returns></returns> public IEnumerator Texture2DCapture ( string filePath ) { yield return new WaitForEndOfFrame ( ) ; //1.起始的X坐标,Y坐标,宽、高 var rect = new Rect ( 0 , 0 , Screen . width , Screen . height ) ; Texture2D tex = new Texture2D ( ( int ) rect . width , ( int ) rect . height ) ; //2.读取像素、后面两个参数分别是X轴的偏移量,Y轴偏移量 tex . ReadPixels ( rect , 0 , 0 ) ; //3.保存数据 tex . Apply ( ) ; //4.将数据转换成PNG数据 byte [ ] bytes = tex . EncodeToPNG ( ) ; //5.将数据写成文件 File . WriteAllBytes ( filePath , bytes ) ; Debug . Log ( "Texture2D截图文件路径保存在" + filePath ) ; //6.刷新unity目录 RefreshResource ( ) ; } /// <summary> /// 刷新Unity的目录 /// </summary> private static void RefreshResource ( ) { # if UNITY_EDITOR UnityEditor . AssetDatabase . Refresh ( ) ; # endif } /// <summary> /// Texture2D生成图片 /// </summary> /// <param name="filePath"></param> public void CameraCapture ( string filePath ) { var camera = mainCamera ; //设置截图相机 var rect = new Rect ( 0 , 0 , Screen . width , Screen . height ) ; RenderTexture renderTexture = new RenderTexture ( ( int ) rect . width , ( int ) rect . height , 32 ) ; camera . targetTexture = renderTexture ; //设置相机的renderTexture camera . Render ( ) ; //手机开启相机的渲染 RenderTexture . active = renderTexture ; //当前活动的渲染纹理 Texture2D tex = new Texture2D ( ( int ) rect . width , ( int ) rect . height ) ; tex . ReadPixels ( rect , 0 , 0 ) ; tex . Apply ( ) ; RenderTexture . active = null ; //重置当前活动的渲染纹理 camera . targetTexture = null ; //重置相机的targetTexture //设置第二个截图相机 camera = extraCamera ; camera . targetTexture = renderTexture ; camera . Render ( ) ; RenderTexture . active = renderTexture ; tex . ReadPixels ( rect , 0 , 0 ) ; tex . Apply ( ) ; //重置当前活动的渲染纹理 camera . targetTexture = null ; camera = null ; RenderTexture . active = null ; //删除RenderTexture对象 Destroy ( renderTexture ) ; //写成图片文件 byte [ ] bytes = tex . EncodeToPNG ( ) ; File . WriteAllBytes ( filePath , bytes ) ; Debug . Log ( "多相机截图文件路径保存在" + filePath ) ; //刷新unity目录 RefreshResource ( ) ; //回收垃圾 Resources . UnloadUnusedAssets ( ) ; GC . Collect ( ) ; } public string GetPath ( ) { return Application . dataPath + "/截图" + UnityEngine . Random . Range ( 0 , 1000 ) + ".Png" ; } }
2、设置生成路径,与对应的设置。根据以下截图所示。操作界面中的按钮,生成所需要的截图文件。
第二部分:生成指定内容(带透明背景通道)的截图 1、第一步,创建工程项目后,直接接上功能的核心代码。SuperRunScreenshot.cs 组件
    
using System . Collections ; using System . Collections . Generic ; using UnityEngine ; using System . IO ; using System . Reflection ; using System ; public class SuperRunScreenshot : MonoBehaviour { public enum Extension { EXR , JPG , PNG , TGA } public int CaptureWidth = 0 ; public int CaptureHeight = 0 ; public Camera CaptureCamera = null ; public bool CaptureTransparent = true ; public string CapturePath = null ; public string CaptureLast = null ; public Extension CaptureExtension = Extension . PNG ; public bool FilenameCustomToggle = false ; public string FilenameCustomValue = null ; private void OnGUI ( ) { if ( GUI . Button ( new Rect ( 200 , 100 , 100 , 100 ) , "截取透明图片" ) ) { CaptureAction ( ) ; } } private void CaptureAction ( ) { // HDRP - HDAdditionalCameraData Type HDRPCameraTypeA = Type . GetType ( "UnityEngine.Rendering.HighDefinition.HDAdditionalCameraData, " + "Unity.RenderPipelines.HighDefinition.Runtime" , false , true ) ; Type HDRPCameraTypeB = Type . GetType ( "UnityEngine.Experimental.Rendering.HDPipeline.HDAdditionalCameraData, " + "Unity.RenderPipelines.HighDefinition.Runtime" , false , true ) ; Type HDRPCameraType = HDRPCameraTypeA ?? HDRPCameraTypeB ; Component HDRPCameraInstance = HDRPCameraType == null ? null : CaptureCamera . gameObject . GetComponent ( HDRPCameraType ) ; FieldInfo HDRPCameraBackgroundColorHDR = HDRPCameraType == null ? null : HDRPCameraType . GetField ( "backgroundColorHDR" ) ; FieldInfo HDRPCameraClearMode = HDRPCameraType == null ? null : HDRPCameraType . GetField ( "clearColorMode" ) ; // HDRP - HDAdditionalCameraData.ClearColorMode Type HDRPClearModeEnumA = Type . GetType ( "UnityEngine.Rendering.HighDefinition.HDAdditionalCameraData+ClearColorMode, " + "Unity.RenderPipelines.HighDefinition.Runtime" , false , true ) ; Type HDRPClearModeEnumB = Type . GetType ( "UnityEngine.Experimental.Rendering.HDPipeline.HDAdditionalCameraData+ClearColorMode, " + "Unity.RenderPipelines.HighDefinition.Runtime" , false , true ) ; Type HDRPClearModeEnum = HDRPClearModeEnumA ?? HDRPClearModeEnumB ; object HDRPClearModeColor = null ; if ( HDRPClearModeEnum != null && HDRPClearModeEnum != null ) { try { HDRPClearModeColor = Enum . Parse ( HDRPClearModeEnum , "Color" ) ; } catch ( Exception ) { } if ( HDRPClearModeColor == null ) { try { HDRPClearModeColor = Enum . Parse ( HDRPClearModeEnum , "BackgroundColor" ) ; } catch ( Exception ) { } } } // Temporary objects TextureFormat formatRGB = CaptureExtension == Extension . EXR ? TextureFormat . RGBAFloat : TextureFormat . RGB24 ; TextureFormat formatRGBA = CaptureExtension == Extension . EXR ? TextureFormat . RGBAFloat : TextureFormat . ARGB32 ; RenderTexture target = RenderTexture . GetTemporary ( CaptureWidth , CaptureHeight , 24 ) ; Texture2D capture = null ; if ( CaptureTransparent ) { // Remember current settings object preHDRPClearColorMode = HDRPCameraInstance == null ? null : HDRPCameraClearMode == null ? null : HDRPCameraClearMode . GetValue ( HDRPCameraInstance ) ; object preHDRPBackgroundColorHDR = HDRPCameraInstance == null ? null : HDRPCameraBackgroundColorHDR == null ? null : HDRPCameraBackgroundColorHDR . GetValue ( HDRPCameraInstance ) ; CameraClearFlags preClearFlags = CaptureCamera . clearFlags ; RenderTexture preTargetTexture = CaptureCamera . targetTexture ; RenderTexture preActiveTexture = RenderTexture . active ; Color preBackgroundColor = CaptureCamera . backgroundColor ; // Modify current settings if ( HDRPCameraInstance != null && HDRPCameraClearMode != null ) HDRPCameraClearMode . SetValue ( HDRPCameraInstance , HDRPClearModeColor ) ; CaptureCamera . clearFlags = CameraClearFlags . Color ; CaptureCamera . targetTexture = target ; RenderTexture . active = target ; // Capture screenshot with black background if ( HDRPCameraInstance != null && HDRPCameraBackgroundColorHDR != null ) HDRPCameraBackgroundColorHDR . SetValue ( HDRPCameraInstance , Color . black ) ; CaptureCamera . backgroundColor = Color . black ; CaptureCamera . Render ( ) ; Texture2D captureBlack = new Texture2D ( CaptureWidth , CaptureHeight , formatRGB , false ) ; captureBlack . ReadPixels ( new Rect ( 0f , 0f , CaptureWidth , CaptureHeight ) , 0 , 0 , false ) ; captureBlack . Apply ( ) ; // Capture screenshot with white background if ( HDRPCameraInstance != null && HDRPCameraBackgroundColorHDR != null ) HDRPCameraBackgroundColorHDR . SetValue ( HDRPCameraInstance , Color . white ) ; CaptureCamera . backgroundColor = Color . white ; CaptureCamera . Render ( ) ; Texture2D captureWhite = new Texture2D ( CaptureWidth , CaptureHeight , formatRGB , false ) ; captureWhite . ReadPixels ( new Rect ( 0f , 0f , CaptureWidth , CaptureHeight ) , 0 , 0 , false ) ; captureWhite . Apply ( ) ; // Create capture with transparency capture = new Texture2D ( CaptureWidth , CaptureHeight , formatRGBA , false ) ; for ( int x = 0 ; x < CaptureWidth ; ++ x ) { for ( int y = 0 ; y < CaptureHeight ; ++ y ) { Color lColorWhenBlack = captureBlack . GetPixel ( x , y ) ; Color lColorWhenWhite = captureWhite . GetPixel ( x , y ) ; float alpha = 1 + lColorWhenBlack . r - lColorWhenWhite . r ; Color color = new Color ( lColorWhenBlack . r / alpha , lColorWhenBlack . g / alpha , lColorWhenBlack . b / alpha , alpha ) ; capture . SetPixel ( x , y , color ) ; } } capture . Apply ( ) ; // Cleanup DestroyImmediate ( captureBlack ) ; DestroyImmediate ( captureWhite ) ; // Revert settings if ( HDRPCameraInstance != null && HDRPCameraBackgroundColorHDR != null ) HDRPCameraBackgroundColorHDR . SetValue ( HDRPCameraInstance , preHDRPBackgroundColorHDR ) ; if ( HDRPCameraInstance != null && HDRPCameraClearMode != null ) HDRPCameraClearMode . SetValue ( HDRPCameraInstance , preHDRPClearColorMode ) ; RenderTexture . active = preActiveTexture ; CaptureCamera . targetTexture = preTargetTexture ; CaptureCamera . backgroundColor = preBackgroundColor ; CaptureCamera . clearFlags = preClearFlags ; } else { // Remember current settings RenderTexture preTargetTexture = CaptureCamera . targetTexture ; RenderTexture preActiveTexture = RenderTexture . active ; // Modify current settings CaptureCamera . targetTexture = target ; RenderTexture . active = target ; // Capture screenshot without transparency CaptureCamera . Render ( ) ; capture = new Texture2D ( CaptureWidth , CaptureHeight , formatRGB , false ) ; capture . ReadPixels ( new Rect ( 0f , 0f , CaptureWidth , CaptureHeight ) , 0 , 0 , false ) ; capture . Apply ( ) ; // Revert settings RenderTexture . active = preActiveTexture ; CaptureCamera . targetTexture = preTargetTexture ; } // Encode texture to data byte [ ] data = Encode ( capture , CaptureExtension ) ; if ( data != null ) { // Create filename path CaptureLast = GetRenamedFilename ( Path . Combine ( CapturePath , GetFilename ( ) ) ) ; string filename = Path . GetFileName ( CaptureLast ) ; // Write data to path using ( FileStream stream = new FileStream ( CaptureLast , FileMode . Create ) ) { BinaryWriter writer = new BinaryWriter ( stream ) ; writer . Write ( data ) ; } // Log Debug . Log ( "Screenshot '" + filename + "' saved to '" + CapturePath + "'" , this ) ; } // Cleanup DestroyImmediate ( capture ) ; RenderTexture . ReleaseTemporary ( target ) ; } private string GetRenamedFilename ( string filename ) { int count = 1 ; string file = Path . GetFileNameWithoutExtension ( filename ) ; string extension = Path . GetExtension ( filename ) ; string path = Path . GetDirectoryName ( filename ) ; string renamed = filename ; while ( File . Exists ( renamed ) ) { string temp = string . Format ( "{0} ({1})" , file , count ++ ) ; renamed = Path . Combine ( path , temp + extension ) ; } return renamed ; } private string GetFilename ( ) { string extension = "." + CaptureExtension . ToString ( ) . ToLower ( ) ; if ( FilenameCustomToggle && ! string . IsNullOrEmpty ( FilenameCustomValue ) ) { if ( FilenameCustomValue . ToLower ( ) . EndsWith ( extension ) ) { return FilenameCustomValue ; } else { return FilenameCustomValue + extension ; } } else { return DateTime . Now . ToString ( "yyyy-MM-dd-HH-mm-ss" ) + extension ; } } private static byte [ ] Encode ( Texture2D texture , Extension extension ) { if ( extension == Extension . TGA ) { MethodInfo EncodeToTGA = typeof ( ImageConversion ) . GetMethod ( "EncodeToTGA" , BindingFlags . Static | BindingFlags . Public ) ; if ( EncodeToTGA == null ) { Debug . LogError ( "TGA Encoder not found." ) ; return null ; } else { return ( byte [ ] ) EncodeToTGA . Invoke ( null , new object [ ] { texture } ) ; } } else { switch ( extension ) { default : case Extension . PNG : return texture . EncodeToPNG ( ) ; case Extension . EXR : return texture . EncodeToEXR ( Texture2D . EXRFlags . CompressZIP ) ; case Extension . JPG : return texture . EncodeToJPG ( ) ; } } } }
2、第二步,我们如果需要渲染成图的内容,只要设置单独相机渲染。其他的设置按照图中设置即可。以Unity-Chan 角色为例。 3、运行项目,最终得到效果图。 最后,如果想深度学习的同伴,可以直接下载项目工程学习哈!GitHub项目工程地址: https://github.com/haili1234/ScreenShotExample
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值