2.5 事件函数


文档摘要

2.5 事件函数 (OnCollisionEnter, OnTriggerEnter, OnMouseDown 等) 二、C# 脚本编程父章节领域 - 2.5 事件函数 (OnCollisionEnter, OnTriggerEnter, OnMouseDown 等) 2.5.1 事件函数概述 事件函数,顾名思义,是在特定事件发生时被 Unity 引擎自动调用的函数。这些事件涵盖了游戏运行的各个方面,例如物理碰撞、触发器交互、鼠标点击、渲染更新等等。使用事件函数,开发者无需手动轮询检测事件是否发生,引擎会在事件发生时主动通知脚本,并执行预先定义好的代码逻辑。这种事件驱动的编程模式极大地简化了游戏逻辑的编写,提高了代码的效率和可读性。

2.5 事件函数 (OnCollisionEnter, OnTriggerEnter, OnMouseDown 等)

二、C# 脚本编程父章节领域 - 2.5 事件函数 (OnCollisionEnter, OnTriggerEnter, OnMouseDown 等)

2.5.1 事件函数概述

事件函数,顾名思义,是在特定事件发生时被 Unity 引擎自动调用的函数。这些事件涵盖了游戏运行的各个方面,例如物理碰撞、触发器交互、鼠标点击、渲染更新等等。使用事件函数,开发者无需手动轮询检测事件是否发生,引擎会在事件发生时主动通知脚本,并执行预先定义好的代码逻辑。这种事件驱动的编程模式极大地简化了游戏逻辑的编写,提高了代码的效率和可读性。

Unity 提供了丰富的事件函数,它们都以特定的命名规则和参数结构存在。通常,事件函数都以 On 开头,后面跟上事件的名称,例如 OnCollisionEnter 表示碰撞进入事件,OnTriggerEnter 表示触发器进入事件,OnMouseDown 表示鼠标按下事件。

事件函数通常附加在 MonoBehaviour 脚本上,并挂载到 GameObject 上才能生效。当游戏对象所关联的事件发生时,引擎会自动调用脚本中相应的事件函数。

2.5.2 物理碰撞事件函数:OnCollisionEnter, OnCollisionStay, OnCollisionExit

物理碰撞事件函数用于处理游戏对象之间发生物理碰撞的情况。Unity 的物理引擎负责检测和处理碰撞,并在碰撞的不同阶段触发相应的事件函数。

2.5.2.1 OnCollisionEnter

定义: void OnCollisionEnter(Collision collision)

触发时机: 当依附脚本的 GameObjectCollider 组件与其他 GameObjectCollider 组件开始发生物理碰撞时,OnCollisionEnter 函数会被调用一次。

参数: Collision collision 参数包含了碰撞相关的详细信息,例如:

  • collision.contacts: 一个 ContactPoint[] 数组,包含了碰撞接触点的详细信息,例如接触点的位置、法线方向等。

  • collision.collider: 碰撞到的另一个 GameObjectCollider 组件。

  • collision.gameObject: 碰撞到的另一个 GameObject

  • collision.rigidbody: 碰撞到的另一个 GameObjectRigidbody 组件 (如果存在)。

  • collision.transform: 碰撞到的另一个 GameObjectTransform 组件。

  • collision.relativeVelocity: 相对速度。

代码实践:

