Creating and Removing Nodes Via Code
That's great when everything is available in the scene from the outset, but more often than not some objects should be created and deleted at runtime.
Creating and deleting nodes at runtime as almost as easy as in the Editor. The basic set of actions is as follows:
- Creation. To create a node we should call a constructor of the corresponding class by using the new keyword and providing construction parameters, if necessary.
- Deletion. To delete a node we simply call the DeleteLater() method for the node we are going to remove.
In general, the code will look as follows:
// creating a node of the NodeType named nodename
<NodeType> nodename = new <NodeType>(<constructor_params>);
// removing the node
nodename.DeleteLater();
Now let us illustrate the process of loading a node from a *.node file from disk using the AssetLinkNode class.
// link to a *.node asset file on disk
public AssetLinkNode assetNode;
// specify the spawn transform (position, rotation and scale)
public Node spawnPoint;
// load the node from the specified *.node file and place it using the transformations of spawnPoint
assetNode.Load(spawnPoint);
You can also create new nodes of various built-in classes using AssetLink, for example create Static Mesh. Just provide the asset file path to a class constructor.
// link to an asset file on disk
public AssetLink meshAsset;
// specify the spawn transform (position, rotation and scale)
public Node spawnPoint;
// check if the file exists on disk
if (meshAsset.IsFileExist)
{
// create a new Static Mesh from the specified mesh asset
ObjectMeshStatic mesh = new ObjectMeshStatic(meshAsset.Path);
// copy the transformation of spawnPoint
mesh.WorldTransform = spawnPoint.WorldTransform;
}
Practice#
For our project, let's create the ObjectPlacer component that will place the specified objects in the scene at the specified points (NodeDummy) and the Removable component that will allow us to remove objects by right-clicking. Destroying is always easier that creating, so let's start simple — create the Removable component by inheriting it from Interactable. As a click action, it will simply remove the node to which it is assigned.
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 Removable : Interactable
{
public void Init()
{
// set the tooltip text that will be displayed when the cursor hovers over the object
tooltip = "The object can be removed by right-clicking the mouse.";
}
public override void Action(int num=0)
{
// remove the node to which the component is assigned
node.DeleteLater();
}
}
Now let's deal with the placer component.
-
Create a new component, name it ObjectPlacer, and add the following code into it:
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 ObjectPlacer : Component { // combine parameters into groups: for the first and second objects [Parameter(Group="First Object Placement")] public AssetLinkNode placeable = null; [Parameter(Group="First Object Placement", Title = "Spawn Points", Tooltip ="Points for placing the first object.")] public Node spawnPoints1 = null; // the top node in the placement points hierarchy [Parameter(Group="Second Object Placement")] public AssetLink meshAsset; [Parameter(Group="Second Object Placement")] public Material meshMat = null; [Parameter(Group="Second Object Placement", Title = "Spawn Points", Tooltip ="Points for placing the second object.")] public Node spawnPoints2 = null; // he top node in the placement points hierarchy private void Init() { // check if there is a specified node-file contains the hosting object(s) and if it has a list of points if (placeable.IsFileExist && (spawnPoints1 != null)) { // load the specified .node-asset's content and place it in every point, // marked with child nodes of the specified list (Spawn-points) for(int i = 0; i < spawnPoints1.NumChildren; i++) placeable.Load(spawnPoints1.GetChild(i).WorldTransform).AddComponent<Removable>(); } // check if the specified *.mesh file used to create the Static Mesh object exists and a list of points is specified for it if (meshAsset.IsFileExist && (spawnPoints2 != null)) { // place in every point marked by child nodes of the specified list (Spawn-points) for(int i = 0; i < spawnPoints2.NumChildren; i++) { // create the Static Mesh node using the specified *.mesh asset and set the specified material for it ObjectMeshStatic mesh = new ObjectMeshStatic(meshAsset.Path); mesh.Name = "generated_mesh_" + i.ToString(); mesh.SetMaterial(meshMat ,"*"); mesh.WorldTransform = spawnPoints2.GetChild(i).WorldTransform; // add the Removable component to the node, that allows us to delete a node by right-clicking mesh.AddComponent<Removable>(); } } } }
-
Now let's find the interior node (NodeDummy) and assign our ObjectPlacer component to it.
-
The parameters of the component are divided into two groups: the first one is for placement of the specified *.node asset, and the second one is for generation of Mesh Static objects from the specified *.mesh asset and assignment of the specified material. Next, let's assign a flower (the pot_ceramic_small.node asset) to the Placeable field in the First Object Placement group, toy_fox.mesh and toy_fox_mat material to the Mesh Asset and Mesh Material fields in the Second Object Placement group.
-
Next, let's define the points to place flowers: create a NodeDummy, name it plant_spawn_points and create several NodeDummy children for it (by clicking on it in the World Hierarchy and choosing Create → Node → Dummy), name them plant_spawn_point_1, plant_spawn_point_2 and plant_spawn_point_3 respectively and place them in the scene in the places where we need flowers. Do the same for the fox figure. We will have the following hierarchy:
-
Now drag the plant_spawn_points and fox_spawn_points nodes to the Spawn Point fields in the corresponding groups of the ObjectPlacer component:
Let's run our project by clicking the Play button (or Ctrl + F5) and check the spawned objects.