How to assemble a spider in Godot, Unigine or PlayCanvas

Happy 21st year of the 21st century.



In this article I will go over the features of working in three game engines, using the example of writing code for a spider-like vehicle.







The general structure of the "spider car" was as follows - there are 6 paws, each copy of the control script, which tracks the movement of the main structure and rearranges the paw to a new position when it moves away a certain distance.

For a more accurate landing of the paws, it was planned to add raycasts, but, for example, in the same Godot I wanted to make a spider for a game with a top view, in which such accuracy is not particularly needed.



Thus, the task was to form the desired structure inside the engine and write the code for a separate foot. Here's what happened in different development environments:







Godot



Here I already had a small project with cars and a spider ready, I decided to add to one of the scenes (prefabs), which contains a subclass of cars that do not have wheels.



The specific_base scene itself is arranged in such a way that at the base is a dummy node, which simply hangs somewhere in the world, without movement, and the kinematic body inside it moves around the world. The camera is inside the scene, but outside the body, just by following it.







To create the spider, I added a separate node inside the body, containing the dummy points for the location of the paws (where they are placed on the ground, not where they are attached to the body).







For convenience, I placed the paws themselves here, in this scene, but outside the body. The script controlling each of them, in addition to moving the paw, will constantly unfold it to the center of the "spider".





Code inside the Godot editor



Writing the code. I use GDScript, because I don't see much point in writing in C # in Godot (not so much a fan of curly braces):



extends Spatial

export var distance = 2.5# ,    
export var step = 1#     ( )

#        ,      
export (NodePath) var spidercenter = null
var trg_center

export (NodePath) var spiderleg = null
var trg_leg

#     x  z
var x_dis = 0.0
var z_dis = 0.0

#-,   
var time_lag = -1.0

# 
func _ready():
	self.hide()# 
	trg_center = get_node(spidercenter)# 
	trg_leg = get_node(spiderleg)
	LegPlace()#      

#  
func _process(delta):
        #     .   ,      
	self.look_at(trg_center.global_transform.origin, Vector3(0,1,0))
	
        # ,    .    ,    ,         (             ,      ).              LegPlace
	if self.visible == false: self.show()

	if time_lag>=0:# - ,    
		time_lag +=1*delta 
		if time_lag>0.06:#       
			time_lag = -1.0
			LegPlace()
	else:#            
		x_dis = abs(trg_leg.global_transform.origin.x - self.global_transform.origin.x)
		z_dis = abs(trg_leg.global_transform.origin.z - self.global_transform.origin.z)
	
		if (x_dis + z_dis) > distance:#   ,  
			time_lag = 0.0
	
	pass
	
func LegPlace():#,    
	self.hide()
	step = step*(-1)
	self.global_transform.origin = trg_leg.global_transform.origin+Vector3(0,0,0.5*step)

      
      







Godot spider dough cutscene. As a bonus, it also included moments from a separate game with terraforming the voxel world, where a "spider" is also used, but purely animated, as well as a demo with cars on playcanvas, before the spider shape was added there.







Unigine



After the implementation for Godot was ready, I decided to transfer this solution to the Unigine engine. There I also had a project with cars , though in order not to overload it, I made a separate "spider" fork, so that later, probably, completely remove the wheels from it and develop it somehow separately.







There is the whole scene of the game world, in which the body of the player's car is located. At the beginning of the game, separately located wheels are docked to this body.

I'm looking for a dummy inside the body, inside which there will be points that set the positions of the paws.







The paws are simply placed in the game world. The movement itself is left realized through the wheels, but their visual representation is disabled.





Unigine launches external environment for code editing



Code:



using System;// ""
using System.Collections;
using System.Collections.Generic;
using Unigine;

//  ,    
[Component(PropertyGuid = "5a8dd6f85781adf7567432eae578c5414581ddac")]
public class theLegBehavior : Component
{

	[ShowInEditor][Parameter(Tooltip = "CenterSpider")]//   
	private Node spiderCenter = null;
	[ShowInEditor][Parameter(Tooltip = "Target Leg Point")]//   
	private Node legPoint = null;

	//     
	private float x_dis= 0.0f;
	private float z_dis= 0.0f;

	private float ifps;//  
	private float time_lag = -1.0f;//-

	private void Init()//
	{
		node.Enabled = false;// 
		LegPlace();//  
		
	}
	
	private void Update()// 
	{
		ifps = Game.IFps;// 

		if (time_lag>=0.0f){//   
			time_lag += 1.0f*ifps;

			if (time_lag>=0.6f) {
				time_lag = -1.0f;
				LegPlace();
			}
		
		}else{
			x_dis = MathLib.Abs(legPoint.WorldPosition.x - node.WorldPosition.x);
			z_dis = MathLib.Abs(legPoint.WorldPosition.z - node.WorldPosition.z);
            	
			if (x_dis + z_dis > 0.8f){
				time_lag = 0.0f;
			}
			
		}

	}

