【知识链】Unity -> Unity脚本 -> 游戏对象 -> 活动状态
【摘要】本文介绍了如何通过编辑器和脚本来访问游戏对象的活动状态,并给出具体的场景示例。
文章目录
- 第一章 引言
- 第二章 在编辑器中设置活动状态
- 2.1. 在编辑器中设置活动状态
- 2.1.1. 停用游戏对象
- 2.1.2. 停用父游戏对象
- 第三章 使用脚本设置活动状态
- 3.1.查看激活状态
- 3.2. 设置对象的活动状态
- 第四章 应用场景
- 4.1.启用/禁用游戏对象
- 4.2.加载和卸载资源
- 4.3.UI控制
- 4.4.状态切换
- 4.5.调试和测试
- 第五章 重点总结
- 第六章 学以致用
- 第七章 参考资料
第一章 引言
游戏对象的活动状态决定了其是否在游戏中被渲染和执行其行为逻辑。这种状态的控制可以让开发者动态地开启或关闭对象,从而实现各种游戏机制,例如暂停、隐藏或临时禁用对象。
第二章 在编辑器中设置活动状态
2.1. 在编辑器中设置活动状态
2.1.1. 停用游戏对象
要暂时从场景中移除游戏对象,可以将该游戏对象标记为非活动状态。
在Inspector窗口并清除GameObject名称左侧的复选框。停用的游戏对象的名称在Hierarchy窗口中会以淡色显示。
2.1.2. 停用父游戏对象
如果您停用父游戏对象,则也会停用其所有子游戏对象,因为停用会覆盖activeSelf所有子游戏对象的设置。当您重新激活父游戏对象时,子游戏对象将返回其原始状态。
注意:如果检查子游戏对象,该activeSelf属性并不总是准确的,因为即使它设置为活动状态,您也可能已将其一个父游戏对象设置为非活动状态。
比如下面的选定的游戏对象(Body)被设置为活动状态,但仍保持非活动状态,直到其父游戏对象被设置为活动状态。
第三章 使用脚本设置活动状态
要通过脚本停用GameObject,请使用SetActive方法。要查看对象是处于活动状态还是非活动状态,请检查activeSelf属性。
要了解场景中的子游戏对象是否处于活动状态,请使用activeInHierarchy属性。
3.1.查看激活状态
(1)activeSelf,只读属性。获取此游戏对象本地活动状态。
该状态用GameObject.SetActive方法进行设置。请注意,即使返回true,GameObject也可能因为父级不活动而处于非活动状态。一旦所有父级都处于活动状态,就会使用此状态。如果你想检查GameObject在场景中是否真正被视为活动,可以使用GameObject.activeInHierarchy。
(2)activeInHierarchy,属性,当前对象在场景中的激活状态。
定义游戏对象在场景中是否处于活动状态。
这可以让你知道GameObject是否在游戏中处于活动状态。如果其GameObject.activeSelf属性已启用,则表示该对象及其所有父级的GameObject.activeSelf属性已启用。
与GameObject.activeSelf不同,它还会检查是否有任何父GameObject影响GameObject的当前活动状态。
当父GameObject停用时,其子对象通常会被标记为活动状态,即使它们不可见,因此根据GameObject.activeSelf,它们仍处于活动状态。但是,GameObject.activeInHierarchy会检查GameObject是否未被其层次结构中的成员停用,从而确保不会发生这种情况。
下面的示例展示了查看两个对象的activeSelf和activeInHierarchy属性。
using UnityEngine;
public class GetActiveStates : MonoBehaviour
{
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.G))
{
Debug.Log($"activeSelf: {gameObject.activeSelf}; activeInHierarchy: {gameObject.activeInHierarchy}");
}
}
}
3.2. 设置对象的活动状态
使用SetActive方法可以激活或停用对象
用法:public void SetActive(bool value)
激活或停用对象,其中true激活GameObject,false停用GameObjet。
GameObject可能因为其父对象不活跃而处于非活动状态。在这种情况下,调用SetActive不会激活它,而只会设置GameObject的本地状态(activeSelf),可以使用GameObject.activeSelft检查该状态。当所有对象都变为活动状态时,Unity便可以使用此状态。
所以如果想通过此方法设置活动状态时,需要将脚本挂载到一个空对象上,并在脚本里将要操作的对象设置公开变量。
停用GameObject会禁用每个组件,包括附加的渲染器、碰撞器、刚体和脚本。例如,Unity将不再调用已停用Update上附加的脚本的方法。OnEnable或OnDisable方法将被调用当GameObject收到SetActive(true) 或 SetActive(false)时。
示例:演示了如何通过SetActive改变游戏对象的活动状态。
using UnityEngine;
public class ActivationControl : MonoBehaviour
{
// 记录对象的初始激活状态
private bool initialActiveState;
void Start()
{
// 保存对象的初始激活状态
initialActiveState = gameObject.activeSelf;
}
void Update()
{
// 检测按键D
if (Input.GetKeyDown(KeyCode.D))
{
// 将对象设置为非激活状态
gameObject.SetActive(false);
}
// 检测按键R
if (Input.GetKeyDown(KeyCode.R))
{
// 重新激活对象
gameObject.SetActive(true);
}
}
}
第四章 应用场景
对游戏对象活动状态的停用和激活,通过可以在以下场景中应用。
4.1.启用/禁用游戏对象
- 应用场景:通过激活或禁用游戏对象来控制它们在场景中的存在和行为。例如,可以在需要时启用敌人对象,或者在玩家离开特定区域时禁用不需要的对象。
- 优点:节省计算资源,提高性能。
4.2.加载和卸载资源
应用场景:在场景切换或资源加载时,可以通过激活状态控制资源的加载和卸载。例如,可以在玩家进入新区域时激活新区域的对象,并禁用旧区域的对象。
优点:管理内存和资源,提高游戏流畅度。
4.3.UI控制
- 应用场景:在UI系统中,通过激活状态控制界面的显示和隐藏。例如,可以在玩家点击按钮时显示或隐藏特定的UI面板。
- 优点:简化UI管理,提升用户体验。
4.4.状态切换
- 应用场景:在游戏中,通过激活状态切换不同的游戏状态或模式。例如,可以在游戏暂停时禁用所有游戏对象,并启用暂停菜单。
- 优点:简化状态管理,提升代码可读性和维护性。
4.5.调试和测试
- 应用场景:在开发过程中,通过激活状态控制对象的存在,用于调试和测试。例如,可以在测试特定功能时禁用其他无关对象。
- 优点:提高开发效率,便于定位问题。
第五章 重点总结
- 要通过脚本停用GameObject,请使用SetActive方法。
- 要查看对象是处于活动状态还是非活动状态,请检查activeSelf属性。
- 要了解场景中的子游戏对象是否处于活动状态,请使用activeInHierarchy属性。
第六章 学以致用
1. 选择题:游戏对象的活动状态(Active State)主要用于控制游戏对象的
A. 渲染顺序
B. 存在与否
C. 静态属性
D. 标签
2. 操作题:设置游戏对象的活动状态
(1)创建一个场景,并在场景中添加一个游戏对象。
(2)使用 Inspector 面板将该对象的活动状态设置为不可见(Inactive)。
(3)运行游戏,验证对象是否消失。
3. 小项目:动态控制游戏对象的活动状态
(1)编写一个脚本,使玩家接近某个道具时,显示该道具;离开时,隐藏该道具。
(2)验证脚本是否能正确控制对象的活动状态。
第七章 参考资料
1.https://docs.unity3d.com/Manual/DeactivatingGameObjects.html
2.https://docs.unity3d.com/ScriptReference/GameObject.html
【学以致用】答案
1.B
2.参见本文第二章节
3.参考代码
using UnityEngine;
public class StatusTask3 : MonoBehaviour
{
private float movementHorizontal, movementVertical;
public float speed = 5.0f;
public GameObject targetObj;
void Update()
{
// 获取鼠标
movementHorizontal = Input.GetAxis("Horizontal");
movementVertical = Input.GetAxis("Vertical");
// 改变物体的位置
transform.position += new Vector3(movementHorizontal, 0, movementVertical) * Time.deltaTime * speed;
float distance = Vector3.Distance(transform.position, targetObj.transform.position);
// 小球与正方体的位置 < 2时,隐藏正方体
if (distance < 2.0f)
{
targetObj.SetActive(false);
}
// 小球与正方体的位置 >= 2时,显示正方体
if (distance >= 2.0f)
{
targetObj.SetActive(true);
}
}
}