Le player :
- capsule collider2D + rigidbody2D pour détecter les collisions
- Light2D (nécessite le package Universel Render Pipeline)
- script PlayerMovement (renseigner la vitesse)
Code : Tout sélectionner
using UnityEngine;
/// <summary>
/// Gestion du mouvement de joueur.
/// </summary>
public class PlayerMovement : MonoBehaviour
{
[SerializeField] private float speed = 5f;
private void Update ()
{
HandleMovement ();
}
private void HandleMovement ()
{
float xInput = Input.GetAxis ("Horizontal");
Vector2 position = transform.position;
position.x += speed * Time.deltaTime * xInput;
// Limite le mouvement à l'écran (pour ma résolution).
position.x = Mathf.Clamp (position.x, -8f, 8f);
transform.position = position;
}
}
- script PlayerHealth (renseigner santé mini et maxi)
Code : Tout sélectionner
using UnityEngine;
/// <summary>
/// Gestion de la santé et des soins/dégâts.
/// </summary>
public class PlayerHealth : MonoBehaviour
{
[SerializeField] private float minHealth = 0f;
[SerializeField] private float maxHealth = 100f;
private float currentHealth;
private PlayerLight playerLight;
private void Awake ()
{
playerLight = GetComponent<PlayerLight> ();
}
private void Start ()
{
// On divise par 2 pour tester plus vite.
currentHealth = maxHealth / 2;
// Pour éviter une éventuelle division par zéro.
if (minHealth == maxHealth)
{
minHealth = 0f;
maxHealth = 50f;
}
// On ne modifie l'intensité que dans le Start pour être sûr que PlayerLight a fini son Awake.
playerLight.LightUpdate ();
}
public void TakeZoneEffect (float amount)
{
currentHealth += amount;
// Limite la santé à minHealth et maxHealth.
currentHealth = Mathf.Clamp (currentHealth, minHealth, maxHealth);
playerLight.LightUpdate ();
if (currentHealth <= minHealth)
{
Die ();
}
}
public float GetCurrentHealth => currentHealth;
public float GetMinHealth => minHealth;
public float GetMaxHealth => maxHealth;
private void Die ()
{
//Destroy (gameObject);
}
}
- script PlayerLight (renseigner light mini et maxi)
Code : Tout sélectionner
using UnityEngine;
using UnityEngine.Experimental.Rendering.Universal;
/// <summary>
/// Gestion de la lumière du joueur.
/// </summary>
public class PlayerLight : MonoBehaviour
{
[Header ("Lumière")]
[SerializeField] private float minLight;
[SerializeField] private float maxLight;
private PlayerHealth playerHealth;
private Light2D playerLight;
private void Awake ()
{
playerHealth = gameObject.GetComponent<PlayerHealth> ();
playerLight = GetComponent<Light2D> ();
}
public void LightUpdate ()
{
// Application d'une règle de 3 pour calculer une intensité en rapport avec la santé.
playerLight.intensity = minLight + (
(playerHealth.GetCurrentHealth - playerHealth.GetMinHealth) * (maxLight - minLight)
/ (playerHealth.GetMaxHealth - playerHealth.GetMinHealth));
// On peut également renforcer l'effet en jouant sur le rayon extérieur de la lumière
// (en gros, le range des lumières 3D).
playerLight.pointLightOuterRadius = playerLight.intensity;
}
}
Les zones d'effet sont des sprites square avec BoxCollider2D en mode trigger, et le script ZoneEffect (renseigner le nombre de PV par seconde, négatif pour des dégâts, positif pour des soins). Le matérial a pour shader URP/Lit surface type à transparent. Pour accélérer l'effet, on peut soit augmenter EffectPerSecond, soir ajouter une vitesse dans le script (dans la ligne du deltaTime).
Code : Tout sélectionner
using UnityEngine;
/// <summary>
/// Gestion des effets de zone.
/// </summary>
public class ZoneEffect : MonoBehaviour
{
[Tooltip("Nombre négatif pour des dégâts, positif pour des soins")]
[SerializeField] private float effectPerSecond = 0f;
private void OnTriggerStay2D (Collider2D _collider)
{
// Ne pas oublier de passer les collider en mode Trigger.
// Ne pas oublier de passer le SleepingMode du rigidbody2D du player à NeverSleep.
if (_collider.CompareTag ("Player"))
{
_collider.gameObject.GetComponent<PlayerHealth> ().TakeZoneEffect (effectPerSecond * Time.deltaTime);
}
}
}
Il y a une UI, avec deux textes (TextMeshPro) et un script pour mettre à jour l'affichage.
Code : Tout sélectionner
using UnityEngine;
using UnityEngine.Experimental.Rendering.Universal;
using TMPro;
/// <summary>
/// Affiche l'intensité et la santé. Utilise TextMeshPro.
/// </summary>
public class DebugUI : MonoBehaviour
{
[SerializeField] private TMP_Text lightIntensityText;
[SerializeField] private TMP_Text playerHealthText;
private PlayerHealth playerHealth;
private Light2D playerLight;
private void Awake ()
{
GameObject player = GameObject.Find ("Player");
playerHealth = player.GetComponent<PlayerHealth> ();
playerLight = player.GetComponent<Light2D> ();
}
// L'utilisation d'un delegate Action serait plus pertinent.
private void Update ()
{
lightIntensityText.text = $"Intensité : {playerLight.intensity:0.00}";
playerHealthText.text = $"Santé : {playerHealth.GetCurrentHealth:0.00}";
}
}
Ne pas oublier une image de fond, de préférence plutôt sombre.
Pour l'ambiance, j'ai ajouté une global light de couleur rouge, elle est superflue.