        //   .        .         .       ,  ,    ,     - .         ,      Update.
	private void LegPlace()
	{
		node.Enabled = false;

		vec3 targetDirection = vec3.ZERO;
		targetDirection = (legPoint.WorldPosition - node.WorldPosition);

		quat targetRot = new quat(MathLib.LookAt(vec3.ZERO, targetDirection, vec3.UP, MathLib.AXIS.Y));

		quat delta = MathLib.Inverse(targetRot);
		delta.z = 0;
		delta.Normalize();

		node.WorldPosition = legPoint.WorldPosition;

        targetDirection = (spiderCenter.WorldPosition - node.WorldPosition);
		node.SetWorldDirection(targetDirection, vec3.UP, MathLib.AXIS.Y);

		node.Enabled = true;		
	}
}

      
      







Unigine Spider Dough Cutscene







PlayCanvas



PlayCanvas is a webGL game engine using javascript. Recently I started to understand it. It looks like a cross between Unity and Godot, but with online development - the editor opens in the browser.



In this case, I redid one of the examples offered by this platform, adding a couple of my car models, a little additional functionality like jumping, adding a camera and playing with materials / settings.



The visual representation of the base car in the original example was given by a solid model, which I partially disabled, leaving only the wheels, which are pulled from the inside of the model by its control script (that is, they are not wound by separate nodes in the scene hierarchy). This visual representation during gameplay clings to a moving physical wheel model.

To implement the "spider" within this project, I started a "spider center" inside the visual representation of the car. For convenience, the "spider body" is nested inside it, as I wanted to immediately switch to the "spider shape" and back.







Thus, the local "spider" is also placed on top of the wheel drive, and the wheels themselves are hidden. Perhaps it would be more correct to attach the spider frame to the physics node, but switching between forms is already located in the script of the node with the visual of the car, and other models are inside this node, so I chose this option for simplicity. In fact, it turns out that the visual in its script moves behind the physics, and the scripts of the paws are already looking at the spider frame moving along with the visual. In theory, there may be some desynchronization here, at least I noticed that on weak devices some paws do not have time to calculate positions and only some move.

And so, in general, the solution, of course, is not tied to physics or rigidbody, the legs, in fact, do not care how you move the main object - by forces or simply by changing the position.







The paws are located in the scene itself, but for the convenience of enabling / disabling them, they are collected inside a separate node, so that you can simply disable it, and not each by a separate link.





In playcanvas, the code editor is launched in a new browser tab



Code:



var TheLegBehavior = pc.createScript('theLegBehavior');

//   
TheLegBehavior.attributes.add('N_spiderCenter', { type: 'entity' });
//     
TheLegBehavior.attributes.add('N_legPoint', { type: 'entity' });

//    
this.x_dis = 0.0;
this.z_dis = 0.0;

this.time_lag = -1.0;//-

//  ,     , -     
TheLegBehavior.prototype.initialize = function() {    
};

// 
TheLegBehavior.prototype.update = function(dt) {
    if (this.N_spiderCenter) {//  -    
        this.entity.lookAt(this.N_spiderCenter.getPosition());// ,     
    }
};

//.       ,     , , ,   .
TheLegBehavior.prototype.postUpdate = function(dt) {
    //,      
    if (time_lag>=0.0){
        time_lag+=1.0*dt;
        if (time_lag>=0.06){
            time_lag=-1.0;
            this.LegUpdate();
        }
        
    } else {
        
        x_dis = Math.abs(this.entity.getPosition().x-this.N_legPoint.getPosition().x);
        z_dis = Math.abs(this.entity.getPosition().z-this.N_legPoint.getPosition().z);
        
        if ((x_dis+z_dis)>3.0){
         time_lag=0.0;
        }
        
        
    }
};

//      ,        ", , ",       
TheLegBehavior.prototype.LegUpdate = function() {
    
    if (this.N_legPoint) {// ,   ,     
        this.entity.setPosition(this.N_legPoint.getPosition());
    }
      
};

      
      





In general, so far we have obtained a blank spider with four legs and not quite optimal calculations.



You can test the resulting frame

here .



I personally tried to run on a not too powerful smartphone through Chrome and Dolphin, the graphics become similar to PsOne and calculations for some paws do not work, while the level is visible on the screen, paws appear at the edge of the map. On a weak laptop, there were very strong brakes in Chrome, but everything rolls fine in Firefox. On a laptop with a discrete video card and on a stationary it flies in both of these browsers.



On a PC, unlike smartphones, this demo works with a jump (by pressing the spacebar), preparing a strafe (Q and E) and reloading a level (on R).



Outcome



As you can see, languages ​​and engines are different, but nevertheless, many things in the family of scripting languages ​​are done in a rather similar way. How often did you master new game engines and frameworks, what were the main difficulties you faced?



All Articles