This page has been translated automatically.
Основы UNIGINE
1. Введение
2. Виртуальные миры и работа с ними
3. Подготовка 3D моделей
4. Материалы
5. Камеры и освещение
6. Реализация логики приложения
7. Создание кат-сцен и запись видео
8. Подготовка проекта к релизу
9. Физика
10. Основы оптимизации
12. ПРОЕКТ3: Аркадная гонка по пересеченной местности от 3-го лица
13. ПРОЕКТ4: VR приложение с простым взаимодействием
Внимание! Эта версия документация УСТАРЕЛА, поскольку относится к более ранней версии SDK! Пожалуйста, переключитесь на самую актуальную документацию для последней версии SDK.
Внимание! Эта версия документации описывает устаревшую версию SDK, которая больше не поддерживается! Пожалуйста, обновитесь до последней версии SDK.

Здоровье и урон при попадании

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.Игрок и враги должны иметь уровень здоровья, который будет уменьшаться каждый раз, когда в них попадает пуля. Информацию о здоровье мы будем хранить в компоненте Health.

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

    Health.csHealth.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 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);
    	}
    }
    Create the Health.cs component and copy the following code into it:Health.cs

    Create the Health.cs component and copy the following code into it:Создайте компонент Health.cs и скопируйте следующий код:

    Health.csHealth.cs

    Исходный код (C#)
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using Unigine;
    
    [Component(PropertyGuid = "AUTOGENERATED_GUID")] // <-- идентификатор генерируется автоматически для нового компонента
    public class Health : Component
    {
    	public int health = 5; // начальный уровень здоровья
    
    	// флаг, проверяющий, не достиг ли текущий уровень здоровья 0
    	public bool IsDead => health <= 0;
    
    	public void TakeDamage(int damage)
    	{
    		// применяем ущерб
    		health = MathLib.Max(health - damage, 0);
    	}
    }
  2. Add it to the visuals node of the robot_enemy node.Add it to the visuals node of the robot_enemy node.

    Add it to the visuals node of the robot_enemy node.

    Add it to the visuals node of the robot_enemy node. Добавьте его в ноду visuals ноды robot_enemy.

  3. Add it to the player_hit_box node of the player node.Добавьте его в ноду player_hit_box ноды player.
  4. In order to use the Health.cs component logic, we need to modify number of components.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:In WeaponController.cs, add the following several lines to the part detecting that the player has hit an object:

    Исходный код (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: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:

    Исходный код (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#}$
    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: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:

    In order to use the Health.cs component logic, we need to modify number of components.Чтобы использовать логику компонента Health.cs. надо внести изменения в код ряда компонентов.

    In WeaponController.cs, add the following several lines to the part detecting that the player has hit an object:В WeaponController.cs добавим несколько строчек в блок обнаружения попадания игрока в объект:

    Исходный код (C#)
    // если обнаружено попадание в объект
    if (hitObject)
    {
      // рисуем нормаль в точке попадания 
      Visualizer.RenderVector(hitInfo.Point, hitInfo.Point + hitInfo.Normal, vec4.RED, 0.25f, false, 2.0f);
      // генерируем в точке попадания NodeReference визуального эффекта
      vfx.OnHit(hitInfo.Point, hitInfo.Normal, hitObject);
      ${#HL}$ // применяем ущерб
      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:В Bullet.cs после обнаружения попадания в игрока и непосредственно перед удалением пули добавим несколько строчек, для нанесения урона персонажу, в который наша пуля попала, а также обновление информации о здоровье игрока, если пуля попала в него :

    Исходный код (C#)
    // проверяем, попали ли мы в объект
    if (!hitObject)
    	return;
    
    // загружаем NodeReference спецэффекта попадания пули
    Node hitEffect = World.LoadNode(hitPrefab.AbsolutePath);
    // помещаем NodeReference в точку попадания и устанавливаем направление в соответствии с нормалью 
    hitEffect.Parent = hitObject;
    hitEffect.WorldPosition = hitInfo.Point;
    hitEffect.SetWorldDirection(hitInfo.Normal, vec3.UP, MathLib.AXIS.Y);
    
    ${#HL}$ // проверяем объект, в который попали (hitObject), игрок ли это и есть ли у него компонента Health
    Health health = hitObject.GetComponent<Health>();
    if (health && hitObject.GetComponentInParent<playerlogic>())
    {
       // применяем ущерб от пули
       health.TakeDamage(damage);
    
       // обновляем информацию о здоровье игрока в HUD
       ComponentSystem.FindComponentInWorld<HUD>().UpdateHealthInfo(health.health);
    }
    // удаляем пулю
    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:Роботы, здоровье которых становится равным нулю, удаляются со сцены. У компонента Health есть флаг IsDead, который проверяется компонентом логики вражеского робота (EnemyLogic). Если флаг равен true, то нода соответствующего робота будет удалена. Для этого в компоненту EnemyLogic добавим свойство health, проинициализируем его в Init() и каждый кадр в Update() будем проверять уровень здоровья вражеского робота и удалять его при необходимости:

Исходный код (C#)
${#HL}$private Health health = null;${HL#}$

// ...

private void Init()
{
  // ...
  ${#HL}$// берем компонент Health
  health = node.GetComponentInChildren<Health>();${HL#}$
}

private void Update()
{
  // ...

  ${#HL}$// проверяем, выставлен ли флаг IsDead
  if (health && health.IsDead)
	// удаляем врага со сцены, если он убит (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:Create the PlayerLogic.cs component and add the following code into it:

    Исходный код (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;
       	 }
        }
    }
    Create the PlayerLogic.cs component and add the following code into it:

    Create the PlayerLogic.cs component and add the following code into it:Создайте компонент PlayerLogic.cs и добавьте в него следующий код:

    Исходный код (C#)
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using Unigine;
    
    [Component(PropertyGuid = "AUTOGENERATED_GUID")] // <-- идентификатор генерируется автоматически для нового компонента
    public class PlayerLogic : Component
    {
        private Health health = null;
        private void Init()
        {
       	 // берем у ноды компонент Health
       	 health = node.GetComponentInChildren<Health>();
     	 // обновляем информацию об исходном здоровье игрока
       	 ComponentSystem.FindComponentInWorld<HUD>().UpdateHealthInfo(health.health);
        }
        
        private void Update()
        {
       	 // проверяем выставлен ли флаг IsDead 
       	 if (health && health.IsDead)
       	 {
       		 // обездвиживаем игрока, отключая компоненты
       		 node.GetComponent<FirstPersonController>().Enabled = false;
              	 node.GetComponent<WeaponController>().Enabled = false;
               	 node.GetComponent<ShootInput>().Enabled = false;
       	 }
        }
    }
  2. Add the PlayerLogic component to the player node.Добавьте компонент PlayerLogic к ноде player.

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:Добавим также отображение информации о здоровье игрока в HUD. Для этого допишем несколько строчек в метод Init() и добавим метод UpdateHealthInfo() для обновления значения в виджете GUI в файле HUD.cs:

Исходный код (C#)
${#HL}$ private WidgetLabel label = null;${HL#}$

private void Init()
{
    // получаем текущий экранный GUI
    screenGui = Gui.GetCurrent();

    // создаем виджет WidgetSprite для прицела
    sprite = new WidgetSprite(screenGui, crosshairImage);
    // устанавливаем размер спрайта
    sprite.Width = crosshairSize;
    sprite.Height = crosshairSize;

    // добавляем спрайт к GUI так, чтобы он всегда был посередине экрана и поверх всех остальных виджетов
    screenGui.AddChild(sprite, Gui.ALIGN_CENTER | Gui.ALIGN_OVERLAP);
    // привязываем время жизни виджета к миру
    sprite.Lifetime = Widget.LIFETIME.WORLD;


    ${#HL}$ // добавляем виджет WidgetLabel для отображения здоровья игрока, устанавливаем его положение размер шрифта
    label = new WidgetLabel(screenGui, "");
    label.FontSize = 50;
    label.SetPosition(10,10);

    // добавляем виджет к GUI
    screenGui.AddChild(label, Gui.ALIGN_CENTER | Gui.ALIGN_OVERLAP);
    // привязываем время жизни виджета к миру
    label.Lifetime = Widget.LIFETIME.WORLD;${HL#}$

}


${#HL}$ // обновление текущего уровня здоровья игрока
public void UpdateHealthInfo(int health)
{
    label.Text = "Health: " + health.ToString();
}${HL#}$
Последнее обновление: 04.04.2024
Build: ()