[DB]Lier l'intensité d'une PointLight avec la HealthBar

Questions à propos du scripting. Hors Shader, GUI, Audio et Mobile.
Gérard le Graviton
Messages : 5
Inscription : 04 Juil 2021 18:35

Re: [DB]Lier l'intensité d'une PointLight avec la HealthBar

Message par Gérard le Graviton » 08 Juil 2021 00:52

jmhoubre a écrit :
06 Juil 2021 17:31
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.
bonsooooooooooir~

merci énormément pour toute vos réponses qui m'ont permis d'avancer dans mon projet mais également merci infiniment à @jmhoubre pour les scripts partagés !

Je les ai repris quasiment à la lettre et grâce à ses scripts la mécanique de lumière lié aux points de vies fonctionne nickel ***

J'ai cependant une micro interrogation concernant le radius:
j'ai recopié la même ligne que tu as écrite " playerLight.pointLightOuterRadius = playerLight.intensity; " cependant lorsque je lance le jeu le radius de la Light2D se met automatiquement à zéro et donc il n'y a plus de lumière O.o" ( il n'est d'ailleurs pas modifiable in game )
pour le moment je l'ai retiré pour avoir la lumière fonctionnel et c'est déjà très bien ainsi !

mais si tu (@ jmhoubre) repasses par ici ce sera vraiment génial que tu éclaircisses ce micro soucis ( vu que c'est toi qui a écrit ces scripts tu dois surement les maitriser du bout des doigts ) ~~

encore une fois je remercie tout ce qui sont venus à mon secours vous venez de refaire ma semaine je vais pouvoir continuer à travailler plus sereinement sur la suite de mon projet !

je vous souhaite une agréable soirée/journée <3

Avatar de l’utilisateur
jmhoubre
Messages : 851
Inscription : 05 Oct 2019 22:05

Re: [DB]Lier l'intensité d'une PointLight avec la HealthBar

Message par jmhoubre » 08 Juil 2021 11:10

Bonjour,

difficile de répondre, d'autant que chez moi cela fonctionne très bien (revoir la vidéo).

Es-tu sûr d'avoir recopié les scripts à l'identique ? D'avoir conservé les valeurs par défaut (au besoin, enlève le composant Light2D et remet-le) ? De ne pas modifier la valeur de l'intensité de la Light2D ailleurs (au besoin, désactive tous les scripts sauf les 5 que j'ai partagés) ?

Répondre

Revenir vers « Scripting »