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?
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);*