[Résolu] Comment connaître la luminosité à une position particulière ?

Questions à propos du scripting. Hors Shader, GUI, Audio et Mobile.
Avatar de l’utilisateur
jmhoubre
Messages : 851
Inscription : 05 Oct 2019 22:05

[Résolu] Comment connaître la luminosité à une position particulière ?

Message par jmhoubre » 10 Avr 2022 19:08

Bonjour,

Contexte
dans Unity 2020.3.33 URP, j'ai une scène 2D : un donjon constitué de salles rectangulaires et de couloirs les reliant. Pièces et couloirs contiennent des torches sur les murs à des positions aléatoires. Pour ces torches, j'utilise les composants Light2D du type point (ou spot selon la version Unity).
Mon personnage possède une infravision lui permettant de voir (un peu) dans la pénombre, que je souhaite couper quand il y a assez de lumière (certaines pièces peuvent ne pas avoir de torches allumées). J'ai lu un sujet du forum de 2014, qui me renvoie à quelque chose de faisable mais que je souhaite simplifier.

Question
Existe-il une solution plus simple avec l'arrivée d'URP et des Light 2D ?
Dernière édition par jmhoubre le 13 Avr 2022 12:23, édité 1 fois.

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

Re: Comment connaître la luminosité à une position particulière ?

Message par jmhoubre » 13 Avr 2022 12:23

Bonjour,

j'ai fait quelque chose qui me satisfait, même si la formule de l'intensité lumineuse est plutôt empirique.
https://youtu.be/AsEXuDF5u7Y

Le script du personnage :

Code : Tout sélectionner

using System.Collections.Generic;

using TMPro; // Juste pour l'affichage d'une ligne pour le déboguage.

using UnityEngine;
using UnityEngine.Experimental.Rendering.Universal;

public class SwitchInfravision : MonoBehaviour
{
	public static List<Light2D> lights = new List<Light2D> ();

	// Inutile de calculer ceci à chaque update...
	[SerializeField] private float brightnessComputingRate = 0.2f;
	// En-dessous de ce seuil, l'infravision se déclenche.
	[SerializeField, Range (0.1f, 1f)] private float infravisionThreshold = 0.3f;

	[SerializeField] private Light2D infravisionLight;

	// Debug.
	private TMP_Text lightNumber;
	private TMP_Text lightIntensity;

	private void Start ()
	{
		lightNumber = GameObject.Find ("LightsNumber").GetComponent<TMP_Text> ();
		lightIntensity = GameObject.Find ("Intensity").GetComponent<TMP_Text> ();
		InvokeRepeating (nameof (CalculateBrightness), brightnessComputingRate, brightnessComputingRate);
	}

	private void CalculateBrightness ()
	{
		Vector3 playerPosition = transform.position;
		float intensity;
		lightNumber.text = $"{lights.Count} lumières.";

		if (lights.Count == 0)
		{
			intensity = 0f;
		}
		else
		{
			float totalIntensity = 0f;
			foreach (Light2D light in lights)
			{
				// L'intensité de la Light2D n'apparait pas, car mes torches sont paramétrées à 1.
				float factor = 1 / (light.pointLightOuterRadius - 1);
				float distance = (playerPosition - light.gameObject.transform.position).magnitude;

				if (distance <= light.pointLightInnerRadius)
				{
					// En-dessous de Inner Radius, l'intensité vaut 1.
					totalIntensity++;
					continue;
				}
				else if (distance > light.pointLightOuterRadius)
				{
					// Au-dessus de Outer Radius, l'intensité vaut 0.
					continue;
				}
				else
				{
					// Entre les deux, on ajoute une estimation de l'intensité lumineuse.
					totalIntensity += (light.pointLightOuterRadius - distance) / distance * distance * factor;
				}
			}
			intensity = totalIntensity;
			lightIntensity.text = $"Intensité : {intensity}";
		}

		infravisionLight.enabled = intensity < infravisionThreshold;
	}
}
Le script des torches :

Code : Tout sélectionner

using UnityEngine;
using UnityEngine.Experimental.Rendering.Universal;

public class TorchTrigger : MonoBehaviour
{
	Light2D torchLight;

	private void Awake ()
	{
		torchLight = gameObject.GetComponentInChildren<Light2D> ();
	}

	private void OnTriggerEnter2D (Collider2D collision)
	{
		if (collision.CompareTag ("Player")) { SwitchInfravision.lights.Add (torchLight); }
	}

	private void OnTriggerExit2D (Collider2D collision)
	{
		if (collision.CompareTag ("Player")) { SwitchInfravision.lights.Remove (torchLight); }
	}
}

Répondre

Revenir vers « Scripting »