添加交互区域
In games and VR applications, some actions are performed when you enter a specific area in the scene (for example, music starts, sound or visual effects appear). Let's implement this in our project: when you enter or teleport to a certain area, it rains inside it.在游戏和 VR 应用中,一些动作会在你进入场景中特定区域时触发(例如,播放音乐、出现音效或视觉特效)。我们将在项目中实现这一功能:当你进入某个区域或传送到该区域时,区域内会开始下雨。
In UNIGINE, the World Trigger node is used to track when any node (collider or not) gets inside or outside of it (for objects with physical bodies, the Physical Trigger node is used).在 UNIGINE 中,可以使用 World Trigger 节点来检测任何节点(包括非碰撞体)进入或离开该区域的情况(对于带有物理实体的对象,则使用 Physical Trigger 节点)。
-
First of all, create a trigger to define the rain area. On the Menu bar, choose Create -> Logic -> World Trigger and place the trigger near the Material Ball, for example. Set the trigger size to (2, 2, 2).首先,创建一个触发器以定义降雨区域。在菜单栏中选择 Create -> Logic -> World Trigger,并将其放置在 Material Ball 附近(例如)。将触发器的尺寸设置为 (2, 2, 2)。
-
Create a new TriggerZone component that will turn the rain node on and off (in our case, it is a particle system simulating rain), depending on the trigger state. Add the following code to the component and then assign it to the World Trigger node:创建一个新的 TriggerZone 组件,根据触发器的状态开启或关闭降雨节点(本示例中是一个模拟降雨的粒子系统)。将以下代码添加至组件中,并将该组件赋给 World Trigger 节点:
源代码 (C++)#pragma once #include <UnigineComponentSystem.h> #include <UnigineWorlds.h> class TriggerZone : public Unigine::ComponentBase { public: COMPONENT(TriggerZone, Unigine::ComponentBase); COMPONENT_INIT(init); // 属性名称 PROP_NAME("TriggerZone"); // 由触发器控制的节点 PROP_PARAM(Node, controlledNode); protected: void init(); // 触发器的事件处理函数 void trigger_enter(const Unigine::NodePtr &player); void trigger_leave(const Unigine::NodePtr &player); private: // 触发器节点 Unigine::WorldTriggerPtr trigger; // 触发器事件连接引用(shutdown 时会移除所有事件连接) Unigine::EventConnections conns; };
源代码 (C++)#include "TriggerZone.h" using namespace Unigine; REGISTER_COMPONENT(TriggerZone); void TriggerZone::init() { // 检查该组件是否被附加到 WorldTrigger if (node->getType() != Node::WORLD_TRIGGER) { Log::error("Node %s (TriggerZone) 错误:此组件只能附加到 WorldTrigger 上。\n", node->getName()); ComponentSystem::get()->removeComponent<TriggerZone>(node); return; } // 检查是否指定了 controlledNode if (controlledNode.nullCheck()) { Log::error("节点 %s (TriggerZone) 错误:未设置 'controlledNode'。\n", node->getName()); ComponentSystem::get()->removeComponent<TriggerZone>(node); return; } // 添加在节点进入和离开触发器时要执行的事件处理器 trigger = checked_ptr_cast<WorldTrigger>(node); trigger->getEventEnter().connect(conns, this, &TriggerZone::trigger_enter); trigger->getEventLeave().connect(conns, this, &TriggerZone::trigger_leave); } // 处理函数:当玩家进入触发区域时启用 ControlledNode void TriggerZone::trigger_enter(const NodePtr &player) { if (!player->isPlayer()) return; controlledNode->setEnabled(true); } // 处理函数:当玩家离开触发区域时禁用 ControlledNode void TriggerZone::trigger_leave(const NodePtr &player) { if (!player->isPlayer()) return; controlledNode->setEnabled(false); }
-
Now, let's add the rain effect. Drag the rain_effect.node asset from the vr/particles folder of the UNIGINE Starter Course Project add-on to the scene, add it as the child to the trigger node and turn it off (the component will turn it on later).现在,让我们添加下雨效果。从 UNIGINE Starter Course Project 插件的 vr/particles 文件夹中将 rain_effect.node 资源拖到场景中,将其作为触发器节点的子节点添加,并将其关闭(稍后由组件开启)。
-
Drag the rain_effect node from the World Hierarchy window to the Controlled Node field of the TriggerZone (in the Parameters window).从 World Hierarchy 窗口中将 rain_effect 节点拖动到 Parameters 窗口中 TriggerZone 组件的 Controlled Node 字段中。
Save changes (Ctrl+S) you've made to the world.保存对世界所做的更改(Ctrl+S)。
-
We also have to enable the Triggers Interaction option for the VR Player to make the trigger react on contacting it. Simply add the following line to the init_player() method of the VRPlayerSpawner component (Framework\Components\VRPlayerSpawner.cpp):我们还需要为 VR Player 启用 Triggers Interaction 选项,以使触发器在接触时做出反应。只需将以下代码行添加到 Framework\Components\VRPlayerSpawner.cpp 中的 init_player() 方法中:
源代码 (C++)void VRPlayerSpawner::init_player(const PlayerPtr &player) { // 复制变换 player->setWorldTransform(node->getWorldTransform()); ${#HL}$player->setTriggerInteractionEnabled(true); ${HL#}$ if (node->getType() >= Node::PLAYER_BEGIN && node->getType() <= Node::PLAYER_END) { PlayerPtr player_ref = checked_ptr_cast<Player>(node); // 复制基本参数 player->setFov(player_ref->getFov()); player->setZNear(player_ref->getZNear()); player->setZFar(player_ref->getZFar()); for (int i = 0 ; i < player_ref->getNumScriptableMaterials(); i++) player->addScriptableMaterial(player_ref->getScriptableMaterial(i)); } // 解除当前节点的父子关系 // (因为 vr_group 可能是其父节点,而我们不希望关闭 // 附属于我们的组件) node->setWorldParent(NodePtr()); }
-
Save changes (Ctrl+S), rebuild the project, and run it via SDK Browser, then try to enter the area defined by the trigger — it should raininside.保存更改(Ctrl+S),重新构建项目并通过 SDK Browser 运行它,然后尝试进入触发器定义的区域——你会看到下雨效果。
本页面上的信息适用于 UNIGINE 2.20 SDK.