This page has been translated automatically.
视频教程
界面
要领
高级
实用建议
专业(SIM)
UnigineEditor
界面概述
资源工作流程
版本控制
设置和首选项
项目开发
调整节点参数
Setting Up Materials
设置属性
照明
Sandworm
使用编辑器工具执行特定任务
如何擴展編輯器功能
嵌入式节点类型
Nodes
Objects
Effects
Decals
光源
Geodetics
World Nodes
Sound Objects
Pathfinding Objects
Players
编程
基本原理
搭建开发环境
使用范例
C++
C#
UnigineScript
UUSL (Unified UNIGINE Shader Language)
Plugins
File Formats
材质和着色器
Rebuilding the Engine Tools
GUI
双精度坐标
应用程序接口
Animations-Related Classes
Containers
Common Functionality
Controls-Related Classes
Engine-Related Classes
Filesystem Functionality
GUI-Related Classes
Math Functionality
Node-Related Classes
Objects-Related Classes
Networking Functionality
Pathfinding-Related Classes
Physics-Related Classes
Plugins-Related Classes
IG Plugin
CIGIConnector Plugin
Rendering-Related Classes
VR-Related Classes
创建内容
内容优化
材质
Material Nodes Library
Miscellaneous
Input
Math
Matrix
Textures
Art Samples
Tutorials

管理游戏规则

Let's create the LevelManager component to manage game rules, level states and the User Interface. The manager creates a graphical user interface and shows the time left until the game is over. It also checks and shows the number of objects left to clear away from the Play Area.让我们创建 LevelManager 组件来管理游戏规则、关卡状态和用户界面。 管理器创建一个图形用户界面,并显示游戏结束前的剩余时间。 它还检查并显示离开游戏区域的剩余物体数量。

Step 1. Set Up Timer and Game UI
步骤1。设置定时器和游戏界面#

A node with the LevelManager component assigned should be present in the world for rules to take effect. It will manage the timer and update the widget user interface for the game.分配了 LevelManager 组件的节点应该存在于世界中,以使规则生效。 它将管理计时器并更新游戏的 widget 用户界面。

  1. Create a new C# component and call it LevelManager.创建一个新的 C# 组件 并将其命名为 LevelManager
  2. Open the LevelManager component in an IDE and copy the code below. Save your code in an IDE to ensure it's automatic compilation on switching back to UnigineEditor. LevelManager开放组件在IDE和复制下面的代码。您的代码保存在一个IDE,以确保它是自动切换回UnigineEditor编译。

    LevelManager.cs
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using Unigine;
     
    [Component(PropertyGuid = "AUTOGENERATED_GUID")] // <-- this line is generated automatically for a new component
    public class LevelManager : Component
    {
    	// level timer
    	public float timer = 100.0f; 
    
    	bool isCounting = true;
    
    	int physicalObjectsNum;
    	
    	WidgetLabel widget_timer, widget_goal;
    
    	void Init()
    	{
    		InitGUI();
    		// count physical objects in the level
    		physicalObjectsNum = node.NumChildren;
    	}
    
    	void InitGUI()
    	{
    		// getting a GUI pointer
    		Gui gui = Gui.GetCurrent();
    
    		// creating a label widget and setting up its parameters
    		widget_timer = new WidgetLabel(gui, "Time Left:");
    		widget_timer.SetPosition(10, 10);
    		widget_timer.FontColor = vec4.RED;
    
    		widget_goal = new WidgetLabel(gui, "Objects Left: ");
    		widget_goal.SetPosition(10, 30);
    		widget_goal.FontColor = vec4.BLUE; 
    
    		// add widgets to the GUI
    		gui.AddChild(widget_timer, Gui.ALIGN_OVERLAP);
    		gui.AddChild(widget_goal, Gui.ALIGN_OVERLAP);
    	}
    
    	void Update()
    	{
    		// decrease the timer
    		if (isCounting)
    		{
    			timer -= Game.IFps;
    			if (timer <= 0)
    			{
    				//end game
    				isCounting = false;
    			}
    		}
    
    		//win
    		if (physicalObjectsNum <= 0)
    		{
    			isCounting = false;
    		}
    
    		// show the current time and objects left to clear
    		if (isCounting)
    		{
    			widget_timer.Text = "Time Left: " + timer.ToString("0.0") + " s";
    			widget_goal.Text = "Objects Left: " + physicalObjectsNum.ToString();
    		}
    		//hide the widgets on end game
    		else
    		{
    			widget_timer.Enabled = false;
    			widget_goal.Enabled = false;
    		}
    	}
    
    	void Shutdown()
    	{
    		widget_timer.DeleteLater();
    		widget_goal.DeleteLater();
    	}
    
    	public void DecPhysicalObjectsNum()
    	{
    		physicalObjectsNum--;
    	}
    }
  3. Create a new Dummy Node called "level_manager" and place it somewhere in the world.创建一个名为 "level_manager" 的新 虚拟节点,并将其放置在世界某处。
  4. Add the LevelManager component to the level_manager node.LevelManager组件添加到level_manager节点。

