当前位置: 首页 > news >正文

【Unity脚本】使用脚本修改游戏对象静态属性

【知识链】Unity -> -> 脚本系统 -> 访问游戏对象 -> 静态属性

【摘要】本文介绍了Unity中游戏对象的静态和动态类型,并说明了如何修改静态属性。
在这里插入图片描述

文章目录

  • 第一章 Unity中的静与动
  • 第二章 静态和动态对象
    • 1. 静态对象(Static Objects)
    • 2. 动态对象(Dynamic Objects)
    • 3. 对比总结
    • 4. 实际应用
  • 第三章 如何修改对象的静态属性
    • 1. 在编辑器中手动设置
    • 2. 在脚本中动态设置(运行时修改)
    • 3. 使用 GameObjectUtility.SetStaticEditorFlags(在编辑器脚本中)
    • 总结
  • 第四章 StaticEditorFlags
    • 1. BatchingStatic
    • 2. NavigationStatic
    • 3. OccludeeStatic
    • 4. OccluderStatic
    • 5. ReflectionProbeStatic
    • 6. OffMeshLinkGeneration
    • 7. LightmapStatic
    • 8. ContributeGI
    • 9. Everything
    • 小结
  • 第五章 运行时修改静态属性
    • 1. 运行时修改 GameObject.isStatic
    • 2. 运行时修改的影响
    • 3. 编辑器中的静态优化
    • 4. 小结
  • 第六章 本文总结
  • 第七章 学以致用
    • 练习题 1:理论题
    • 练习题 2:实践题
  • 第八章 参考资料

第一章 Unity中的静与动

在Unity中,静态(Static)对象和动态(Dynamic)对象有着不同的属性和用途,它们的主要区别在于它们是否能够在运行时移动或变化,以及Unity对它们应用的优化策略。

静态对象是指那些在游戏中不会动的东西,比如地面、建筑物,它们永远固定在那里。Unity可以对这些静态对象进行优化,以提高游戏性能,因为这些东西不会变动。

动态对象则是会动的东西,比如玩家角色、敌人或者会滚动的球。这些对象在游戏运行时会改变位置、大小或方向,Unity需要实时计算它们的变化,所以不能对它们进行像静态对象那样的优化。

简单来说,静态对象是固定不动的,性能更好;动态对象是会动的,但需要更多计算

需要特别说明的是,在构建应用时Unity会对静态对象进行优化。Unity提供了相应的方法来改变对象的静态属性,但这种改变只是在编辑状态时有效,而对于运行时即使设置了静态属性也不会进行相应的优化。当然运行时静态属性的改变也有其他一些用途,将在本文中一一说明。

第二章 静态和动态对象

1. 静态对象(Static Objects)

定义:
静态对象是指在运行时不会移动、缩放或旋转的对象。它们的变换(Transform)属性在游戏运行期间保持不变。

主要特点:

  • 性能优化:

    • 静态批处理(Static Batching):Unity可以对静态对象进行静态批处理,这样可以大大减少绘制调用(Draw Calls),提高渲染性能。静态批处理通过将多个静态对象合并为一个网格(Mesh)来减少渲染开销。
    • 光照贴图(Lightmapping):静态对象可以在编辑器中进行光照贴图烘焙,这意味着光照信息在构建时就被预先计算并存储在贴图中,减少了运行时的光照计算开销。
    • 剔除优化(Occlusion Culling):静态对象可以参与剔除优化,Unity可以预先计算哪些对象在视野之外,从而减少不必要的渲染。
  • 物理计算:

    • 静态对象通常不会参与物理模拟(如刚体、重力等),因为它们的状态不会发生变化。Unity可以对这些对象应用简化的物理计算,从而提高性能。
      场景构建:
    • 静态对象通常用作场景的不可移动部分,例如地形、建筑物、固定障碍物等。它们为游戏世界提供了稳定的背景。

设置方式:

  • 在Unity编辑器中,选择对象后,可以在Inspector面板中勾选 “Static” 复选框,或选择具体的静态类型(如光照静态、导航静态等)。