using UnityEngine; public class CollisionDetection : MonoBehaviour { void OnCollisionEnter(Collision collision) { Debug.Log("碰撞发生!碰撞对象名称: " + collision.gameObject.name); // 获取碰撞点信息 if (collision.contacts.Length > 0) { ContactPoint contact = collision.contacts[0]; Debug.Log("第一个碰撞点位置: " + contact.point); Debug.Log("第一个碰撞点法线方向: " + contact.normal); } // 判断碰撞对象标签 if (collision.gameObject.CompareTag("Enemy")) { Debug.Log("碰撞到敌人!"); // 在这里处理与敌人的碰撞逻辑,例如扣血、触发特效等 } // 获取碰撞对象的Rigidbody并施加力 Rigidbody otherRigidbody = collision.rigidbody; if (otherRigidbody != null) { otherRigidbody.AddForce(Vector3.up * 10f, ForceMode.Impulse); // 向上施加一个冲量 } } }

内容详解:

  1. 触发条件: OnCollisionEnter 函数只有在两个 GameObjectCollider 组件都启用了碰撞检测,并且至少其中一个 GameObject 带有 Rigidbody 组件时才会被触发。 这是因为物理碰撞需要物理引擎的参与,而 Rigidbody 组件是使 GameObject 参与物理模拟的关键。 如果两个 GameObject 都没有 Rigidbody 组件,即使它们的 Collider 组件相交,也不会触发物理碰撞事件。

  2. 参数使用: Collision collision 参数提供了丰富的碰撞信息,可以用于实现各种复杂的碰撞逻辑。 例如,通过 collision.contacts 可以获取精确的碰撞点信息,用于实现粒子特效、碰撞火花等视觉效果。 通过 collision.gameObjectcollision.collider 可以访问碰撞对象的属性和组件,进行进一步的逻辑判断和操作。 通过 collision.rigidbody 可以获取碰撞对象的刚体组件,并对其施加力、改变速度等。

  3. 应用场景: OnCollisionEnter 常用于处理需要精确物理碰撞响应的场景,例如:

    • 子弹击中目标: 检测子弹与敌人或场景物体的碰撞,并根据碰撞信息计算伤害、触发击中特效。

    • 角色与环境交互: 检测角色与地面、墙壁等环境物体的碰撞,用于实现角色移动、跳跃、攀爬等动作。

    • 物体破碎: 检测物体受到足够大的冲击力时,触发破碎效果。

    • 物理推动: 检测物体之间的碰撞,并根据碰撞信息计算物理推动力,实现物体之间的相互作用。

2.5.2.2 OnCollisionStay

定义: void OnCollisionStay(Collision collision)

触发时机: 当依附脚本的 GameObjectCollider 组件与其他 GameObjectCollider 组件持续保持物理碰撞状态时,OnCollisionStay 函数会在每个物理引擎更新帧被持续调用。

参数: Collision collision 参数与 OnCollisionEnter 的参数相同,包含碰撞相关的详细信息。

代码实践:

using UnityEngine; public class CollisionStayDetection : MonoBehaviour { void OnCollisionStay(Collision collision) { Debug.Log("持续碰撞中... 碰撞对象名称: " + collision.gameObject.name); // 可以持续获取碰撞信息,例如持续施加力 Rigidbody otherRigidbody = collision.rigidbody; if (otherRigidbody != null) { otherRigidbody.AddForce(Vector3.right * 0.5f); // 持续向右施加力 } } }

内容详解:

  1. 触发条件: OnCollisionStay 的触发条件与 OnCollisionEnter 类似,需要两个 GameObjectCollider 组件都启用碰撞检测,并且至少其中一个带有 Rigidbody 组件。

  2. 持续调用: OnCollisionStay 的关键在于它的持续性,只要碰撞双方的 Collider 仍然保持相交状态,该函数就会在每个物理引擎更新帧被调用。物理引擎更新帧的频率由 Unity 的物理设置决定,通常为每秒多次。

  3. 应用场景: OnCollisionStay 适用于需要持续性碰撞响应的场景,例如:

    • 持续伤害区域: 角色进入一个持续伤害区域 (例如毒气区域、火焰区域) 时,OnCollisionStay 可以持续检测角色是否还在区域内,并持续扣血。

    • 摩擦力模拟: 当物体在地面上滑动时,OnCollisionStay 可以持续模拟摩擦力,使物体逐渐减速停止。

    • 物体吸附: 当两个物体碰撞并需要吸附在一起时,OnCollisionStay 可以持续调整物体的位置和方向,保持吸附状态。

2.5.2.3 OnCollisionExit

定义: void OnCollisionExit(Collision collision)

触发时机: 当依附脚本的 GameObjectCollider 组件与其他 GameObjectCollider 组件结束物理碰撞时,OnCollisionExit 函数会被调用一次。

参数: Collision collision 参数与 OnCollisionEnterOnCollisionStay 的参数相同,包含碰撞相关的详细信息。

代码实践:

using UnityEngine; public class CollisionExitDetection : MonoBehaviour { void OnCollisionExit(Collision collision) { Debug.Log("碰撞结束!碰撞对象名称: " + collision.gameObject.name); // 在碰撞结束时执行一些清理或重置操作,例如停止持续伤害、移除吸附效果等 } }

内容详解:

  1. 触发条件: OnCollisionExit 的触发条件同样需要物理碰撞的基础,即两个 GameObjectCollider 组件都启用碰撞检测,并且至少其中一个带有 Rigidbody 组件。

  2. 碰撞结束标志: OnCollisionExit 函数标志着物理碰撞的结束。 当两个碰撞的 GameObject 分离,不再发生物理接触时,OnCollisionExit 会被调用。

  3. 应用场景: OnCollisionExit 常用于处理碰撞结束后的逻辑,例如:

    • 离开伤害区域: 角色离开持续伤害区域时,停止扣血效果。

    • 解除吸附: 当吸附状态结束时,解除吸附效果,使物体可以自由移动。

    • 统计碰撞次数: 记录碰撞开始和结束的次数,用于统计碰撞事件。

    • 触发音效或特效: 在碰撞结束时播放特定的音效或特效。

2.5.2.4 物理碰撞事件函数总结

事件函数 触发时机 持续性
OnCollisionEnter 碰撞开始时 (仅触发一次)
OnCollisionStay 碰撞持续期间 (每物理引擎更新帧触发)
OnCollisionExit 碰撞结束时 (仅触发一次)

Graph TD 图示物理碰撞事件流程:

2.5.3 触发器事件函数:OnTriggerEnter, OnTriggerStay, OnTriggerExit

触发器事件函数用于处理 GameObjectCollider 组件被设置为 Is Trigger 属性时与其他 Collider 组件发生的交互。触发器与物理碰撞不同,它不会产生物理碰撞响应,而是仅仅用于检测进入、停留和离开触发器区域的事件。

2.5.3.1 OnTriggerEnter

定义: void OnTriggerEnter(Collider other)

触发时机: 当依附脚本的 GameObjectCollider 组件(设置为 Is Trigger) 与另一个 GameObjectCollider 组件开始发生重叠时,OnTriggerEnter 函数会被调用一次。

参数: Collider other 参数包含了触发到的另一个 GameObjectCollider 组件信息。

  • other: 触发到的另一个 GameObjectCollider 组件。

  • other.gameObject: 触发到的另一个 GameObject

  • other.transform: 触发到的另一个 GameObjectTransform 组件。

  • other.attachedRigidbody: 触发到的另一个 GameObjectRigidbody 组件 (如果存在)。

代码实践:

using UnityEngine; public class TriggerDetection : MonoBehaviour { void OnTriggerEnter(Collider other) { Debug.Log("触发器进入!触发对象名称: " + other.gameObject.name); // 判断触发对象标签 if (other.gameObject.CompareTag("Player")) { Debug.Log("玩家进入触发区域!"); // 在这里处理玩家进入触发区域的逻辑,例如打开门、显示提示信息等 } // 获取触发对象的脚本组件并调用方法 PlayerController playerController = other.GetComponent<PlayerController>(); if (playerController != null) { playerController.IncreaseScore(10); // 调用玩家脚本中的加分方法 } } }

内容详解:

  1. 触发条件: OnTriggerEnter 函数只有在依附脚本的 GameObjectCollider 组件被设置为 Is Trigger 属性时才会被触发。 触发器事件不需要 Rigidbody 组件参与,只要两个 GameObjectCollider 组件都启用了碰撞检测 (即使其中一个或两个都没有 Rigidbody ),并且其中一个的 Collider 设置为 Is Trigger, 就可以触发触发器事件。

  2. 参数使用: Collider other 参数提供了触发对象的信息,可以用于识别触发对象、访问其组件和属性。 与 Collision collision 参数相比,Collider other 参数的信息相对简单,因为它只关注触发对象本身,而不包含具体的碰撞点和物理碰撞信息。

  3. 应用场景: OnTriggerEnter 常用于实现非物理碰撞的触发逻辑,例如:

    • 区域检测: 检测角色是否进入特定区域 (例如传送门区域、奖励区域、剧情触发区域)。

    • 物品拾取: 当角色进入物品的触发器区域时,自动拾取物品。

    • 陷阱触发: 当敌人进入陷阱的触发器区域时,触发陷阱效果。

    • UI 提示: 当玩家靠近某个交互对象时,显示 UI 提示信息。

2.5.3.2 OnTriggerStay

定义: void OnTriggerStay(Collider other)

触发时机: 当依附脚本的 GameObjectCollider 组件(设置为 Is Trigger) 与另一个 GameObjectCollider 组件持续保持重叠状态时,OnTriggerStay 函数会在每个物理引擎更新帧被持续调用。

参数: Collider other 参数与 OnTriggerEnter 的参数相同,包含触发到的另一个 GameObjectCollider 组件信息。

代码实践:

using UnityEngine; public class TriggerStayDetection : MonoBehaviour { void OnTriggerStay(Collider other) { Debug.Log("触发器持续停留... 触发对象名称: " + other.gameObject.name); // 可以持续执行触发逻辑,例如持续治疗、持续检测状态等 if (other.gameObject.CompareTag("Player")) { // 持续治疗玩家 PlayerHealth playerHealth = other.GetComponent<PlayerHealth>(); if (playerHealth != null) { playerHealth.Heal(1); // 每帧治疗 1 点生命值 } } } }

内容详解:

  1. 触发条件: OnTriggerStay 的触发条件与 OnTriggerEnter 相同,需要依附脚本的 GameObjectCollider 组件设置为 Is Trigger 属性。

  2. 持续调用: OnTriggerStayOnCollisionStay 类似,它也是一个持续调用的事件函数。 只要触发对象仍然停留在触发器区域内,OnTriggerStay 就会在每个物理引擎更新帧被调用。

  3. 应用场景: OnTriggerStay 适用于需要持续性触发响应的场景,例如:

    • 持续治疗区域: 角色停留在治疗区域内时,持续回复生命值。

    • 加速区域: 角色停留在加速区域内时,持续增加移动速度。

    • 持续检测状态: 持续检测触发对象的状态,并根据状态变化执行相应的逻辑。

2.5.3.3 OnTriggerExit

定义: void OnTriggerExit(Collider other)

触发时机: 当依附脚本的 GameObjectCollider 组件(设置为 Is Trigger) 与另一个 GameObjectCollider 组件结束重叠时,OnTriggerExit 函数会被调用一次。

参数: Collider other 参数与 OnTriggerEnterOnTriggerStay 的参数相同,包含触发到的另一个 GameObjectCollider 组件信息。

代码实践:

using UnityEngine; public class TriggerExitDetection : MonoBehaviour { void OnTriggerExit(Collider other) { Debug.Log("触发器离开!触发对象名称: " + other.gameObject.name); // 在触发器离开时执行一些清理或重置操作,例如关闭门、隐藏提示信息等 if (other.gameObject.CompareTag("Player")) { Debug.Log("玩家离开触发区域!"); // 关闭门或隐藏提示信息 } } }

内容详解:

  1. 触发条件: OnTriggerExit 的触发条件与 OnTriggerEnterOnTriggerStay 相同,需要依附脚本的 GameObjectCollider 组件设置为 Is Trigger 属性。

  2. 触发结束标志: OnTriggerExit 函数标志着触发器交互的结束。 当触发对象离开触发器区域,不再与触发器 Collider 重叠时,OnTriggerExit 会被调用。

  3. 应用场景: OnTriggerExit 常用于处理触发器交互结束后的逻辑,例如:

    • 离开区域效果移除: 角色离开加速区域或治疗区域时,移除加速或治疗效果。

    • 关闭门或隐藏提示: 当玩家离开交互区域时,关闭门或隐藏 UI 提示信息。

    • 重置状态: 当敌人离开陷阱区域时,重置陷阱状态。

2.5.3.4 触发器事件函数总结

事件函数 触发时机 持续性
OnTriggerEnter 触发器进入时 (仅触发一次)
OnTriggerStay 触发器持续停留期间 (每物理引擎更新帧触发)
OnTriggerExit 触发器离开时 (仅触发一次)

Graph TD 图示触发器事件流程:

2.5.4 鼠标事件函数:OnMouseDown, OnMouseUp, OnMouseEnter, OnMouseExit, OnMouseOver

鼠标事件函数用于处理用户鼠标与 GameObject 交互的情况。Unity 提供了多个鼠标事件函数,涵盖了鼠标按下、抬起、进入、离开、悬停等不同的鼠标动作。

2.5.4.1 OnMouseDown

定义: void OnMouseDown()

触发时机: 当鼠标指针在 GameObjectCollider 组件上按下鼠标左键时,OnMouseDown 函数会被调用一次。

代码实践:

using UnityEngine; public class MouseClickDetection : MonoBehaviour { void OnMouseDown() { Debug.Log("鼠标左键按下!点击对象名称: " + gameObject.name); // 改变对象的颜色 GetComponent<Renderer>().material.color = Color.red; // 执行其他点击事件逻辑,例如播放音效、触发动画、打开UI界面等 } }

内容详解:

  1. 触发条件: OnMouseDown 函数需要依附脚本的 GameObject 具有 Collider 组件。 当鼠标指针位于 GameObjectCollider 上,并且按下鼠标左键时,OnMouseDown 函数会被调用。

  2. 鼠标左键: OnMouseDown 仅响应鼠标左键的按下事件。 如果需要响应鼠标右键或中键,需要使用其他输入事件检测方法 (例如 Input.GetMouseButtonDown)。

  3. 应用场景: OnMouseDown 常用于实现简单的鼠标点击交互,例如:

    • 按钮点击: 模拟 UI 按钮的点击效果。

    • 对象选择: 点击游戏场景中的对象进行选择。

    • 物体交互: 点击物体触发交互事件 (例如打开门、拿起物品)。

    • 游戏控制: 使用鼠标点击进行游戏操作 (例如射击、移动角色)。

2.5.4.2 其他鼠标事件函数

除了 OnMouseDown,Unity 还提供了其他常用的鼠标事件函数,用于处理不同的鼠标交互场景:

  • OnMouseUp(): 鼠标左键在 GameObjectCollider 组件上抬起时调用。

  • OnMouseEnter(): 鼠标指针进入 GameObjectCollider 组件时调用 (仅触发一次)。

  • OnMouseExit(): 鼠标指针离开 GameObjectCollider 组件时调用 (仅触发一次)。

  • OnMouseOver(): 鼠标指针悬停在 GameObjectCollider 组件上时,在每个帧被持续调用。

代码实践 (示例 OnMouseEnter 和 OnMouseExit):

using UnityEngine; public class MouseHoverDetection : MonoBehaviour { void OnMouseEnter() { Debug.Log("鼠标进入!对象名称: " + gameObject.name); GetComponent<Renderer>().material.color = Color.yellow; // 鼠标进入时改变颜色 } void OnMouseExit() { Debug.Log("鼠标离开!对象名称: " + gameObject.name); GetComponent<Renderer>().material.color = Color.white; // 鼠标离开时恢复颜色 } }

内容详解:

  • OnMouseUp(): 通常与 OnMouseDown 配合使用,实现完整的点击交互流程 (按下 -> 执行操作 -> 抬起)。

  • OnMouseEnter()OnMouseExit(): 用于检测鼠标指针进入和离开 GameObjectCollider 区域,可以实现鼠标悬停高亮、显示提示信息等效果。

  • OnMouseOver():OnMouseStayOnTriggerStay 类似,OnMouseOver 也是一个持续调用的事件函数。 只要鼠标指针悬停在 GameObjectCollider 上,OnMouseOver 就会在每个帧被调用。 可以用于实现持续的鼠标悬停效果,例如持续显示信息、持续改变对象状态等。

2.5.4.3 鼠标事件函数总结

事件函数 触发时机 持续性
OnMouseDown 鼠标左键按下时 (仅触发一次)
OnMouseUp 鼠标左键抬起时 (仅触发一次)
OnMouseEnter 鼠标指针进入 Collider 时 (仅触发一次)
OnMouseExit 鼠标指针离开 Collider 时 (仅触发一次)
OnMouseOver 鼠标指针悬停在 Collider 上 (每帧持续触发)

Graph TD 图示鼠标事件流程 (示例 OnMouseEnter, OnMouseOver, OnMouseExit):

2.5.5 事件函数的选择与应用

Unity 提供了种类繁多的事件函数,开发者需要根据具体的游戏逻辑需求选择合适的事件函数。

  • 物理碰撞事件函数 (OnCollisionEnter, OnCollisionStay, OnCollisionExit): 适用于需要精确物理碰撞响应的场景,例如子弹击中、角色与环境交互、物体破碎等。 需要确保参与碰撞的 GameObject 具有 Collider 组件,并且至少一个 GameObject 具有 Rigidbody 组件。

  • 触发器事件函数 (OnTriggerEnter, OnTriggerStay, OnTriggerExit): 适用于非物理碰撞的触发逻辑,例如区域检测、物品拾取、陷阱触发、UI 提示等。 需要将 Collider 组件的 Is Trigger 属性设置为 true。

  • 鼠标事件函数 (OnMouseDown, OnMouseUp, OnMouseEnter, OnMouseExit, OnMouseOver): 适用于处理用户鼠标与 GameObject 交互的场景,例如按钮点击、对象选择、物体交互、游戏控制等。 需要确保 GameObject 具有 Collider 组件。

在实际开发中,可以组合使用不同的事件函数,构建更加复杂和丰富的游戏逻辑。 例如,可以使用 OnCollisionEnter 检测子弹击中敌人,使用 OnTriggerEnter 检测角色进入奖励区域,使用 OnMouseDown 实现物体点击交互。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U