【Unity脚本】使用脚本操作游戏对象的组件

c 复制代码
【知识链】Unity -> Unity脚本 -> 游戏对象 -> 组件
【知识链】Unity -> Unity界面 -> Inspector

摘要】本文介绍如何使用脚本添加、删除组件,以及如何访问组件

文章目录

  • 引言
  • [第一章 游戏对象与组件](#第一章 游戏对象与组件)
    • 1.1什么是组件?
    • [1.2 场景、游戏对象与组件的关系](#1.2 场景、游戏对象与组件的关系)
  • [第二章 在Inpector中操作组件](#第二章 在Inpector中操作组件)
    • [2.1 添加组件](#2.1 添加组件)
    • [2.2 删除组件](#2.2 删除组件)
    • [2.3 修改组件](#2.3 修改组件)
    • [2.4 变换组件](#2.4 变换组件)
  • [第三章 使用脚本操作组件](#第三章 使用脚本操作组件)
    • [3.1 添加组件](#3.1 添加组件)
    • [3.2 删除组件](#3.2 删除组件)
    • [3.3 访问组件](#3.3 访问组件)
  • [第四章 应用场景](#第四章 应用场景)
  • [第五章 总结](#第五章 总结)
  • [第六章 学以致用](#第六章 学以致用)
  • [第七章 参考资料](#第七章 参考资料)

引言

在现代游戏开发中,灵活操作游戏对象的组件已经成为提升游戏体验的重要手段。通过脚本动态添加、删除、修改组件以及切换状态和生成特效,开发者可以创建更加丰富和互动的游戏世界。这种方法不仅提高了游戏的可玩性和视觉效果,还使游戏的逻辑更加清晰和易于维护。在本文中,我们将深入探讨如何利用脚本来操作游戏对象的组件,并通过实际案例来展示其应用场景和实现方法。无论你是新手开发者还是有经验的游戏设计师,希望这篇文章能为你提供有价值的参考和启发。

第一章 游戏对象与组件

1.1什么是组件?

在Unity中,组件(Component)是构建游戏对象(GameObject)的基本单元。它们赋予游戏对象各种功能和行为。可以将组件看作是游戏对象的特性或能力,例如移动、渲染、物理交互等。

要在 Inspector 窗口中查看附加到 GameObject 的组件列表,请在 Hierarchy 窗口或 Scene 视图中选择一个 GameObject。

1.2 场景、游戏对象与组件的关系

Unity的核心设计架构可以概括为组件式架构,这种架构强调将功能拆分为独立的模块,这些模块可以自由组合和复用,以构建复杂的游戏对象和场景。

对于核心概念场景、游戏对象和组件三者之间的关系。

(1)场景是游戏的基本单位,它包含了游戏世界中的所有内容。每个场景可以看作是一个容器,包含有多个游戏对象和其相关的组件。

(2)游戏对象是Unity中所有实体的基础,它们是场景中存在的对象的抽象。游戏对象本身是一个空的容器,但通过添加不同的组件,游戏对象可以具有不同的功能和行为。

(3)组件是游戏对象的功能单元。每个组件负责实现特定的功能,例如渲染、物理、音频等。通过组合不同的组件,一个游戏对象可以实现复杂的行为。例如,一个游戏对象可以同时拥有渲染组件(用于显示)、物理组件(用于碰撞检测)和音频组件(用于播放声音)。

所以,三者之间是整体与部分的包含关系。场景由游戏对象组成,游戏对象由组件构成。

第二章 在Inpector中操作组件

2.1 添加组件

方法一:可以通过Component菜单向所选游戏对象添加组件。比如要添加Rigidbody组件,先在Hierarchy或Scene中选择一个游戏对象,然后从菜单中选择Component > Physics > Rigidbody。Inspector会显示Rigidbody的属性。

方法二:还可以在组件浏览器中添加组件。要打开组件浏览器,在检查器中选择"Add Component" 。

您可以在浏览器中按类别浏览组件,或者使用搜索框按名称查找组件。

您可以将任意数量或任意组合的组件附加到单个 GameObject。某些组件与其他组件结合使用效果最佳。例如,Rigidbody 与 Collider 配合使用。

有些组件之间是互斥的,比如Collider与Rigidbody 2D不能同时使用。

2.2 删除组件

右键单击组件的标题部分可以显示上下文菜单,也可从Inspector窗口组件面板右上角的菜单 (⋮) 中获得。

选择"Remove Component",从 GameObject 中移除组件。注意:某些组件组合相互依赖(Hinge Joint仅在附加到Rigidbody时才有效);如果您尝试移除其他组件所依赖的组件,则会显示一条警告消息。

2.3 修改组件

当您将组件附加到 GameObject 时,组件的属性包含默认值。您可以在构建游戏时在编辑器中编辑这些值,也可以在运行游戏时在脚本中编辑这些值。

属性主要有两种类型:值和引用

您可以在Inspector中编辑值属性。值有多种类型,包括文本、切换按钮和下拉菜单。

对于引用属性,您可以将文件从 Project 视图拖到属性中,或者使用属性上的对象选择器(圆圈图标)。引用属性可以引用其他类型的组件、游戏对象或资产。

比如下图显示了Transform组件的Position属性是值类型,而Mesh Renderer组件中Material的值则是引用类型。

2.4 变换组件

Transform组件决定了 GameObject 的位置、旋转、缩放和父级状态。你可以将许多组件附加到 GameObject,但每个 GameObject 必须有且只有一个 Transform 组件你无法移除 Transform 或创建没有 Transform 组件的 GameObject

要创建空 GameObject,请选择GameObject > Create Empty 。当您选择新的 GameObject 时,Inspector 会显示具有默认值的 Transform 组件。

更多参考:https://docs.unity3d.com/cn/current/Manual/class-Transform.html

第三章 使用脚本操作组件

3.1 添加组件

添加组件的方法是:public T AddComponent()。比如:

csharp 复制代码
 SphereCollider sc = gameObject.AddComponent<SphereCollider>() as SphereCollider;

示例:添加Rigidbody组件

1.在Project中Asset文件夹,创建一个脚本AddComponentDemo.cs,内容如下。

2.菜单GameObject -> 3D Object -> Cube,创建一个Cube,将脚本AddComponentDemo.cs拖入到这个Cube上。

3.点击Play运行,在Game窗口中,按键盘上的A。在Hierarchy中选中Cube,可以看到Rigidbody组件已经添加成功。Game窗口中,Cube因为有了Rigidbody开始下落。

csharp 复制代码
1.using UnityEngine;
2.
3.public class AddComponentDemo : MonoBehaviour
4.{
5.    Rigidbody rb = null;
6.
7.    void Update()
8.    {
9.        if (Input.GetKeyDown(KeyCode.A))
10.        {
11.            AddComponentTest();
12.        }
13.    }
14.
15.    void AddComponentTest()
16.    {
17.        rb = gameObject.AddComponent<Rigidbody>();
18.
19.        if(rb != null )
20.        {
21.            Debug.Log("已添加Rigidbody组件");
22.        }
23.    }
}

3.2 删除组件

(1)Destroy方法

此方法可以删除游戏对象、组件或资产。例如:

csharp 复制代码
public static void Destroy(Object obj, float t = 0.0F);

对象obj在当前更新循环结束后立即销毁,t如果指定了时间,则在几秒后销毁。如果obj是组件,则此方法从GameObject中移除组件并销毁它。如果obj是GameObject,则它会销毁GameObject 、其所有组件以及GameObject的所有变换子项。实际对象销毁总是延迟到当前更新循环之后,但总是在渲染之前完成。

注意:销毁 MonoBehaviour 脚本时,在移除脚本之前会调用OnDisable和OnDestroy。

示例:在上面添加组件的基础上,我们增加一个功能:按D键删除Rigidbody组件,完整代码如下。

csharp 复制代码
1.using UnityEngine;
2.
3.public class AddComponentDemo : MonoBehaviour
4.{
5.    Rigidbody rb = null;
6.
7.    void Update()
8.    {
9.        if (Input.GetKeyDown(KeyCode.A))
10.        {
11.            AddComponentTest();
12.        }
13.
14.        if(Input.GetKeyDown(KeyCode.D))
15.        {
16.            RemoveComponentTest();
17.        }
18.    }
19.
20.    void AddComponentTest()
21.    {
22.        rb = gameObject.AddComponent<Rigidbody>();
23.
24.        if(rb != null )
25.        {
26.            Debug.Log("已添加Rigidbody组件");
27.        }
28.    }
29.
30.    void RemoveComponentTest()
31.    {
32.        Destroy(rb);
33.         Debug.Log("已移除Rigidbody组件");
34.    }
35.}

(2)DestroyImmidiate方法

csharp 复制代码
public static void DestroyImmediate(Object obj, bool allowDestroyingAssets = false);

立即销毁该对象obj。不过强烈建议使用 Destroy方法。
此函数应仅在编写编辑器代码时使用,因为延迟销毁永远不会在编辑模式下调用。在游戏代码中,应改用Object.Destroy。销毁始终会延迟(但在同一帧内执行)。请谨慎使用此函数,因为它可能会永久销毁资产!另请注意,永远不应迭代数组并销毁正在迭代的元素。这将导致严重问题(作为一般编程实践,而不仅仅是在 Unity 中)。

3.3 访问组件

我们先来看一下访问组件的方法有哪些:

(1)public T GetComponent()

获取对指定 GameObject上T类型组件的引用。

(2)public T GetComponentInChildren(bool includeInactive = false)

获取对指定 GameObject 或 GameObject 的任何子项上类型 T 组件的引用。

(3)public T GetComponentInParent(bool includeInactive = false)

获取对指定 GameObject 或 GameObject 的任何父级上类型 T 组件的引用。

(4)public T[] GetComponents()

获取对指定 GameObject 上所有类型 T 组件的引用。

(5)public T[] GetComponentsInChildren(bool includeInactive)

获取对指定 GameObject 上所有类型 T 的组件以及该 GameObject 的任何子组件的引用。

(6)public T[] GetComponentsInParent(bool includeInactive)

获取对指定 GameObject 上所有类型 T 的组件以及该 GameObject 的任何父级的引用。

以上方法中的参数includeInactive是个bool值,当为true时表示会获取非激活状态对象上的符合条件的组件,默认为false。

在Unity 2022.3之后,还增加了下面三个方法,主要是用于访问Inspector里的组件

(7)public Component GetComponentAtIndex(int index)

获取对指定 GameObject 上特定索引处的组件的引用。

(8)public int GetComponentCount() :返回此 GameObject 上的组件数量。

(9)public int GetComponentIndex(Component component)

获取指定 GameObject 上指定组件的索引。

接下来就以GetComponen()为例详细说明一下使用方法。

  • 返回值:T,如果找到 该类型的组件,则为其引用,否则为null。
  • 方法描述:T获取对指定 GameObject类型组件的引用。

此方法的典型用法是在对脚本所在 GameObject 以外的其他 GameObject 的引用上调用它。例如:

csharp 复制代码
myResults = otherGameObject.GetComponent<ComponentType>()

但是,如果在 MonoBehaviour 类中编写代码,则可以省略前面的 GameObject 引用,以便从脚本所附加到的同一GameObject中获取组件。在这种情况下,实际上是在调用Component.GetComponent,因为脚本本身是一种组件,但结果与引用GameObject本身一样。例如:

csharp 复制代码
myResults = GetComponent<ComponentType>()

GetComponent仅返回在调用它的GameObject上找到的第一个匹配组件,并且检查组件的顺序未定义。因此,如果有多个指定类型可以匹配,并且需要找到一个特定的类型,则应使用Component.GetComponents并检查返回的组件列表以识别所需的组件。

通过这些方法获取到组件后,就可以对组件的属性进行修改。

比如我们获取到Rigidbody组件后,改变其mass属性的值。

csharp 复制代码
Rigidbody rb = GetComponent<Rigidbody>();
rb.mass = 0.5f;

第四章 应用场景

在 Unity 游戏开发过程中,使用脚本来添加、删除和修改组件是常见的需求,这种操作可以动态地改变游戏对象的行为和外观,适应各种游戏逻辑和需求。以下是一些具体的应用场景和实际案例:

  1. 动态添加组件

    案例:角色拾取物品

    在游戏中,角色可以拾取不同的装备(如武器、防具)。当角色拾取物品时,可能需要为角色动态添加新的组件以增加新功能。

  2. 动态删除组件

    案例:移除临时效果

    在一些游戏中,角色可能会受到临时效果(如加速、减速)。当这些效果过期时,需要移除相应的组件。

  3. 动态修改组件

    案例:改变角色属性

    在游戏中,角色可能会因为等级提升、技能效果等原因需要修改其属性。例如,角色升级后增加攻击力。

  4. 动态切换状态

    案例:切换敌人AI状态

    在复杂的AI系统中,敌人的行为可能需要根据玩家的动作进行切换。例如,敌人从巡逻状态切换到追击状态。

  5. 动态生成特效

    案例:生成粒子特效

    在游戏中,某些事件(如角色释放技能、敌人死亡)可能需要生成特效。可以通过脚本动态添加粒子系统组件。

第五章 总结

学习就是从薄到厚,再从厚到薄的过程。

今天学习的重点可以总结为两点:

1.场景、游戏对象和组件之间是包含 关系

2.掌握对组件的操作方法
(1)添加组件:AddComponent()
(2)删除组件:Destroy(component)
(3)编辑组件:GetComponent()

第六章 学以致用

下面就通过任务来刻意训练一下刚学到的知识吧。

在场景中创建一个平面(Plane)和一个球体(Sphere),将球体的位置设置为 (0,1,0),并删除场景中的Directional Light。当你完成任务后就可以将脚本挂载到球体进行测试。

任务1:手动添加和删除组件

运行的效果:

(1)按A时添加Light组件。

(2)按G时将Light组件的color设置为红色,range设置3,intensity设置为10。

(3)按D时删除Light组件。

(4)通过Log显示添加和删除的结果。

最终运行效果如下:

第七章 参考资料

  1. https://docs.unity3d.com/cn/current/Manual/GameObjects.html
  2. https://docs.unity3d.com/cn/current/Manual/UsingComponents.html
  3. https://docs.unity3d.com/2021.3/Documentation/ScriptReference/Component.html

【学以致用】参考答案:

任务1:

相关推荐
DvLee10241 小时前
UnityGLTF 材质创建与赋值流程
unity·材质
勿忘初心912 小时前
游戏手柄遥控越疆协作机器人[一]
游戏·机器人
全栈软件开发2 小时前
萌猫 合并卡牌 RPG抽卡游戏 Unity3D休闲益智游戏源码完整项目
游戏·unity源码
HahaGiver6664 小时前
从0到1做一个“字母拼词”Unity小游戏(含源码/GIF)- 字母拼词正确错误判断
unity·游戏引擎·游戏程序
远程软件小帮手16 小时前
好用的云电脑!手机怎么用UU远程云电脑玩电脑游戏?
运维·服务器·游戏·电脑
yingxiao88817 小时前
挖掘百亿“数字热土”!解读印度游戏与媒体娱乐的高速增长
游戏·娱乐·媒体
一个小狼娃1 天前
Android集成Unity避坑指南
android·游戏·unity
极客柒1 天前
Unity 协程GC优化记录
java·unity·游戏引擎
黄思搏1 天前
Unity SpriteRenderer 进度条 Shader 实现
unity·游戏引擎
猫屋小鱼丸1 天前
手把手教你在unity中实现一个视觉小说系统(一)
unity