We created the system GUI via the API from the code. The alternative method is to use UI files.我们通过 代码中的 API 创建了系统 GUI。 另一种方法是使用 UI 文件

Step 2. Detect Physical Objects
步骤2。检测物理对象#

Only the level_manager's children nodes shall be deleted by the Kill Zone's trigger. Let's add each physical object that we created earlier as a child to the level_manager node. For the rules to function properly you also need to add a new condition and a method call to the KillZone component that checks if the entered node has a parent with the LevelManager component attached.只有 level_manager 的子节点会被 Kill Zone 的触发器删除。 让我们将 之前创建的每个物理对象 作为子节点添加到 level_manager 节点。 为了使规则正常运行,您还需要向 KillZone 组件添加一个新条件和一个方法调用,以检查输入的节点是否具有附加了LevelManager 组件的父节点。

  1. Open the KillZone component in your IDE, add a levelManager field and replace the content of Enter callback function according to the following code. Save your code in an IDE to ensure it's automatic compilation on switching back to UnigineEditor.在你的 IDE 中打开 KillZone 组件,添加一个 levelManager 字段并将 Enter callback 函数的内容替换为如下 代码。 将您的代码保存在 IDE 中,以确保在切换回 UnigineEditor 时自动编译。

    KillZone.cs
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using Unigine;
    
    [Component(PropertyGuid = "AUTOGENERATED_GUID")] // <-- this line is generated automatically for a new component
    public class KillZone : Component
    {
    	// the area into which an object should fall
    	WorldTrigger trigger;
    //========================== NEW - BEGIN ===============================
    	LevelManager levelManager;
    //=========================== NEW - END ================================
    	void Init()
    	{
    		trigger = node as WorldTrigger;
    
    		if (trigger != null)
    			trigger.EventEnter.Connect(Enter); // set the handler to be executed when an object enters the area
    	}
    
    	void Enter(Node target)
    	{
    //========================== NEW - BEGIN ===============================
    		levelManager = target.GetComponentInParent<LevelManager>();
    		// check if the parent node has a LevelManager component attached
    		if (levelManager != null)
    		{
    			// delete the entered node and decrease the amount of physical objects
    			levelManager.DecPhysicalObjectsNum();
    			target.DeleteLater();
    		}
    //=========================== NEW - END ================================
    	}
    }
  2. Let's set the level_manager node as a parent to physical objects. Open the ObjectGenerator component in your IDE and replace the code with the following. Save the code in your IDE and switch back to UnigineEditor.让我们设置level_manager节点作为一个家长物理对象。在IDE中打开ObjectGenerator组件和替换用下面的代码。保存您的IDE中的代码并切换回UnigineEditor。

    ObjectGenerator.cs (C#)
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using Unigine;
    
    [Component(PropertyGuid = "AUTOGENERATED_GUID")] // <-- this line is generated automatically for a new component
    public class ObjectGenerator : Component
    {
    //========================== NEW - BEGIN ===============================
    	public Node levelManager;
    //=========================== NEW - END ================================
    	private void Init()
    	{
    //========================== NEW - BEGIN ===============================
    		if (levelManager)
    		{
    //=========================== NEW - END ================================
    			// cube 
    			ObjectMeshDynamic box = Primitives.CreateBox(new vec3(1.0f));
    			//========================== NEW - BEGIN =============================
    			box.Parent = levelManager;
    			//========================== NEW - END ===============================
    			box.TriggerInteractionEnabled = true;
    			box.SetIntersection(true, 0);
    			box.SetIntersectionMask(0x00000080, 0); // check the BulletIntersection bit
    			box.WorldTransform = MathLib.Translate(new vec3(0.5f, 7.5f, 1.0f));
    			box.SetMaterialPath("materials/mesh_base_0.mat", "*");
    			box.Name = "box";
    			BodyRigid bodyBox = new BodyRigid(box);
    			ShapeBox shapeBox = new ShapeBox(bodyBox, new vec3(1.0f));
    			new ShapeSphere(bodyBox, 0.5f);
    			bodyBox.ShapeBased = false;
    			bodyBox.Mass = 2.0f;
    
    			// sphere
    			ObjectMeshDynamic sphere = Primitives.CreateSphere(0.5f, 9, 32);
    			//========================== NEW - BEGIN ===============================
    			sphere.Parent = levelManager;
    			//========================== NEW - END ===============================
    			sphere.TriggerInteractionEnabled = true;
    			sphere.SetIntersection(true, 0);
    			sphere.SetIntersectionMask(0x00000080, 0); // check the BulletIntersection bit
    			sphere.WorldTransform = MathLib.Translate(new vec3(4.5f, 5.5f, 1.0f));
    			sphere.SetMaterialPath("materials/mesh_base_1.mat", "*");
    			sphere.Name = "sphere";
    			BodyRigid bodySphere = new BodyRigid(sphere);
    			new ShapeSphere(bodySphere, 0.5f);
    			bodySphere.ShapeBased = false;
    			bodySphere.Mass = 2.0f;
    
    			// capsule
    			ObjectMeshDynamic capsule = Primitives.CreateCapsule(0.5f, 1.0f, 9, 32);
    			//========================== NEW - BEGIN ===============================
    			capsule.Parent = levelManager;
    			//========================== NEW - END ===============================
    			capsule.TriggerInteractionEnabled = true;
    			capsule.SetIntersection(true, 0);
    			capsule.SetIntersectionMask(0x00000080, 0); // check the BulletIntersection bit
    			capsule.WorldTransform = MathLib.Translate(new vec3(4.5f, 0.5f, 3.0f));
    			capsule.SetMaterialPath("materials/mesh_base_2.mat", "*");
    			capsule.Name = "capsule";
    			BodyRigid bodyCapsule = new BodyRigid(capsule);
    			new ShapeCapsule(bodyCapsule, 0.5f, 1.0f);
    			bodyCapsule.ShapeBased = false;
    			bodyCapsule.Mass = 2.0f;
    //========================== NEW - BEGIN ===============================
    		}
    //=========================== NEW - END ================================
    	}
    }
  3. Select the object_generator node in the World Nodes window and drag the level_manager node to the corresponding field of the ObjectGenerator component.选择object_generator节点World Nodes窗口拖动level_manager节点的对应字段ObjectGenerator组件。

  4. Save changes to the world, go to File->Save World or press Ctrl+S hotkey. Then run the game to see the game rules in action.保存对世界的更改,转到 File->Save World 或按 Ctrl+S 热键。 然后运行游戏以查看实际的游戏规则。
最新更新: 2024-04-19
Build: ()