静默截取物体快照,物体可以放在任意位置,不影响屏幕显示。和之前那个截屏不同,这次使用了RenderTexture。其中难点在于,要把相机放到合适的位置才能观察到物体的全貌,具体可以看代码注释。
另外有个技巧,如果不想要背景和其他物体,只要该物体的截图,可以在调用前把物体放置到一个非常远的位置(比如世界坐标y=-1000),调用完后再恢复位置。
///
/// 保存物体快照到PNG文件
///
/// yoyo(http://yoyo.play175.com)
/// 需要快照的物体
/// 文件路径
/// 照片像素大小(正方形照片)
public static void SnapshotToFile(GameObject targetObject,string filePath,int imageSize = 256)
{
Camera cam = Camera.main;
//记录相机位置
Vector3 opos = cam.transform.position;
Vector3 oscale = cam.transform.localScale;
Quaternion orot = cam.transform.localRotation;
//计算物体包围盒
Renderer[] renderers = targetObject.GetComponentsInChildren();
Vector3 min = targetObject.transform.position, max = targetObject.transform.position;
for (int i = 0; i < renderers.Length; i++)
{
min = Vector3.Min(renderers[i].bounds.min, min);
max = Vector3.Max(renderers[i].bounds.max, max);
}
//把相机放到合适位置
Vector3 center = new Vector3((max.x + min.x) / 2, (max.y + min.y) / 2, (max.z + min.z) / 2);//中心点
Vector3 step = (max - center).normalized;//相对于中心点的单位向量
//先放到中心点的前右上角
cam.transform.position = center + step;
//拉到合适距离
cam.transform.position = cam.transform.position + step * (max - min).magnitude * 50 / cam.fieldOfView;
//旋转方向以便看到目标
cam.transform.LookAt(center);
RenderTexture rt = new RenderTexture(imageSize, imageSize, 24);
cam.targetTexture = rt;
cam.Render();
RenderTexture.active = rt;//关键点,有点类似make current 的意思
Texture2D t = new Texture2D(imageSize, imageSize, TextureFormat.RGB24, false);//false代表不需要使用mipmaps
t.ReadPixels(new Rect(0, 0, imageSize, imageSize), 0, 0);
RenderTexture.active = null;//置空,以免出错
GameObject.Destroy(rt);
//恢复相机位置
cam.targetTexture = null;
cam.transform.position = opos;
cam.transform.localScale = oscale;
cam.transform.localRotation = orot;
//转为png数据
byte[] b = t.EncodeToPNG();
GameObject.Destroy(t);
//保存文件
System.IO.File.WriteAllBytes(filePath, b);
}
//调用举例:SnapshotToFile(gameobj, Application.dataPath + "/snap.png");