2. 动态对象(Dynamic Objects)

定义:
动态对象是指在运行时会发生移动、缩放、旋转或其他变化的对象。它们的变换属性在游戏运行期间是可变的。

主要特点:

  • 没有静态优化:

  • 动态对象不会参与静态批处理或光照贴图烘焙,因为它们的状态是动态变化的,无法预先计算和优化。渲染这些对象时需要单独进行处理,可能会增加绘制调用。

  • 物理计算:

    • 动态对象通常是物理模拟的一部分,它们可能受到重力、碰撞、力等影响。例如,玩家角色、敌人、可移动的道具等都属于动态对象。
  • 实时光照:

    • 动态对象通常使用实时光照,这意味着光照计算在运行时进行,适应对象的实时位置和状态变化。
  • 交互性:

    • 动态对象通常是游戏中可交互的部分,它们响应玩家输入或环境变化,如推拉门、移动平台、掉落的物体等。

常见用途:

  • 动态对象用于所有需要在运行时发生变化的场景中,例如玩家角色、NPC、可移动的道具、环境变化的物体等。

3. 对比总结

特性静态对象动态对象
移动/旋转/缩放在运行时不变在运行时会变化
性能优化静态批处理、光照贴图、剔除优化等无静态优化,渲染和物理计算开销较高
物理计算通常不参与物理模拟或使用简化的计算参与物理模拟,响应力、重力和碰撞等
光照光照贴图烘焙(静态)实时光照(动态)
场景用途固定不变的场景元素,如建筑、地形可移动的游戏元素,如角色、道具

4. 实际应用

  • 选择静态对象:如果你确定某个对象在游戏运行时绝不会移动、旋转或缩放,建议将其标记为静态对象,以便Unity应用各种性能优化。
  • 选择动态对象:对于需要在运行时发生变化或与玩家互动的对象,应该保持它们为动态对象。

第三章 如何修改对象的静态属性

在Unity中,可以通过以下几种方法来改变对象的static属性:

1. 在编辑器中手动设置

操作方法:

  1. 在Unity编辑器中,选中需要设置为静态的对象。
  2. 在Inspector面板的顶部,有一个名为"Static"的复选框。
  3. 勾选此复选框后,弹出下拉菜单,你可以选择应用哪些静态标志(例如BatchingStatic、NavigationStatic等)。如果选择了Everything,对象将会被标记为所有类型的静态对象。
    用途:适用于手动设置场景中的对象为静态。

2. 在脚本中动态设置(运行时修改)

操作方法:

  • 通过C#脚本,在运行时修改对象的静态属性。虽然在运行时可以修改,但实际上在运行时修改对象的静态属性并不会触发Unity的静态优化,静态标志的实际作用在编辑器中设置并在构建时生效。

示例代码

GameObject myObject = GameObject.Find("MyObject");
// 设置对象为静态
myObject.isStatic = true;
// 取消对象的静态设置
myObject.isStatic = false;

用途:适用于在特殊情况下根据游戏逻辑临时改变对象的静态状态,但不推荐用于期望的性能优化场景,因为运行时设置isStatic并不会应用静态优化。

3. 使用 GameObjectUtility.SetStaticEditorFlags(在编辑器脚本中)

操作方法:

  • GameObjectUtility.SetStaticEditorFlags方法通常用于编辑器扩展或批量设置多个对象的静态标志。这在你需要创建自定义工具或编辑器脚本时非常有用。

示例代码:

