Skip to content

Instantly share code, notes, and snippets.

@N-Carter
Created January 2, 2012 13:05
Show Gist options
  • Select an option

  • Save N-Carter/1550606 to your computer and use it in GitHub Desktop.

Select an option

Save N-Carter/1550606 to your computer and use it in GitHub Desktop.
Raycast rain particle system
using UnityEngine;
using System.Collections;
public class Rain : MonoBehaviour
{
[SerializeField] protected ParticleEmitter m_ParticleEmitter;
[SerializeField] protected Splashes m_Splashes;
[SerializeField] protected float m_Width = 10.0f;
[SerializeField] protected LayerMask m_CollisionMask;
[SerializeField] protected float m_RayLengthFactor = 1.0f;
protected Particle[] m_Particles;
[SerializeField] protected float m_RaindropSpeed = 30.0f;
[SerializeField] protected float m_MaxRaindropDuration = 2.0f;
[SerializeField] protected float m_MaxRainAngle = 30.0f;
protected Quaternion m_RainRotation;
[SerializeField] protected float m_RainSpacing = 0.1f;
[SerializeField] protected float m_DropInterval = 0.02f;
protected float m_LastDropEmissionTime;
protected bool m_AlternateRow = false;
protected WindArea[] m_WindAreas;
protected void Start()
{
m_WindAreas = (WindArea[])FindObjectsOfType(typeof(WindArea));
}
protected void Update()
{
float spacing = m_Width * m_RainSpacing * 0.5f;
Vector3 position = transform.position;
position.x = Mathf.Floor(Camera.main.transform.position.x / spacing) * spacing + Time.time % spacing;
if(m_AlternateRow)
position.x += spacing * 0.5f;
transform.position = position;
m_RainRotation = Quaternion.AngleAxis((Mathf.Sin(Time.time) + Mathf.Sin((Time.time + 0.25f) * 0.41f)) * 0.5f * m_MaxRainAngle, Vector3.forward);
if(Time.time > m_LastDropEmissionTime + m_DropInterval)
{
AddRowOfRaindrops(m_RainSpacing);
m_LastDropEmissionTime = Time.time;
m_AlternateRow = !m_AlternateRow;
}
m_Particles = m_ParticleEmitter.particles;
MoveParticles(Time.deltaTime);
m_ParticleEmitter.particles = m_Particles;
}
protected void MoveParticles(float deltaTime)
{
for(int i = 0; i < m_Particles.Length; ++i)
{
foreach(var windArea in m_WindAreas)
m_Particles[i].velocity += windArea.RainForceForPoint(m_Particles[i].position) * deltaTime;
m_Particles[i].position += m_Particles[i].velocity * deltaTime;
m_Particles[i].energy -= deltaTime;
Vector3 direction = m_Particles[i].velocity * Time.deltaTime * m_RayLengthFactor;
// Debug.DrawRay(m_Particles[i].position - direction, direction, Color.cyan, 0.0f);
RaycastHit hit;
if(Physics.Raycast(m_Particles[i].position - direction, direction, out hit, m_Particles[i].velocity.magnitude * deltaTime, m_CollisionMask))
{
m_Particles[i].energy = 0.0f;
m_Splashes.AddSplash(hit.point, hit.normal, 0.2f);
if(hit.collider.gameObject.layer == Layer.WettableIndex)
{
if(hit.rigidbody.gameObject.layer == Layer.PlayerIndex)
Game.Wetness += 1.0f;
hit.rigidbody.SendMessage("HitByRain");
}
}
}
}
protected void AddRaindrop()
{
m_ParticleEmitter.Emit(GetRandomStartPosition(), m_RainRotation * (Vector3.up * -m_RaindropSpeed),
Random.Range(m_ParticleEmitter.minSize, m_ParticleEmitter.maxSize), m_MaxRaindropDuration, Color.white);
}
protected void AddRowOfRaindrops(float spacing)
{
for(float x = -1.0f; x <= 1.0f; x += spacing)
{
m_ParticleEmitter.Emit(GetStartPositionFromFactor(x), m_RainRotation * (Vector3.up * -m_RaindropSpeed),
Random.Range(m_ParticleEmitter.minSize, m_ParticleEmitter.maxSize), m_MaxRaindropDuration, Color.white);
}
}
protected Vector3 GetRandomStartPosition()
{
return GetStartPositionFromFactor(Random.Range(-1.0f, 1.0f));
}
protected Vector3 GetStartPositionFromFactor(float factor)
{
return transform.position + transform.right * m_Width * 0.5f * factor;
}
protected void OnDrawGizmosSelected()
{
Vector3 halfWidth = transform.right * m_Width;
Gizmos.color = Color.blue;
Gizmos.DrawLine(transform.position + halfWidth * -0.5f, transform.position + halfWidth * 0.5f);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment