This page has been translated automatically.
Unigine Basics
1. Introduction
2. Managing Virtual Worlds
3. Preparing 3D Models
4. Materials
5. Cameras and Lighting
6. Implementing Application Logic
7. Making Cutscenes and Recording Videos
8. Preparing Your Project for Release
9. Physics
10. Optimization Basics
12. PROJECT3: Third-Person Cross-Country Arcade Racing Game
13. PROJECT4: VR Application With Simple Interaction
Warning! This version of documentation is OUTDATED, as it describes an older SDK version! Please switch to the documentation for the latest SDK version.
Warning! This version of documentation describes an old SDK version which is no longer supported! Please upgrade to the latest SDK version.

Health and Damage

The player and enemies should have a health level that will decrease each time they are hit by a bullet. We'll store the health information in the Health component.

  1. Create the Health.cs component and copy the following code into it:

    Health.cs

    Source code (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 Health : Component
    {
    	public int health = 5;
    
    	// flag indicating that the health value is less or equal to 0
    	public bool IsDead => health <= 0;
    
    	public void TakeDamage(int damage)
    	{
    		// calculate damage to health
    		health = MathLib.Max(health - damage, 0);
    	}
    }
  2. Add it to the visuals node of the robot_enemy node.

  3. Add it to the player_hit_box node of the player node.
  4. In order to use the Health.cs component logic, we need to modify number of components.

    In WeaponController.cs, add the following several lines to the part detecting that the player has hit an object:

    Source code (C#)
    // if the intersection is found
    if (hitObject)
    {
      // render the intersection normal in the hit point 
      Visualizer.RenderVector(hitInfo.Point, hitInfo.Point + hitInfo.Normal, vec4.RED, 0.25f, false, 2.0f);
      // spawn the visual effect NodeReference in the hit point
      vfx.OnHit(hitInfo.Point, hitInfo.Normal, hitObject);
     ${#HL}$ // apply damage
      Health health = hitObject.GetComponent<Health>();
      if (health)
      	health.TakeDamage(damage); ${HL#}$
    }

    In Bullet.cs, let's add several lines after detecting that the player has been hit and just before removing the bullet in order to apply damage to the characher and update the health information:

    Source code (C#)
    // check if any object has been hit
    if (!hitObject)
    	return;
    
    // load a visual effect NodeReference to visuallize the hit
    Node hitEffect = World.LoadNode(hitPrefab.AbsolutePath);
    // place the NodeReference to the hit point to set its direction according to the hit normal 
    hitEffect.Parent = hitObject;
    hitEffect.WorldPosition = hitInfo.Point;
    hitEffect.SetWorldDirection(hitInfo.Normal, vec3.UP, MathLib.AXIS.Y);
    
    ${#HL}$ // check the object that has been hit (hitObject): if it is a player and if it has the Health component
    Health health = hitObject.GetComponent<Health>();
    if (health && hitObject.GetComponentInParent<playerlogic>())
    {
       // apply the damage from the bullet
       health.TakeDamage(damage);
    
       // update the player's health information in HUD
       ComponentSystem.FindComponentInWorld<HUD>().UpdateHealthInfo(health.health);
    }
    // delete the bullet
    node.DeleteLater(); ${HL#}$

The robots that have zero health should be deleted from the scene. The Health component has the IsDead flag which is checked by the EnemyLogic component of the robot. If the flag is set to true, the node of that robot will be deleted. To do this, we will add the health property to the EnemyLogic component, initialize it in Init() and then we'll check the health level of the enemy robot every frame in Update() and remove it if necessary:

Source code (C#)
${#HL}$private Health health = null;${HL#}$

// ...

private void Init()
{
  // ...
  ${#HL}$// grab the Health component
  health = node.GetComponentInChildren<Health>();${HL#}$
}

private void Update()
{
  // ...

  ${#HL}$// check if the IsDead flag is set
  if (health && health.IsDead)
	// remove the enemy from the scene if it is killed (IsDead)
	node.DeleteLater();${HL#}$
}

We need to add the same check for the player, only instead of deleting it (in this case we'll just delete the main camera and see nothing else) we'll just make it immovable by disabling several components.

  1. Create the PlayerLogic.cs component and add the following code into it:

    Source code (C#)
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using Unigine;
    
    [Component(PropertyGuid = "AUTOGENERATED_GUID")] // <-- identifier is generated automatically for a new component
    public class PlayerLogic : Component
    {
        private Health health = null;
        private void Init()
        {
       	 // grab the Health component of the node
       	 health = node.GetComponentInChildren<Health>();
     	 // update the player's health information
       	 ComponentSystem.FindComponentInWorld<HUD>().UpdateHealthInfo(health.health);
        }
        
        private void Update()
        {
       	 // check if the IsDead flag is set
       	 if (health && health.IsDead)
       	 {
       		 // make the player immovable by disabling the components
       		 node.GetComponent<FirstPersonController>().Enabled = false;
              	 node.GetComponent<WeaponController>().Enabled = false;
               	 node.GetComponent<ShootInput>().Enabled = false;
       	 }
        }
    }
  2. Add the PlayerLogic component to the player node.

Let's also add displaying of player's health information in the HUD. To do this, we will add a few lines to the Init() method and add the UpdateHealthInfo() method to update the value in the GUI widget in the HUD.cs file:

Source code (C#)
${#HL}$ private WidgetLabel label = null;${HL#}$

private void Init()
{
    // get an instance of the current screen GUI
    screenGui = Gui.GetCurrent();

    // create a WidgetSprite for crosshair
    sprite = new WidgetSprite(screenGui, crosshairImage);
    // set the sprite size
    sprite.Width = crosshairSize;
    sprite.Height = crosshairSize;

    // add the sprite to GUI so that it would always be in the center of the screen and overlap any other widgets
    screenGui.AddChild(sprite, Gui.ALIGN_CENTER | Gui.ALIGN_OVERLAP);
    // bind the widget lifetime to the world
    sprite.Lifetime = Widget.LIFETIME.WORLD;


    ${#HL}$ // add WidgetLabel to display the player's health, set its position and font size
    label = new WidgetLabel(screenGui, "");
    label.FontSize = 50;
    label.SetPosition(10,10);

    // add the widget to GUI
    screenGui.AddChild(label, Gui.ALIGN_CENTER | Gui.ALIGN_OVERLAP);
    //  bind the widget lifetime to the world
    label.Lifetime = Widget.LIFETIME.WORLD;${HL#}$

}


${#HL}$ // update the current player's health
public void UpdateHealthInfo(int health)
{
    label.Text = "Health: " + health.ToString();
}${HL#}$
Last update: 2024-04-04
Build: ()