using UnityEditor;
using UnityEngine;
using UnityEditor.SceneManagement;
using System.IO;
public class MenuTest : MonoBehaviour {
// Добавляем пункт меню
[MenuItem("MyMenu/Capture Terrain ScreenShots")]
static void CaptureTerrainScreenShots()
{
int textureHeight = 1024;
// Получаем количество сцен
int sceneCount = UnityEngine.SceneManagement.SceneManager.sceneCountInBuildSettings;
for (int i = 0; i < sceneCount; i++)
{
// Получаем путь к сцене
string scenePath = UnityEngine.SceneManagement.SceneUtility.GetScenePathByBuildIndex(i);
// И ее имя
string sceneName = System.IO.Path.GetFileNameWithoutExtension(scenePath);
// Открываем сцену
EditorSceneManager.OpenScene(scenePath);
// Получаем объект типа Terrain в сцене
Terrain terrain = FindObjectOfType<Terrain>();
if (terrain == null) continue;
// Берем его размер
Vector3 size = terrain.terrainData.size;
// Создаем камеру, с которой будем снимать
Camera camera = new GameObject("ScreenShotCamera", typeof(Camera)).GetComponent<Camera>();
// Позиционируем ее над террейном
camera.transform.position = terrain.transform.position + new Vector3(size.x / 2, size.y, size.z / 2);
camera.transform.LookAt(new Vector3(size.x / 2, 0, size.z / 2));
camera.orthographic = true;
camera.orthographicSize = size.z / 2;
// Создаем текстуру, в которую будем рендерить
// (Предварительно сохранив текущую)
RenderTexture currentRT = RenderTexture.active;
// Создаем текстуру, пропорциональную размеру террейна
RenderTexture rt = new RenderTexture(textureHeight, (int)(textureHeight * size.z / size.x), 24);
// Или вот так - 1 юнит = 1 пиксель
// RenderTexture rt = new RenderTexture(text(int)size.x, (int)size.z, 24);
// Устанавливаем созданную текстуру как целевую
RenderTexture.active = rt;
camera.targetTexture = rt;
// Принудительно вызываем рендер камеры
camera.GetComponent<Camera>().Render();
// Получаем обычную текстуру из RenderTexture'ы
// Ее можно будет использовать в игре, или же
// Сохранить, что мы и сделаем
Texture2D image = new Texture2D(rt.width, rt.height);
image.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0);
image.Apply();
// Пишем текстуру в .png файл
byte[] bytes = image.EncodeToPNG();
File.WriteAllBytes(Application.dataPath + "/TerrainScreenshots/" + sceneName + ".png", bytes);
// Восстанавливаем рендер таргет
RenderTexture.active = currentRT;
// Чистим все (при необходимости)
DestroyImmediate(image);
DestroyImmediate(camera.gameObject);
DestroyImmediate(rt);
}
}
}
一般来说,如果我理解正确,那么你需要一个神奇的按钮“在场景中截取所有地形”。
好吧,让我们想想:
我们将无法按照应有的方式设置透视相机,因为地形在不同的点可能有不同的高度,它不会变得很酷。所以我们使用正交相机。
让事情变得更好,
UnityEditor而不用抽搐UnityEngine。最好先渲染
RenderTexture,然后保存到常规纹理和磁盘。然后不要忘记删除您身后的所有内容。
考虑到所有先前的注释,我铆接了以下代码(代码被大量注释):
当您将此代码保存到您的项目时,您将在顶部有一个菜单项
MyMenu/Capture Terrain ScreenShots:单击哪个后,您添加到构建设置 (
File/BuildSettings) 的所有场景将循环运行,并且出现在它们上的第一个地形将被相机捕获。该代码绝对有效,我在我的机器上对其进行了测试。不要忘记指定保存截图所需的路径(我提醒你,该路径上的所有文件夹都必须创建,否则会出现类似“部分路径不存在等等等等”的错误)。
顺便说一句,代码中有一个不太明显的时刻。当我设置相机时,我设置了一些
size:这等于景观的深度。你问宽度在哪里?并且宽度是和你设置的贴图宽度成比例的
camera.targetTexture,所以我特意只通过 来设置贴图大小textureHeight,而宽度已经算是比例了。是的。如果您需要截取未添加到构建设置中的场景的屏幕截图,那么您将不得不想出另一种获取场景的方法。例如,如果它们在同一个文件夹
Resources/ЭтаСамаяПапка中,那么您可以使用Resources.LoadAll. 然而,这是一个完全不同的故事(我懒得写对文件系统的迭代,抱歉)。像这样的东西。我希望打勾)
为了对单个对象或一组对象“拍照”,您可以使用Render Texture,然后借助代码中的简单操作,您可以将生成的 Render Texute 保存为纹理并保存为一个PNG文件。
例如,类似的技术被用于在游戏中创建迷你地图。说明创建小地图的过程的教程。
关于自动化,在这里您必须自己完成,但由于您将通过单独的相机进行渲染,因此您可以根据需要对其进行自定义。这是使用渲染纹理的另一个示例。
你好!
有一次我做了类似的事情,但仅限于
GameObject's. 我在某个地方找到了一个例子,我记不太清了,但代码仍然存在。首先,您需要计算
Bounds对象的边界,并使用它们来调整相机。以地形为代价,我不确定它是如何工作的,但原则上它们也是非洲的物体)用法:
以防万一,如果您想为某些游戏对象自定义相机?这是计算对象边界的代码。
代码并不完美,您可能需要根据需要调整一些东西,但主要的是它可以满足您的需求。