要触发 相机一个组件,它会创建场景中特定视点的图像。输出要么绘制到屏幕上,要么作为纹理捕获。更多信息
查看 术语表 渲染到 渲染纹理一种特殊类型的纹理,它是在运行时创建和更新的。要使用它们,首先创建一个新的渲染纹理,并将其中一个相机指定为渲染到该纹理中。然后,你可以在材质中像使用普通纹理一样使用渲染纹理。更多信息
查看 术语表 在通用 渲染管线一系列操作,它将场景的内容获取并显示在屏幕上。Unity 允许你从预构建的渲染管线中选择,或编写你自己的渲染管线。更多信息
查看 术语表 (URP) 渲染循环之外,请在 C# 脚本中使用 SubmitRenderRequest
API。
此示例演示如何使用渲染请求和回调来监控这些请求的进度。你可以在 示例代码 部分看到完整的代码示例。
要渲染单个相机而不考虑完整的相机堆栈,请使用 UniversalRenderPipeline.SingleCameraRequest
API。请按照以下步骤操作
创建一个名为 SingleCameraRenderRequestExample
的 C# 脚本,并添加下面所示的 using
语句。
using System.Collections;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
public class SingleCameraRenderRequestExample : MonoBehaviour
{
}
创建数组以存储你想要从其渲染和渲染到的相机和渲染纹理。
public class SingleCameraRenderRequestExample : MonoBehaviour
{
public Camera[] cameras;
public RenderTexture[] renderTextures;
}
在 Start
方法中,添加一个检查以确保 cameras
和 renderTextures
数组有效,并且包含正确的数据,然后再继续运行脚本。
void Start()
{
// Make sure all data is valid before you start the component
if (cameras == null || cameras.Length == 0 || renderTextures == null || cameras.Length != renderTextures.Length)
{
Debug.LogError("Invalid setup");
return;
}
}
在 SingleCameraRenderRequest
类中创建一个名为 SendSingleRenderRequests
的方法,其返回类型为 void
。
在 SendSingleRenderRequests
方法中,添加一个 for
循环,它会像下面所示那样迭代 cameras
数组。
void SendSingleRenderRequests()
{
for (int i = 0; i < cameras.Length; i++)
{
}
}
在 for
循环中,使用 UniversalRenderPipeline.SingleCameraRequest
类型创建一个名为 request
的变量中的渲染请求。然后,使用 RenderPipeline.SupportsRenderRequest
检查活动渲染管线是否支持此渲染请求类型。
如果活动渲染管线支持渲染请求,则将相机输出的目标设置为 renderTextures
数组中匹配的渲染纹理。然后,使用 RenderPipeline.SubmitRenderRequest
提交渲染请求。
void SendSingleRenderRequests()
{
for (int i = 0; i < cameras.Length; i++)
{
UniversalRenderPipeline.SingleCameraRequest request =
new UniversalRenderPipeline.SingleCameraRequest();
// Check if the active render pipeline supports the render request
if (RenderPipeline.SupportsRenderRequest(cameras[i], request))
{
// Set the destination of the camera output to the matching RenderTexture
request.destination = renderTextures[i];
// Render the camera output to the RenderTexture synchronously
// When this is complete, the RenderTexture in renderTextures[i] contains the scene rendered from the point
// of view of the Camera in cameras[i]
RenderPipeline.SubmitRenderRequest(cameras[i], request);
}
}
}
在 SendSingleRenderRequest
方法上方,创建一个名为 RenderSingleRequestNextFrame
的 IEnumerator
接口。
在 RenderSingleRequestNextFrame
中,等待主相机完成渲染,然后调用 SendSingleRenderRequest
。等待帧结束,然后使用 StartCoroutine
在协程中重新启动 RenderSingleRequestNextFrame
。
IEnumerator RenderSingleRequestNextFrame()
{
// Wait for the main camera to finish rendering
yield return new WaitForEndOfFrame();
// Enqueue one render request for each camera
SendSingleRenderRequests();
// Wait for the end of the frame
yield return new WaitForEndOfFrame();
// Restart the coroutine
StartCoroutine(RenderSingleRequestNextFrame());
}
在 Start
方法中,使用 StartCoroutine
在协程中调用 RenderSingleRequestNextFrame
。
void Start()
{
// Make sure all data is valid before you start the component
if (cameras == null || cameras.Length == 0 || renderTextures == null || cameras.Length != renderTextures.Length)
{
Debug.LogError("Invalid setup");
return;
}
// Start the asynchronous coroutine
StartCoroutine(RenderSingleRequestNextFrame());
}
在编辑器中,在你的 场景场景包含游戏环境和菜单。将每个唯一的场景文件视为一个独特的关卡。在每个场景中,你可以放置环境、障碍物和装饰,从本质上讲,你是在设计和构建游戏的各个部分。更多信息
查看 术语表 中创建一个空的 游戏对象Unity 场景中的基本对象,它可以表示角色、道具、场景、相机、航点等等。游戏对象的功能由附加到它的组件定义。更多信息
查看 术语表,并将 SingleCameraRenderRequestExample.cs
添加为一个 组件游戏对象的功能部件。游戏对象可以包含任意数量的组件。Unity 有许多内置的组件,你也可以通过编写从 MonoBehaviour 继承的脚本来自行创建组件。更多信息
查看 术语表。
在 检查器一个 Unity 窗口,用于显示有关当前选定游戏对象、资产或项目设置的信息,允许你检查和编辑这些值。更多信息
查看 术语表 窗口中,将你想要从中渲染的相机添加到 cameras 列表中,并将你想要渲染到的渲染纹理添加到 renderTextures 列表中。
注意:cameras 列表中的相机数量和 renderTextures 列表中的渲染纹理数量必须相同。
现在,当你进入播放模式时,你添加的相机将渲染到你添加的渲染纹理中。
要检查相机何时完成渲染,请使用 RenderPipelineManager API 中的任何回调。
以下示例使用 RenderPipelineManager.endContextRendering 回调。
将 using System.Collections.Generic
添加到 SingleCameraRenderRequestExample.cs
文件的顶部。
在 Start
方法的末尾,订阅 endContextRendering
回调。
void Start()
{
// Make sure all data is valid before you start the component
if (cameras == null || cameras.Length == 0 || renderTextures == null || cameras.Length != renderTextures.Length)
{
Debug.LogError("Invalid setup");
return;
}
// Start the asynchronous coroutine
StartCoroutine(RenderSingleRequestNextFrame());
// Call a method called OnEndContextRendering when a camera finishes rendering
RenderPipelineManager.endContextRendering += OnEndContextRendering;
}
创建一个名为 OnEndContextRendering
的方法。当 endContextRendering
回调触发时,Unity 会运行此方法。
void OnEndContextRendering(ScriptableRenderContext context, List<Camera> cameras)
{
// Create a log to show cameras have finished rendering
Debug.Log("All cameras have finished rendering.");
}
要取消 OnEndContextRendering
方法对 endContextRendering
回调的订阅,请向 SingleCameraRenderRequestExample
类添加一个 OnDestroy
方法。
void OnDestroy()
{
// End the subscription to the callback
RenderPipelineManager.endContextRendering -= OnEndContextRendering;
}
此脚本现在与之前一样工作,但会向 控制台窗口一个 Unity 编辑器窗口,用于显示 Unity 或你的脚本生成的错误、警告和其他消息。更多信息
查看 术语表 记录一条消息,说明哪些相机已完成渲染。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
public class SingleCameraRenderRequest : MonoBehaviour
{
public Camera[] cameras;
public RenderTexture[] renderTextures;
void Start()
{
// Make sure all data is valid before you start the component
if (cameras == null || cameras.Length == 0 || renderTextures == null || cameras.Length != renderTextures.Length)
{
Debug.LogError("Invalid setup");
return;
}
// Start the asynchronous coroutine
StartCoroutine(RenderSingleRequestNextFrame());
// Call a method called OnEndContextRendering when a camera finishes rendering
RenderPipelineManager.endContextRendering += OnEndContextRendering;
}
void OnEndContextRendering(ScriptableRenderContext context, List<Camera> cameras)
{
// Create a log to show cameras have finished rendering
Debug.Log("All cameras have finished rendering.");
}
void OnDestroy()
{
// End the subscription to the callback
RenderPipelineManager.endContextRendering -= OnEndContextRendering;
}
IEnumerator RenderSingleRequestNextFrame()
{
// Wait for the main camera to finish rendering
yield return new WaitForEndOfFrame();
// Enqueue one render request for each camera
SendSingleRenderRequests();
// Wait for the end of the frame
yield return new WaitForEndOfFrame();
// Restart the coroutine
StartCoroutine(RenderSingleRequestNextFrame());
}
void SendSingleRenderRequests()
{
for (int i = 0; i < cameras.Length; i++)
{
UniversalRenderPipeline.SingleCameraRequest request =
new UniversalRenderPipeline.SingleCameraRequest();
// Check if the active render pipeline supports the render request
if (RenderPipeline.SupportsRenderRequest(cameras[i], request))
{
// Set the destination of the camera output to the matching RenderTexture
request.destination = renderTextures[i];
// Render the camera output to the RenderTexture synchronously
RenderPipeline.SubmitRenderRequest(cameras[i], request);
// At this point, the RenderTexture in renderTextures[i] contains the scene rendered from the point
// of view of the Camera in cameras[i]
}
}
}
}