a need
I need to take screenshots at different levels in the scene (such as only taking screenshots of the model, only taking the UI, or only taking the externally added images, or taking all of them, or working with the Shader to present the screen switching of the thermal imaging of the human eye night vision device)
Sort the screenshots into a list and display them in the scene UI
How to do
-
The camera should be able to see different images
-
Store the current frame
-
Display the stored screen
Knowledge point code
https://developer.unity.cn/projects/64ca2cbbedbc2a00187ba6d6
Continue below
Do an exercise. Screenshot details, outline + UI, and display all three pictures separately.
-
First, classify the game objects into categories
-
Simply design the UI, the screenshot function will be operated here, and the screenshot will be displayed here.
The three additions are the main camera of the Main scene, the camera specially displayed in the DesktopUI interface UI, and the CamTexture camera specially used for screenshot operations. It is not turned on at ordinary times, but is only turned on when taking screenshots to capture the picture rendered by this camera.
-
If CamTexture wants to render different images, it must have different settings.
public
class
CtrlScreenShot
:
MonoBehaviour
{
//相机渲染
[
Header
(
"可用渲染内容的相机"
)
]
public
Camera
cameraToChange
;
[
Header
(
"具体渲染的Layers"
)
]
public
LayerMask
CullingLayers0
;
public
LayerMask
CullingLayers1
;
public
LayerMask
CullingLayers2
;
// 照片存储的位置
public
Transform
PhotenRoot
;
//截图的大小模板(在场景中透明显示就行,为的就是截图时候按照这个UI的大小去截图)
public
RectTransform
UIRect
;
//
LayerMask
CullingLayers
;
Transform
photenPos
;
string
photenName
;
public
void
CtrlScreenShotBtFc
(
int
butint
)
{
switch
(
butint
)
{
case
0
:
CullingLayers
=
CullingLayers0
;
//相机渲染显示的Layers
photenPos
=
PhotenRoot
.
GetChild
(
0
)
.
transform
;
//截图显示的位置
break
;
case
1
:
CullingLayers
=
CullingLayers1
;
//相机渲染显示的Layers
photenPos
=
PhotenRoot
.
GetChild
(
1
)
.
transform
;
//截图显示的位置
break
;
case
2
:
CullingLayers
=
CullingLayers2
;
//相机渲染显示的Layers
photenPos
=
PhotenRoot
.
GetChild
(
2
)
.
transform
;
//截图显示的位置
break
;
default
:
break
;
}
StartCoroutine
(
StartScreenShot
(
)
)
;
}
///
IEnumerator
StartScreenShot
(
)
{
cameraToChange
.
cullingMask
=
0
;
//全部剔除
cameraToChange
.
cullingMask
=
CullingLayers
;
//显示选择的Layers
cameraToChange
.
gameObject
.
SetActive
(
true
)
;
photenName
=
System
.
DateTime
.
Now
.
ToString
(
"yyyyMMddHHmmss"
)
+
".png"
;
//截图的名字
string
fileName
=
Application
.
dataPath
+
"/StreamingAssets/"
+
photenName
;
//系统不识别标点符号,但支持中文
yield
return
StartCoroutine
(
CaptureByUI
(
UIRect
,
fileName
)
)
;
// 拼接图片路径
string
imagePath
=
System
.
IO
.
Path
.
Combine
(
Application
.
streamingAssetsPath
,
photenName
)
;
// 开始协程加载图片
yield
return
StartCoroutine
(
LoadImage
(
imagePath
,
photenPos
)
)
;
cameraToChange
.
gameObject
.
SetActive
(
false
)
;
}
/// <summary>
/// 保存截图,并保存成png格式文件
/// </summary>
/// <param name="UIRect"></param>屏幕截图的大小尺寸规范 是个透明的imageUI
/// <param name="mFileName"></param>将截图转换成的png文件保存的位置和命名
/// <returns></returns>
IEnumerator
CaptureByUI
(
RectTransform
UIRect
,
string
mFileName
)
{
yield
return
new
WaitForEndOfFrame
(
)
;
//等待当前帧的UI渲染完成
//计算截图的宽度和高度
int
width
=
(
int
)
(
UIRect
.
rect
.
width
)
;
int
height
=
(
int
)
(
UIRect
.
rect
.
height
)
;
//创建一个新的Texture2D对象,宽度和高度与截图的宽度和高度匹配
Texture2D
tex
=
new
Texture2D
(
width
,
height
,
TextureFormat
.
RGB24
,
false
)
;
//计算从屏幕上读取像素的起始位置
float
leftBtmX
=
UIRect
.
transform
.
position
.
x
+
UIRect
.
rect
.
xMin
;
float
leftBtmY
=
UIRect
.
transform
.
position
.
y
+
UIRect
.
rect
.
yMin
;
//使用tex.ReadPixels()函数从屏幕上读取指定区域的像素,并存储到Texture2D中。
tex
.
ReadPixels
(
new
Rect
(
leftBtmX
,
leftBtmY
,
width
,
height
)
,
0
,
0
)
;
//执行读取操作,将修改应用到Texture2D中
tex
.
Apply
(
)
;
//将Texture2D编码为PNG格式的字节数组
byte
[
]
bytes
=
tex
.
EncodeToPNG
(
)
;
//将字节数组保存为PNG图片文件
System
.
IO
.
File
.
WriteAllBytes
(
mFileName
,
bytes
)
;
}
/// <summary>
/// 将保存的png,根据名字在界面上相对位置展示出来
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
IEnumerator
LoadImage
(
string
path
,
Transform
photenPos
)
{
// 发送请求获取图片
UnityWebRequest
www
=
UnityWebRequestTexture
.
GetTexture
(
path
)
;
yield
return
www
.
SendWebRequest
(
)
;
// 检查请求是否成功
if
(
www
.
result
==
UnityWebRequest
.
Result
.
Success
)
{
// 获取加载的Texture
Texture2D
texture
=
DownloadHandlerTexture
.
GetContent
(
www
)
;
//创建一个RawImage并放在其位置
GameObject
uiObject
=
new
GameObject
(
)
;
uiObject
.
transform
.
parent
=
photenPos
.
transform
;
RectTransform
rectTransform
=
uiObject
.
AddComponent
<
RectTransform
>
(
)
;
CanvasRenderer
canvasRenderer
=
uiObject
.
AddComponent
<
CanvasRenderer
>
(
)
;
RawImage
rawImage
=
uiObject
.
AddComponent
<
RawImage
>
(
)
;
// 将加载的Texture赋值给RawImage的texture属性
rawImage
.
texture
=
texture
;
// 调整RawImage的大小以适应图片的长宽比例
rawImage
.
SetNativeSize
(
)
;
// 获取父级图像的宽度
float
parentWidth
=
rawImage
.
transform
.
parent
.
GetComponent
<
RectTransform
>
(
)
.
rect
.
width
;
// 计算图像的长宽比
float
aspectRatio
=
(
float
)
rawImage
.
texture
.
height
/
rawImage
.
texture
.
width
;
// 计算应用于图像的新高度
float
newHeight
=
parentWidth
*
aspectRatio
;
// 设置图像的宽度和高度
rawImage
.
rectTransform
.
sizeDelta
=
new
Vector2
(
parentWidth
,
newHeight
)
;
// 将图像的位置设置为零
rawImage
.
rectTransform
.
localPosition
=
Vector3
.
zero
;
// 将图像的缩放设置为1
rawImage
.
rectTransform
.
localScale
=
Vector3
.
one
;
}
else
{
Debug
.
LogError
(
"Failed to load image: "
+
www
.
error
)
;
}
}
}
In this way, you can also realize the function of taking pictures in AR, and you can switch whether the screenshot is real or virtual plus reality, etc.