- Home /
Prefab Instantiation
I am currently working on a script to control a laser beam, that on hit with certain objects emits a particle effect at the point of collision.
However the issue is I am unable to figure out how to only Instantiate a single emitter at a time so as not to have too many draw calls.
I have tried several different methods, including WaitForSeconds(), InvokeRepeating() and using bools but to no avail.
Here is the code as it stands, it Instatiates a single particle emitter every frame at the moment. I am probably being an idiot and the solution is staring me in the face but anyway you'll find the code below.
public class LaserWall : MonoBehaviour
{
RaycastHit hitCheck;
public float laserLength = 20.0f;
public GameObject hitEffect;
public GameObject spaceShip;
void Start ()
{
GetComponent<LineRenderer> ().SetPosition (1, Vector3.forward * laserLength);
}
void FixedUpdate ()
{
LaserCollisionCheck();
}
void LaserCollisionCheck ()
{
if (Physics.Raycast (transform.position, -Vector3.up, out hitCheck, laserLength) && GetComponent<LineRenderer> ().enabled == true) {
Debug.Log ("Hit");
if (hitCheck.collider.name == "space_ship") {
Instantiate (hitEffect, hitCheck.point, Quaternion.identity);
GetComponent<LineRenderer> ().SetPosition (1, Vector3.forward * hitCheck.distance);
//spaceShip.GetComponent<SpaceshipController>().Explode();
}
if (hitCheck.collider.name == "laser_wall") {
Instantiate (hitEffect, hitCheck.point, Quaternion.identity);
GetComponent<LineRenderer> ().SetPosition (1, Vector3.forward * laserLength);
}
}
}
}
Thanks in advance to anyone that can help, just to clarify I am trying to reduce the number of particle emitters being created to around 1 per second.
~ byteCrunch
I'd recommend you to have a look at the Emit() function, if the object only is a particle then it's unnecessary to instantiate new content (mainly for performance reasons). To do something at a certain given time repeatedly you could have a look at this example script. I wish I could give you an example script but I tend to be quite lost when it comes to C#.
And that is where @aldonaletto swoops in and saves this Friday!
Answer by aldonaletto · Mar 30, 2012 at 01:33 PM
If you want to create a kind of "laser cut" effect, where the particles are emitted while the laser is hitting something, it would be better to place the particle emitter in the scene with emit = false (you may child it to the laser weapon), and when the laser hits something, set emit to true. There are also other wise things to do, like caching the line renderer in a variable and use Update instead of FixedUpdate:
... public ParticleEmitter hitEffect; // drag the particle here public GameObject spaceShip; LineRenderer lineRendr; // line renderer reference
void Start ()
{
lineRendr = GetComponent< LineRenderer>(); // cache the line renderer
lineRendr.SetPosition (1, Vector3.forward * laserLength);
}
void Update () // use Update instead of FixedUpdate
{
LaserCollisionCheck();
}
void LaserCollisionCheck ()
{
if (Physics.Raycast (transform.position, -Vector3.up, out hitCheck, laserLength) && lineRendr.enabled) {
Debug.Log ("Hit");
if (hitCheck.collider.name == "space_ship") {
hitEffect.transform.position = hitCheck.point;
hitEffect.emit = true;
lineRendr.SetPosition (1, Vector3.forward * hitCheck.distance);
//spaceShip.GetComponent<SpaceshipController>().Explode();
}
else
if (hitCheck.collider.name == "laser_wall") {
hitEffect.transform.position = hitCheck.point;
hitEffect.emit = true;
lineRendr.SetPosition (1, Vector3.forward * laserLength);
}
else { // nothing hit, set effect to false:
hitEffect.emit = false;
}
}
}
Update - Reading you code again I understand it now, I forgot to assign the emitter.
Update 2 - Ok still couldnt get Aldo's code to work, not really sure why, the emitter just doesnt start.
Thanks for the example Aldo, though for me atleast the code didnt seem to do the job, the emitters didnt switch on and off upon collision, this is the code I came up with and it works but I am not sure its the best solution.
Since now it only checks for collisions once every 0.1 seconds, though I think this should be enough, except for maybe very fast moving objects.
public class LaserWall : $$anonymous$$onoBehaviour
{
RaycastHit hitCheck;
public float laserLength = 20.0f;
public GameObject hitEffect;
public GameObject spaceShip;
LineRenderer lineRender;
// Use this for initialization
void Start ()
{
lineRender = GetComponent<LineRenderer>();
lineRender.SetPosition (1, Vector3.forward * laserLength);
InvokeRepeating ("LaserCollisionCheck", 0.0f, 0.1f);
}
// Update is called once per frame
void FixedUpdate ()
{
}
void LaserCollisionCheck ()
{
if (Physics.Raycast (transform.position, -Vector3.up, out hitCheck, laserLength) && GetComponent<LineRenderer> ().enabled == true) {
//Debug.Log ("Hit");
if (hitCheck.collider.name == "space_ship") {
//Instantiate (hitEffect, hitCheck.point, Quaternion.identity);
//lineRender.SetPosition (1, Vector3.forward * hitCheck.distance);
UpdateParticles();
//spaceShip.GetComponent<SpaceshipController>().Explode();
}
if (hitCheck.collider.name == "laser_wall") {
//Instantiate (hitEffect, hitCheck.point, Quaternion.identity);
//lineRender.SetPosition (1, Vector3.forward * laserLength);
UpdateParticles();
}
}
}
void UpdateParticles()
{
Instantiate (hitEffect, hitCheck.point, Quaternion.identity);
lineRender.SetPosition (1, Vector3.forward * hitCheck.distance);
}
}
As I mentioned below I cant seem to get your code to work. The LineRenderer updates the length but the particle emitter doesnt start.
Update - Ok I got it working I had to adjust some things, like assigning the emitter through code, and I also realised the particle emitter was set to one shot. $$anonymous$$anaged to more than half the draw calls now. Still cannot believe I missed such a simple solution, thanks for the help Aldo.