内容将会持续更新,有错误的地方欢迎指正,谢谢!
拥有更好的学习体验 —— 不断努力,不断进步,不断探索 |
助力快速掌握 Unity 生命周期函数 为初学者节省宝贵的学习时间,避免困惑! |
深入探索Unity游戏开发中的生命周期函数(一)
深入探索Unity游戏开发中的生命周期函数(二)
深入探索Unity游戏开发中的生命周期函数(三)
深入探索Unity游戏开发中的生命周期函数(四)
TechX 教程效果:
文章目录
六、Scene Rendering
1、OnPreCull()
在Unity的生命周期中,OnPreCull() 是一个特殊的函数,用于在相机完成场景剔除(culling)计算之前被调用。这个函数的主要用途是允许你在场景剔除之前执行一些自定义的操作,例如在剔除发生之前更新对象的位置或状态,或者在剔除之前进行特定的渲染准备工作。
以下是关于 OnPreCull() 函数的详细介绍:
- 函数签名:
void OnPreCull()
- 触发时机:
- OnPreCull() 函数会在相机执行场景剔除计算之前被调用,确保你在剔除发生之前可以对场景中的对象进行必要的处理。
- 剔除计算:
- 剔除是一种性能优化技术,用于确定哪些物体在相机的视锥体之外,从而避免在渲染阶段不必要地渲染这些物体。OnPreCull() 函数在剔除计算之前被调用,这使得你可以在剔除之前执行一些与渲染相关的操作。
- 自定义渲染准备:
- OnPreCull() 可以用于进行自定义的渲染准备工作,例如计算对象的位置、更新对象的材质或纹理,以及设置特定的渲染参数。这样你可以在剔除发生之前,根据相机的视角对对象进行一些自定义的渲染准备。
- 挂载在摄像机上:
- 将具有 OnPreCull() 函数的脚本挂载在摄像机上,会在摄像机的渲染流程中的 OnPreCull() 阶段执行。在这个阶段,摄像机即将进行场景剔除计算,确定哪些物体将在渲染中被保留,哪些将被剔除。你可以在这个时刻执行一些操作,以影响摄像机最终的渲染结果。注意,在这里进行过度复杂的操作可能会影响性能。
using UnityEngine;
public class PreCullExample : MonoBehaviour
{
// 挂载在摄像机上的 OnPreCull 函数
private void OnPreCull()
{
// 在摄像机渲染前进行操作
if (gameObject.CompareTag("Player"))
{
// 在摄像机渲染前更新玩家位置,实现跟随效果
Vector3 playerPosition = GetPlayerPosition();
Camera.main.transform.position = playerPosition;
}
}
// 获取玩家位置
private Vector3 GetPlayerPosition()
{
// 假设此处返回玩家的当前位置
}
}
上述示例在摄像机的 OnPreCull() 阶段,你可以更新摄像机的位置,从而实现一种“跟随”效果。假设你想实现一个摄像机始终跟随玩家的目标位置,你可以在 OnPreCull() 阶段更新摄像机的位置,使其与目标位置保持一致。
- 挂载在普通对象上:
- 将具有 OnPreCull() 函数的脚本挂载在普通游戏对象上,会在每个摄像机的渲染流程中的 OnPreCull() 阶段执行,而不仅仅是特定摄像机。这意味着,在每次摄像机进行渲染之前,都会执行这个脚本中的 OnPreCull() 函数。
using UnityEngine;
public class PreCullExample : MonoBehaviour
{
// 挂载在普通游戏对象上的 OnPreCull 函数
private void OnPreCull()
{
// 在每个摄像机渲染前进行操作
if (gameObject.CompareTag("Flag"))
{
// 在摄像机渲染前更新旗帜的位置和摆动状态
UpdateFlagPositionAndSwing();
}
}
// 更新旗帜的位置和摆动状态
private void UpdateFlagPositionAndSwing()
{
// 假设此处实现旗帜的位置和摆动状态的更新
}
}
示例: 假设你的场景中有一个旗帜对象,你希望在任何摄像机渲染前都能使旗帜随风摆动。通过在旗帜对象上挂载具有 OnPreCull() 函数的脚本,你可以在每个摄像机渲染之前都更新旗帜的位置和摆动状态,确保在所有视角下都能看到摆动的旗帜。
2、OnBecameVisible()
当游戏对象的渲染器变得对相机可见时,Unity 会自动调用 OnBecameVisible()函数。这个函数在游戏对象的生命周期内只会被调用一次,即当对象从不可见状态变为可见状态时。
以下是关于 OnBecameVisible()`函数的详细介绍:
- 函数签名:
void OnBecameVisible()
- 触发时机:
- OnBecameVisible() 函数是在渲染阶段的早期调用的,它在相机完成对场景的裁剪之后,判断游戏对象是否被裁剪在可见视锥体之内时执行。
- 当游戏对象的渲染器变得对任何相机可见时,OnBecameVisible()函数将被调用。这通常在对象进入相机的视野范围内时发生,也就是说,当对象足够接近相机,以至于它可以被渲染出来时,该函数会被调用。
- 执行流程:
- 当 OnBecameVisible()函数被调用时,Unity 会在主线程中执行函数中的代码。这允许你在对象变得可见时执行一些特定的操作。
- 用途:
- OnBecameVisible()函数常用于处理与对象可见性相关的功能。你可以在函数中编写代码逻辑,以响应对象变得可见的事件。例如,你可以在对象变得可见时开始播放动画、激活粒子效果、加载资源等。
- 注意事项:
-
OnBecameVisible() 函数是在对象变得对任何相机可见时触发的。这意味着即使对象只是部分进入相机视野,函数也会被调用。因此,如果你需要处理精确的对象可见性,可能需要进一步的检查来确保对象的确完全可见。
-
在多相机场景中,当对象在一个相机视野内变得可见时,函数会被调用。这可能导致在不同相机下的多次调用,因此你需要确保在多相机场景中的表现与预期一致。
示例代码:
using UnityEngine;
public class VisibilityExample : MonoBehaviour
{
private void OnBecameVisible()
{
// 当对象变得可见时,播放一个粒子效果
ParticleSystem particleSystem = GetComponent<ParticleSystem>();
if (particleSystem != null)
{
particleSystem.Play();
}
}
}
在上述示例中,当游戏对象的渲染器变得可见时,OnBecameVisible()
函数会触发,然后我们会播放一个粒子效果。
总结来说,OnBecameVisible()函数提供了一个机会,让你在游戏对象变得可见时执行特定的操作,从而响应对象的可见性变化。
3、OnBecameInVisible()
OnBecameInvisible()用于处理游戏对象在变得不可见时触发的事件。当一个游戏对象从相机的视野中消失时,Unity 会自动调用该函数。
以下是关于 OnBecameInvisible()`函数的详细介绍:
- 函数签名:
void OnBecameInvisible()
- 触发时机:
- OnBecameInvisible() 函数是在渲染阶段的早期调用的,它在相机完成对场景的裁剪之后,判断游戏对象是否被裁剪在可见视锥体之外时执行。
- 当游戏对象从一个相机的视野中消失时,OnBecameInvisible()函数被触发。这通常是在游戏对象从相机视野范围内移出时发生的,比如对象离开了相机的可视区域。
- 执行流程:
- 当 OnBecameInvisible()函数被触发后,Unity 会调用该函数,并在主线程中执行函数中的代码。
- 使用场景:
- OnBecameInvisible()函数常用于实现与游戏对象可见性变化相关的功能。通过在该函数中编写代码逻辑,可以实现在对象不可见时暂停特定效果、停止音效、释放资源等操作。
- 注意事项:
-
如果你的游戏中涉及多个相机,OnBecameInvisible() 函数会对每个相机的可见性变化都进行触发。这意味着在切换相机视角时,该函数可能会多次被调用。要确保你的逻辑在不同相机之间正确处理。
-
OnBecameInvisible() 函数只会在游戏对象从可见变为不可见时被调用,但并不会提供关于为何对象不可见的详细信息。如果你需要检测对象是否在某个特定的位置不可见,可能需要使用其他方法来实现,如射线检测等。
-
OnBecameInvisible()是在相机完成场景裁剪之后被调用的,因此在 OnBecameInvisible() 中进行的操作不会影响相机的裁剪结果。相机裁剪是在这个函数之前完成的,所以你无法通过更改对象的状态来影响相机的可见性。
以下是一个示例代码:
using UnityEngine;
public class ExampleScript : MonoBehaviour
{
private ParticleSystem particles;
private AudioSource audioSource;
private void Start()
{
particles = GetComponent<ParticleSystem>();
audioSource = GetComponent<AudioSource>();
}
// 当对象不可见时停止粒子效果和音效
private void OnBecameInvisible()
{
particles.Stop();
if (audioSource.isPlaying)
{
audioSource.Pause();
}
}
}
在上述示例中,当游戏对象变得不可见时,OnBecameInvisible()函数会被调用,停止粒子效果并暂停正在播放的音效。
总而言之,OnBecameInvisible()`函数在处理游戏对象从可见到不可见状态的变化时发挥作用,允许你执行特定的操作,以确保对象的状态与可见性保持同步。
4、OnWillRenderObject()
OnWillRenderObject()用于在每个相机完成裁剪计算后调用,用于决定是否渲染游戏对象。它是一个非常有用的函数,允许你在相机渲染场景之前进行额外的操作。
以下是关于 OnWillRenderObject() 函数的详细介绍:
- 函数签名:
void OnWillRenderObject()
- 触发时机:
- OnWillRenderObject() 函数在每个相机完成裁剪计算后调用,即在相机开始渲染场景之前。
- 使用场景:
- 主要用于自定义渲染和可视化效果。通常情况下,它用于自定义相机渲染、渲染纹理等。
- 执行流程:
- 在每个相机开始渲染场景之前,Unity会调用所有活动游戏对象上的 OnWillRenderObject() 函数。这为开发者提供了一个扩展 Unity 渲染流程的机会。
- 注意事项:
- OnWillRenderObject() 函数的执行次数会受到相机的影响,每个相机都会触发一次。如果你的游戏对象同时被多个相机可见,该函数会在每个相机渲染时都被调用。
示例代码:
下面是一个简单的示例代码,展示了 OnWillRenderObject() 函数的基本使用:
using UnityEngine;
public class CameraDependentColor : MonoBehaviour
{
private Material material;
private void Start()
{
material = GetComponent<Renderer>().material;
}
private void OnWillRenderObject()
{
// 判断是否是主相机渲染
if (Camera.current.tag == "MainCamera")
{
material.color = Color.blue; // 主相机渲染时物体颜色为蓝色
}
// 判断是否是第二个相机渲染
else if (Camera.current.tag == "SecondCamera")
{
material.color = Color.red; // 第二个相机渲染时物体颜色为红色
}
}
}
在这个示例中,我们在脚本中给主相机和第二个相机设置了不同的标签(“MainCamera” 和 “SecondCamera”),然后使用 OnWillRenderObject() 函数来检测当前渲染的相机,并根据相机的标签来改变物体的颜色。主相机渲染时颜色为蓝色,第二个相机渲染时颜色为红色。
总而言之,OnWillRenderObject() 函数允许你在 Unity 的渲染流程中进行自定义操作,可以用于增加渲染效果、自定义渲染逻辑等。
5、OnPreRender()
OnPreRender()是在相机开始渲染场景之前调用。在这个函数中,你可以执行一些在场景渲染之前需要处理的操作。下面是关于 OnPreRender()函数的详细介绍:
- 函数签名:
void OnPreRender()
- 触发时机:
- OnPreRender()函数在相机开始渲染场景之前被调用,即在渲染开始前的时刻。这使得你有机会在渲染开始之前对场景进行一些准备工作。
- 使用场景:OnPreRender()函数在以下情况下特别有用:
- 在渲染前更改相机的设置,如修改投影矩阵、设置渲染目标等。
- 在渲染前更新材质或纹理。
- 执行一些只需要在渲染开始前执行一次的操作。
- 注意事项:
- 在 OnPreRender()中对相机进行更改可能会影响到当前渲染帧,因此需要小心管理渲染状态。
- 如果在 OnPreRender()中修改了渲染目标,确保在 OnPostRender()中将其恢复到正确状态,以免影响后续渲染。
示例代码:
以下是一个简单的示例代码,展示了如何在 OnPreRender()
中更改相机的背景颜色:
using UnityEngine;
public class PreRenderExample : MonoBehaviour
{
private Camera mainCamera;
private void Start()
{
mainCamera = Camera.main;
}
private void OnPreRender()
{
// 在渲染前将相机背景颜色设置为红色
mainCamera.backgroundColor = Color.red;
}
private void OnPostRender()
{
// 在渲染完成后将相机背景颜色恢复为原始颜色
mainCamera.backgroundColor = Color.clear;
}
}
在这个示例中,我们使用 OnPreRender()函数将主相机的背景颜色设置为红色,在渲染前改变了相机的背景颜色。同时,为了确保渲染完成后将背景颜色恢复到原始状态,我们使用了 OnPostRender()函数。
6、OnPostRender()
OnPostRender()是 在相机完成场景渲染之后调用。在这个函数中,你可以执行一些在渲染结束后需要处理的操作。
下面是关于 OnPostRender()函数的详细介绍:
- 函数签名:
void OnPostRender()
- 触发时机:
- OnPostRender()函数在相机完成场景渲染之后被调用,即在渲染结束后的时刻。这使得你有机会在渲染完成后对渲染结果进行一些后处理工作。
- 使用场景:OnPostRender()函数在以下情况下特别有用:
- 在渲染后对渲染结果进行处理,如渲染纹理、截屏、进行后期处理等。
- 执行一些只需要在渲染结束后执行一次的操作。
- 注意事项:
- 在 OnPostRender()中进行渲染后处理时,需要小心管理渲染状态,确保不会影响到下一帧的渲染。
- 如果在 OnPostRender()中修改了渲染目标或其他渲染状态,需要确保将其恢复到正确状态,以免影响下一帧的渲染。
示例代码:
以下是一个简单的示例代码,展示了如何在 OnPostRender()中进行渲染后处理,将渲染结果保存为一张纹理:
using UnityEngine;
public class PostRenderExample : MonoBehaviour
{
private Camera mainCamera;
private RenderTexture renderTexture;
private void Start()
{
mainCamera = Camera.main;
renderTexture = new RenderTexture(Screen.width, Screen.height, 0);
}
private void OnPostRender()
{
// 将渲染结果保存为纹理
RenderTexture.active = renderTexture;
Texture2D screenshot = new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, false);
screenshot.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0);
screenshot.Apply();
RenderTexture.active = null;
// 保存纹理为文件(这里只是示例,实际使用时可以根据需求进行处理)
byte[] bytes = screenshot.EncodeToPNG();
System.IO.File.WriteAllBytes("Screenshot.png", bytes);
}
}
在这个示例中,我们使用 OnPostRender()函数将渲染结果保存为一张纹理,并将纹理保存为 PNG 文件。这是一个简单的后处理操作,实际使用时可以根据需求进行更复杂的渲染后处理。
7、OnRenderObject()
OnRenderObject是在渲染场景中的每个相机完成后被调用。它允许你在渲染阶段之后、渲染完成后执行一些自定义渲染操作。通常情况下,OnRenderObject`用于绘制自定义的几何图形、特效或其他需要在渲染之后执行的任务。
以下是关于 OnRenderObject函数的详细介绍:
- 函数签名:
void OnRenderObject()
- 调用时机:
- OnRenderObject 函数在每个相机完成渲染后被调用。这意味着无论是主相机还是其他相机,只要渲染完成,就会依次调用各个相机的 OnRenderObject 函数。
- 执行流程:
- 当相机完成渲染后,Unity 会依次调用场景中所有挂载了 OnRenderObject函数的脚本实例的该函数。这使得你可以在渲染阶段之后执行自定义的渲染操作。
- 使用场景:
- OnRenderObject函数适用于各种需要在渲染之后执行的自定义渲染操作,如绘制自定义的几何图形、特效、后处理效果等。
- 注意事项:
-
OnRenderObject函数通常用于执行底层的渲染操作,使用 GL类进行绘制。它并不适用于绘制 UI 元素,如果需要绘制 UI,请使用 OnGUI函数。
-
由于 OnRenderObject在渲染之后执行,因此你可以在这里执行渲染后处理、特效等操作。
- 挂载在相机上:
-
当一个挂载了 OnRenderObject 函数的脚本实例被挂载在相机上时,该函数将在相机渲染完成后被调用。这意味着,当相机完成渲染整个场景后,它会依次调用挂载在相机上的脚本实例的 OnRenderObject 函数。
-
这样的应用场景通常是用于在相机渲染之后执行一些全局性的渲染操作,比如绘制后处理效果、屏幕特效等。由于相机渲染是渲染整个场景的最后阶段,因此在这个时候进行后处理或全屏特效能够确保这些效果应用于整个渲染结果。、
using UnityEngine;
public class CameraRenderScript : MonoBehaviour
{
private void OnRenderObject()
{
// 在相机渲染之后绘制一个全屏矩形
GL.PushMatrix();
GL.LoadOrtho();
GL.Begin(GL.QUADS);
GL.Color(Color.blue);
GL.Vertex3(0, 0, 0);
GL.Vertex3(1, 0, 0);
GL.Vertex3(1, 1, 0);
GL.Vertex3(0, 1, 0);
GL.End();
GL.PopMatrix();
}
}
在这个示例中,挂载在相机上的脚本在相机渲染之后绘制一个全屏的蓝色矩形。因为该脚本挂载在相机上,所以绘制操作只会在相机渲染完成后进行。
- 挂载在普通物体上:
-
当一个挂载了 OnRenderObject 函数的脚本实例被挂载在普通物体上时,该函数将在每个相机渲染完成后被调用。这意味着,无论是主相机还是其他相机,只要它们完成了渲染,就会依次调用挂载在普通物体上的脚本实例的 OnRenderObject 函数。
-
这样的应用场景通常用于在相机渲染之后执行与特定物体相关的渲染操作。例如,你可以在 OnRenderObject 函数中绘制一些附加到特定物体上的几何图形,或者实现与物体相关的自定义渲染逻辑。
using UnityEngine;
public class CustomRenderScript : MonoBehaviour
{
private void OnRenderObject()
{
// 确保只在相机渲染时执行绘制操作
if (Camera.current != null)
{
// 设置材质颜色
Material material = GetComponent<Renderer>().material;
material.color = Color.red;
// 在物体的位置绘制一个立方体
Graphics.DrawMeshNow(GetComponent<MeshFilter>().sharedMesh, transform.position, transform.rotation);
}
}
}
在这个示例中,我们挂载了一个脚本到一个普通的游戏对象上。在 OnRenderObject 函数内部,我们首先通过检查 Camera.current 是否为 null 来确保绘制操作仅在相机渲染时执行。然后,我们通过获取物体的材质并设置其颜色为红色,然后使用 Graphics.DrawMeshNow 函数在物体的位置绘制其网格。
每一次跌倒都是一次成长 每一次努力都是一次进步 |
如果您喜欢本博客,请点赞和分享给更多的朋友,让更多人受益。同时,您也可以关注我的博客,以便及时获取最新的更新和文章。
在未来的写作中,我将继续努力,分享更多有趣、实用的内容。再次感谢大家的支持和鼓励,期待与您在下一篇博客再见!