123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216 |
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- namespace Funly.SkyStudio
- {
- // GPU instanced lightning bolt render for a specific art style item.
- [RequireComponent(typeof(AudioSource))]
- public class LightningRenderer : BaseSpriteInstancedRenderer
- {
- static List<LightningSpawnArea> m_SpawnAreas = new List<LightningSpawnArea>();
- float m_LightningProbability;
- float m_NextSpawnTime;
- SkyProfile m_SkyProfile;
- LightningArtItem m_Style;
- float m_TimeOfDay;
- AudioSource m_AudioSource;
- float m_LightningIntensity;
- float m_ThunderSoundDelay;
- float m_SpawnCoolDown;
- // Frequency in time that we'll evaluate lighting probability at, so we're frame rate independant.
- const float k_ProbabiltyCheckInterval = .5f;
- private void Start()
- {
- // Verify GPU instancing is supported.
- if (SystemInfo.supportsInstancing == false) {
- Debug.LogError("Can't render lightning since GPU instancing is not supported on this platform.");
- enabled = false;
- return;
- }
- m_AudioSource = GetComponent<AudioSource>();
- }
- protected override Bounds CalculateMeshBounds()
- {
- return new Bounds(Vector3.zero, new Vector3(500, 500, 500));
- }
- // Allocate a new data item to track a sprite mesh rendering.
- protected override BaseSpriteItemData CreateSpriteItemData()
- {
- return new BaseSpriteItemData();
- }
- // Hook to let client prepare and check if we should render before trying.
- protected override bool IsRenderingEnabled()
- {
- if (m_SkyProfile == null || m_SkyProfile.IsFeatureEnabled(ProfileFeatureKeys.LightningFeature) == false) {
- return false;
- }
- if (m_SpawnAreas.Count == 0) {
- return false;
- }
- return true;
- }
- // Select where the next sprite will be rendered at.
- protected override void CalculateSpriteTRS(BaseSpriteItemData data, out Vector3 spritePosition, out Quaternion spriteRotation, out Vector3 spriteScale)
- {
- LightningSpawnArea area = GetRandomLightningSpawnArea();
-
- float boltScale = CalculateLightningBoltScaleForArea(area);
- spriteScale = new Vector3(boltScale, boltScale, boltScale);
- spritePosition = GetRandomWorldPositionInsideSpawnArea(area);
-
- // Always face the sprite textures towards the main camera.
- if (Camera.main == null) {
- Debug.LogError("Can't billboard lightning to viewer since there is no main camera tagged.");
- spriteRotation = area.transform.rotation;
- } else {
- spriteRotation = Quaternion.LookRotation(spritePosition - Camera.main.transform.position, Vector3.up);
- }
- }
- // Configure a new sprite item data object properties, (could be new or recycled).
- protected override void ConfigureSpriteItemData(BaseSpriteItemData data)
- {
- // A new bolt is getting prepared, so let's schedule the sound effect.
- if (m_SkyProfile.IsFeatureEnabled(ProfileFeatureKeys.ThunderFeature)) {
- Invoke("PlayThunderBoltSound", m_ThunderSoundDelay);
- }
- }
- // Setup any per-instance data you need to pass.
- protected override void PrepareDataArraysForRendering(int instanceId, BaseSpriteItemData data)
- {
- // No custom properties.
- }
- protected override void PopulatePropertyBlockForRendering(ref MaterialPropertyBlock propertyBlock)
- {
- propertyBlock.SetFloat("_Intensity", m_LightningIntensity);
- }
- protected override int GetNextSpawnCount()
- {
- // Cool down from last spawn.
- if (m_NextSpawnTime > Time.time) {
- return 0;
- }
- m_NextSpawnTime = Time.time + k_ProbabiltyCheckInterval;
- if (Random.value < m_LightningProbability) {
- m_NextSpawnTime += m_SpawnCoolDown;
- return 1;
- }
- return 0;
- }
- public void UpdateForTimeOfDay(SkyProfile skyProfile, float timeOfDay, LightningArtItem artItem)
- {
- m_SkyProfile = skyProfile;
- m_TimeOfDay = timeOfDay;
- m_Style = artItem;
- if (m_SkyProfile == null) {
- Debug.LogError("Assigned null sky profile!");
- return;
- }
- if (m_Style == null) {
- Debug.LogError("Can't render lightning without an art item");
- return;
- }
- SyncDataFromSkyProfile();
- }
- void SyncDataFromSkyProfile()
- {
- m_LightningProbability = m_SkyProfile.GetNumberPropertyValue(ProfilePropertyKeys.LightningProbabilityKey, m_TimeOfDay);
- m_LightningIntensity = m_SkyProfile.GetNumberPropertyValue(ProfilePropertyKeys.LightningIntensityKey, m_TimeOfDay);
- m_SpawnCoolDown = m_SkyProfile.GetNumberPropertyValue(ProfilePropertyKeys.LightningStrikeCoolDown, m_TimeOfDay);
- m_ThunderSoundDelay = m_SkyProfile.GetNumberPropertyValue(ProfilePropertyKeys.ThunderSoundDelayKey, m_TimeOfDay);
- // Scale the probability for this art style.
- m_LightningProbability *= m_Style.strikeProbability;
- m_LightningIntensity *= m_Style.intensity;
- m_SpriteSheetLayout.columns = m_Style.columns;
- m_SpriteSheetLayout.rows = m_Style.rows;
- m_SpriteSheetLayout.frameCount = m_Style.totalFrames;
- m_SpriteSheetLayout.frameRate = m_Style.animateSpeed;
- m_SpriteTexture = m_Style.spriteSheetTexture;
- m_TintColor = m_Style.tintColor * m_SkyProfile.GetColorPropertyValue(ProfilePropertyKeys.LightningTintColorKey, m_TimeOfDay);
- modelMesh = m_Style.mesh;
- renderMaterial = new Material(m_Style.material);
- }
- private LightningSpawnArea GetRandomLightningSpawnArea()
- {
- if (m_SpawnAreas.Count == 0) {
- return null;
- }
- int randomSpawnIndex = Mathf.RoundToInt(Random.Range(0, m_SpawnAreas.Count)) % m_SpawnAreas.Count;
- return m_SpawnAreas[randomSpawnIndex];
- }
- private void PlayThunderBoltSound()
- {
- if (m_Style.thunderSound != null) {
- m_AudioSource.volume = m_SkyProfile.GetNumberPropertyValue(ProfilePropertyKeys.ThunderSoundVolumeKey, m_TimeOfDay);
- m_AudioSource.PlayOneShot(m_Style.thunderSound);
- }
- }
- public static void AddSpawnArea(LightningSpawnArea area)
- {
- if (m_SpawnAreas.Contains(area) == false) {
- m_SpawnAreas.Add(area);
- }
- }
- public static void RemoveSpawnArea(LightningSpawnArea area)
- {
- if (m_SpawnAreas.Contains(area)) {
- m_SpawnAreas.Remove(area);
- }
- }
- Vector3 GetRandomWorldPositionInsideSpawnArea(LightningSpawnArea area)
- {
- float xPos = Random.Range(-area.lightningArea.x, area.lightningArea.x) / 2.0f;
- float zPos = Random.Range(-area.lightningArea.z, area.lightningArea.z) / 2.0f;
- float yPos = 0;
- if (m_Style.alignment == LightningArtItem.Alignment.TopAlign) {
- yPos = (area.lightningArea.y / 2.0f) - (m_Style.size / 2.0f);
- }
- return area.transform.TransformPoint(new Vector3(xPos, yPos, zPos));
- }
- float CalculateLightningBoltScaleForArea(LightningSpawnArea area)
- {
- if (m_Style.alignment == LightningArtItem.Alignment.ScaleToFit) {
- return area.lightningArea.y / 2.0f;
- } else {
- return m_Style.size;
- }
- }
- }
- }
|