How to make letters fall from sky like snow?

Hi,

Unity newbie here.

I am working on a VR project for school in which the user will enter the mind of a poet and sort of depicts the creative process. I am trying to make the letters fall from the sky, as the poem is about snow and in another scene they see snow falling.

I know how to use the particle system, but do I have to make several independent particles with letters as materials and then put them into the scene? I think this may put a huge strain on Unity. Is there another way to do this/best way to do this? Do I need to script this?

Thanks!

Here’s a way you could do it. Just create a script named LetterRain.cs and add this to it, then add that to a gameobject in your scene.
This is far from perfect, but it works and does what I believe you are looking for. You can tweak the startPosMax and starPosMin, and probably set those positions based on the current camera location.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class LetterRain : MonoBehaviour {
 

	private List<GameObject> letterPool; // Creating a pool of objects is the most memory efficient way to handle things like this. No new memory will be allocated during runtime.
    private List<GameObject> lettersAlive; //A list of the letters currently alive. 
	private int poolSize; //Poolsize, will be set based on lenght of poem.
	public string poem = "This is a very nice litle poem. It is about letters raining";
	public Vector3 startPosMax = new Vector3(10, 10, 3); 
	public Vector3 startPosMin = new Vector3(-10, 10, -3);
	public float lettersPerSecond = 10; //How many letters per second. Max is one per frame, see how it's implemented in update.
	public float aliveTime = 2f; //How long each letter should live.

	private float timer = 0; //Timer to keep track of when to add new letters.

	// Use this for initialization
	void Start () {
		CreatePool();
    }

    private void CreatePool(){
		poolSize = poem.Length;
		letterPool = new List<GameObject>();
		lettersAlive = new List<GameObject>();
		for (int i = 0; i < poolSize; i++){
			GameObject particle = new GameObject(); //Create particle
            particle.AddComponent<TextMesh>().text = poem*.ToString(); //Let particle letter be the next one in the poem*
  •  	particle.AddComponent<Rigidbody>();  //Add a rigidbody to the particle*
    
  •  	particle.transform.parent = transform;  //Set the particle as a child of this gameobject, mostly to keep hierarchy cleaner.*
    
  •  	particle.AddComponent<Letter>();    //Add component Letter to keep track of how long it's been alive. This class is written in the same file, check below.*
    

particle.SetActive(false); //Turn it off for now.

  •  	letterPool.Add(particle); //Add to pool*
    
  •  }*
    
  • }*

  • void Update () {*

  •  timer += Time.deltaTime;*
    
  •  if(timer > (1/lettersPerSecond)){ //Doing it this way means the maximum letters per secons will be one each frame.*
    
  •  	timer = 0;  //reset timer*
    
  •  	ShowNewParticle();*
    
  •  }*
    
  •  for (int i = lettersAlive.Count - 1; i >= 0; i--){ //Check if any particles should die. Iterating backwards is always best when removing stuff from a list during iteration.*
    

_ if(lettersAlive*.GetComponent().timeAlive > aliveTime){ //This isn’t very good, GetComponent shouldn’t be called in an update. Figure out a better way to do this if it impacts performance. Perhaps with event from Letter?_
_
ReturnLetterToPool(i);_
_
}_
_
}_
_
}*_

///


/// Returns the letter to pool.
///

/// Index in alive-pool
* private void ReturnLetterToPool(int index){*
* lettersAlive[index].SetActive(false);*
* letterPool.Add(lettersAlive[index]);*
* lettersAlive.RemoveAt(index);*
* }*

///


/// Shows the new particle. Select random from letterPool, remove from that pool and add to alive pool
///

* private void ShowNewParticle(){*
* if(letterPool.Count == 0){*
* Debug.Log(“Pool is empty. Chose a longer poem or less particles per second.”);*
* return;*
* }*
* int index = Random.Range(0, letterPool.Count-1);*
* letterPool[index].transform.position = new Vector3(Random.Range(startPosMin.x, startPosMax.x), Random.Range(startPosMin.y, startPosMax.y), Random.Range(startPosMin.z, startPosMax.z)); //Randomize position*
* letterPool[index].SetActive(true);*
* letterPool[index].GetComponent().velocity = Vector3.zero;*
* letterPool[index].GetComponent().timeAlive = 0;*
* lettersAlive.Add(letterPool[index]);*
* letterPool.RemoveAt(index);*
* }*
}

///


/// Component added to each particle. Normally this would probably be in a seperate file, but I kept it in the same file for ease of use.
/// Should be pretty self explanatory
///

public class Letter : MonoBehaviour{

* public float timeAlive = 0;*
* private Vector3 rotations = new Vector3(3, 12, 50);*

* private void OnEnable()*
* {*

* transform.eulerAngles = new Vector3(Random.Range(0, 360), Random.Range(0, 360), Random.Range(0, 360));*
* }*

* private void Update()*
* {*
* timeAlive += Time.deltaTime;*
_ transform.Rotate(rotations * Time.deltaTime);_

* }*

}

Thank you SO much!