using UnityEditor;
using UnityEngine;public class SetStaticFlagsExample : MonoBehaviour
{[MenuItem("Tools/Set Static Flags")]static void SetStaticFlags(){GameObject myObject = GameObject.Find("MyObject");// 设置对象的静态标志GameObjectUtility.SetStaticEditorFlags(myObject, StaticEditorFlags.BatchingStatic | StaticEditorFlags.NavigationStatic);// 取消所有静态标志GameObjectUtility.SetStaticEditorFlags(myObject, 0);}
}

用途:适用于在编辑器中批量或程序化地设置对象的静态属性,通常在构建场景或优化时使用。
还有一种比较简便的方法
参考:https://discussions.unity.com/t/how-to-set-use-staticeditorflags-cant-seem-to-set-them-from-script/476886/13

public static void SetStaticEditorFlag(GameObject obj, StaticEditorFlags flag,  bool shouldEnable){var currentFlags = GameObjectUtility.GetStaticEditorFlags(obj);if (shouldEnable){currentFlags |= flag;}else{currentFlags &= ~flag;}GameObjectUtility.SetStaticEditorFlags(obj, currentFlags);}

使用方法:
SetStaticEditorFlag(gameObject, StaticEditorFlags.LightmapStatic, true)

总结

  • 在编辑器中手动设置:最常用的方式,适合单独设置或通过Inspector面板批量设置对象为静态。
  • 在脚本中动态设置:可以在运行时修改对象的isStatic属性,但无法利用静态优化。
  • 使用 GameObjectUtility.SetStaticEditorFlags:适合在编辑器脚本中批量设置对象的静态属性,特别适用于需要开发自定义工具或进行批量操作时。

第四章 StaticEditorFlags

StaticEditorFlags 是 Unity 中用来标记一个对象在编辑器中静态属性的枚举类型。通过设置这些标志,你可以决定 Unity 如何在构建时优化这些对象。以下是 StaticEditorFlags 的各个类型及其含义:

1. BatchingStatic

  • 描述:用于静态批处理优化。将对象标记为 BatchingStatic 后,Unity 会在构建时将多个静态对象合并为一个网格,以减少绘制调用(Draw Calls)。
  • 用途:适用于大量的、小而重复的几何体,如建筑物的墙体、柱子等。

2. NavigationStatic

  • 描述:用于导航网格优化。将对象标记为 NavigationStatic 后,Unity 会在导航网格烘焙时将其视为不可移动的障碍物或路径的一部分。
  • 用途:适用于需要在AI路径规划中被视为不可穿越的静态对象,如建筑物、固定的障碍物。

3. OccludeeStatic

  • 描述:用于遮挡剔除优化。标记为 OccludeeStatic 的对象可以被遮挡剔除系统考虑,用于决定哪些对象可以被视野外的其他对象遮挡,从而不进行渲染。
  • 用途:适用于较大的、可能会遮挡其他对象的静态物体,如建筑物或大型场景物体。

4. OccluderStatic

  • 描述:用于遮挡物优化。标记为 OccluderStatic 的对象可以作为遮挡物使用,用于遮挡视野中的其他对象。
  • 用途:适用于可以充当遮挡物的静态对象,如建筑物的墙体、山体等。

5. ReflectionProbeStatic

  • 描述:用于反射探针优化。标记为 ReflectionProbeStatic 的对象会在烘焙反射探针时被认为是静态的,因此反射效果更加精确。
  • 用途:适用于需要高质量反射效果的静态对象,如水面、玻璃、光滑的金属表面等。

6. OffMeshLinkGeneration

  • 描述:用于生成离线网格链接。标记为 OffMeshLinkGeneration 的对象会被用来生成离线网格链接,这些链接可以用作AI路径规划的跳跃、攀爬等动态动作。
  • 用途:适用于场景中需要AI做特殊移动的静态对象,如悬崖边缘、楼梯等。

7. LightmapStatic

  • 描述:用于光照贴图优化。将对象标记为 LightmapStatic 后,Unity 会在光照贴图烘焙时将其纳入考虑,使其接收并投射阴影、反射光等。
  • 用途:适用于需要烘焙光照贴图的静态对象,如地形、建筑物、室内装饰等。

8. ContributeGI

  • 描述:用于全局光照贡献。标记为 ContributeGI 的对象会被全局光照系统纳入计算,从而影响整个场景的全局光照。
  • 用途:适用于希望在全局光照中起作用的静态对象,如地形、建筑物、大型场景物体等。

9. Everything

  • 描述:将对象标记为所有类型的静态对象,即它将同时启用所有上述优化选项。
  • 用途:适用于希望对某个对象应用所有可能的静态优化的情况。

小结

  • StaticEditorFlags 提供了针对不同优化需求的标志,可以根据对象在场景中的角色和用途选择合适的标志进行设置。通过合理使用这些标志,可以显著提高游戏的性能,特别是在涉及大量静态几何体的场景中。

第五章 运行时修改静态属性

你可以在运行时修改GameObject.isStatic属性。不过需要理解的是,虽然这个属性在运行时是可修改的,但它的用途和效果与编辑器中的静态优化不同。

1. 运行时修改 GameObject.isStatic

在运行时,你可以通过脚本来动态改变一个游戏对象的静态状态,例如:

void Start()
{// 将该GameObject设置为静态gameObject.isStatic = true;// 也可以在运行时将其设置为非静态gameObject.isStatic = false;
}

2. 运行时修改的影响

虽然你可以在运行时更改 isStatic 属性,但这不会触发编辑器中的静态优化(如静态批处理、全局光照预计算等),因为这些优化操作通常是在构建或预处理阶段完成的,并且在运行时不再重新计算。
运行时的效果:

  • 碰撞检测:Unity可以基于该属性来优化物理系统的处理。将对象设置为静态后,Unity可以假设该对象不会在运行时移动,从而减少碰撞检测的开销。
  • 渲染优化:在某些情况下,渲染系统可能会基于该属性做出不同的优化决策,比如剔除(Culling)或灯光照射计算。
    然而,这些优化在运行时动态修改 isStatic 属性后,不一定会立刻重新计算或应用。例如,静态批处理通常不会因为在运行时改变 isStatic 而重新触发。

3. 编辑器中的静态优化

在编辑器中使用 StaticEditorFlags 来设置对象为静态时,Unity会在场景加载或构建时应用一系列静态优化,例如:

  • 静态批处理:减少绘制调用。
  • 光照贴图:预计算光照并烘焙到贴图中。
  • 导航网格:计算路径时不考虑静态对象的变化。
    这些优化通常在运行时不会因为修改 isStatic 而重新计算。

4. 小结

运行时修改 isStatic:可以改变对象的静态状态,可能会影响物理引擎和渲染系统的某些优化,但不会触发静态批处理或光照贴图等复杂的静态优化重新计算。
编辑器中的静态优化:通过 StaticEditorFlags 设置,在构建或场景加载时应用广泛的静态优化,但这些设置通常在运行时不再动态改变。
如果你希望在编辑器中批量设置对象为静态,以便在构建时获得最大化的性能优化,建议使用 GameObjectUtility.SetStaticEditorFlags 或在Inspector中手动设置静态标志。

第六章 本文总结

在Unity中将对象设置为静态,主要目的是为了提高性能。我们可以通过GameObject.isStatic和GameObjectUtility.SetStaticEditorFlags方法在编辑器中设置对象的静态属性。当然在运行时通过GameObject.isStatic修改静态属性,虽然不会触发静态优化,但可以在碰撞检测等场景中减少一部分开销。

第七章 学以致用

练习题 1:理论题

问题: 在Unity中,如何使用脚本动态设置一个对象的StaticEditorFlags?简要描述你需要完成的步骤,并编写一个脚本,使得名为"Environment"的GameObject对象被标记为静态物体,并且只开启光照贴图(LightmapStatic)和遮挡物(OccluderStatic)的静态标志。

目标:

  • 测试你对如何在脚本中使用GameObjectUtility.SetStaticEditorFlags的理解。
  • 测试你对静态标志的设置及其用途的掌握程度。

练习题 2:实践题

问题: 创建一个Unity场景,场景中包含两个GameObject对象,分别是House和Tree。使用Unity编辑器手动设置它们的静态属性:

  • House应该被设置为BatchingStatic和LightmapStatic。
  • Tree应该被设置为OccludeeStatic和NavigationStatic。
    接着,编写一个编辑器脚本,通过脚本验证这些对象的静态属性是否被正确设置。如果设置正确,在控制台输出相应的消息。

目标:

  • 测试你对在Unity编辑器中手动设置静态属性的熟悉程度。
  • 测试你对如何在脚本中获取和验证对象静态属性的理解与实践能力。

第八章 参考资料

  1. https://docs.unity3d.com/Manual/StaticObjects.html
  2. https://docs.unity3d.com/ScriptReference/GameObject-isStatic.html
  3. https://docs.unity3d.com/ScriptReference/GameObjectUtility.GetStaticEditorFlags.html
  4. https://discussions.unity.com/t/how-to-set-use-staticeditorflags-cant-seem-to-set-them-from-script/476886/13

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • DHCP DNS 欺骗武器化——实用指南
  • 蓝队技能-应急响应篇钓鱼攻击邮件与文件EML还原蠕虫分析线索定性
  • k8s教程
  • 【C语言】进程和线程详解
  • 日志组件导致的内存溢出问题分析
  • Java 4.2 - MySQL
  • Swift 中的影像魔术:Core Video 的高级应用
  • Swift模块化:构建高效可维护代码的秘诀
  • ArcGIS空间自相关 (Global Moran‘s I)——探究人口空间格局的20年变迁
  • 数据恢复技术-手动修复MBR-/NTFS分区
  • Linux静态库和动态链接库的制作和使用
  • How to stream video in a loop via RTP using ffmpeg?
  • 打造redis缓存组件
  • CAN总线/CAN应用层协议设计,理解并实践仲裁段位域定义
  • vue vite创建项目步骤
  • php的引用
  • CSS盒模型深入
  • CSS居中完全指南——构建CSS居中决策树
  • css系列之关于字体的事
  • Javascripit类型转换比较那点事儿,双等号(==)
  • Joomla 2.x, 3.x useful code cheatsheet
  • Python学习之路16-使用API
  • Spring Cloud(3) - 服务治理: Spring Cloud Eureka
  • Tornado学习笔记(1)
  • Webpack 4 学习01(基础配置)
  • 记录一下第一次使用npm
  • 区块链共识机制优缺点对比都是什么
  • 入口文件开始,分析Vue源码实现
  • 腾讯优测优分享 | Android碎片化问题小结——关于闪光灯的那些事儿
  • 一加3T解锁OEM、刷入TWRP、第三方ROM以及ROOT
  • 怎样选择前端框架
  • 正则表达式小结
  • Java总结 - String - 这篇请使劲喷我
  • 阿里云服务器购买完整流程
  • 翻译 | The Principles of OOD 面向对象设计原则
  • 数据可视化之下发图实践
  • 曾刷新两项世界纪录,腾讯优图人脸检测算法 DSFD 正式开源 ...
  • ​DB-Engines 11月数据库排名:PostgreSQL坐稳同期涨幅榜冠军宝座
  • ​补​充​经​纬​恒​润​一​面​
  • ​批处理文件中的errorlevel用法
  • #如何使用 Qt 5.6 在 Android 上启用 NFC
  • (C语言)共用体union的用法举例
  • (Matlab)使用竞争神经网络实现数据聚类
  • (附源码)spring boot网络空间安全实验教学示范中心网站 毕业设计 111454
  • (附源码)springboot建达集团公司平台 毕业设计 141538
  • (附源码)ssm码农论坛 毕业设计 231126
  • (附源码)计算机毕业设计SSM保险客户管理系统
  • (四)activit5.23.0修复跟踪高亮显示BUG
  • (四)js前端开发中设计模式之工厂方法模式
  • (一)SvelteKit教程:hello world
  • (一)十分简易快速 自己训练样本 opencv级联haar分类器 车牌识别
  • (已解决)Bootstrap精美弹出框模态框modal,实现js向modal传递数据
  • (转)linux自定义开机启动服务和chkconfig使用方法
  • (转)Scala的“=”符号简介
  • .NET MVC第五章、模型绑定获取表单数据