Unity 5 updates

Hey,
Here are my updates to get this lessons code working in Unity 5

void PuffSmoke(){
	GameObject smokePuff = Object.Instantiate (smoke, this.transform.position, Quaternion.identity) as GameObject;
	ParticleSystem ps = smokePuff.GetComponent<ParticleSystem> ();
	var main = ps.main;
	main.startColor = this.GetComponent<SpriteRenderer> ().color;
}

Any suggestions/improvements very welcome.
/John

4 Likes

You can write the code even this way:

GameObject smokePuff = Instantiate (smoke, transform.position, Quaternion.identity); ParticleSystem.MainModule main = smokePuff.GetComponent<ParticleSystem>().main; main.startColor = GetComponent<SpriteRenderer>().color;

Less clutter around with all those redundant Object/this keywords. :wink:

3 Likes

Can someone explain why the ParticleSystem’s main has to be assigned to a variable first, and why ps.main.startColor doesn’t work? If you try, it says “Cannot modify the return value of ParticleSystem.main because it is not a variable”, and I don’t understand how that is.

If someone could break down what this line is doing so that i understand it better that would be great :slight_smile:
Im guessing its similar to defining a variable “main” and using it but with unity system stuff??

this totally worked for me. i have been trying to go through the course on 5.5.1f1 and update the code to understand how to implement these principles as of now. thanks a bunch :smiley:

here is my comment code. it’s usually convoluted because i talk to myself in the code to help me understand it

//we create a variable of type GameObject named smokePuff and give it the value of an instantiated particle effect smoke cloud
//the smoke has it’s transform set to the instance of the brick that is creating it, as well as the rotation.
GameObject smokePuff = Instantiate(smoke, transform.position, Quaternion.identity);

//this is wierd, ok so first we have to create a variable of type ParticleSystem.MainModule and call it main
//then we set’s value to the result of smokePuff’s ParticleSystem.main
ParticleSystem.MainModule main = smokePuff.GetComponent().main;

//then on it’s “main” section in the inspector, the startColor, we set that to the same value that the brick is using as it’s color
main.startColor = GetComponent().color;

I was able to do away without even putting in “main” into the code.

smokePuff.GetComponent ().startColor = gameObject.GetComponent ().color;

This right here works totally fine for me.

That will vary depending on Unity version

I’m using the most current version of Unity 5.

Hi Andrew,

That’s quite interesting, in all of the documentation (I’ve read) GetComponent() will either return the component of the type specified, or null if one is not attached to the game object.

Oh, sorry, that was a typo. In my code, I actually do put “GetComponent()”. My point, though, was that I didn’t need to put “.main” before “.startColor” and it works fine, even though there’s no option to autocomplete it.

Hi Andrew,

It wasn’t the space between the brackets I meant, it was that you do not pass a type to the GetComponent method, e.g.

GetComponent<type>()

Or

GetComponent(typeof(type))

The documentation suggests that if a component of the specified type cannot be found the GetComponent method will return null. As you are not specifying a type I would have expected a compilation error perhaps, but maybe it is assuming you are passing in null, and subseauently null is being returned, still seems odd.

I may have a look at this later as I am curious to know what the GetComponent method in this case is actually returning, you would imagine main so that the startColor variable was accessible.

The heck? For some reason it’s not putting in the “ParticleSystem” or the “<>” around it. This time, I’m POSITIVE I typed it in on my last reply, but for some reason it keeps on omitting it when I post the reply. I wasn’t referring to the space between the parenthesis, I was saying that I did put in the “ParticleSystem” as the type to the GetComponent method. But for some reason whenever I type it, it doesn’t show up.

This is a test to see if it does it again: GetComponent()

It did it again! I don’t know what’s going on, some sort of issue with the formatting.

oh, lol…

Having just looked at your post, you are not formatting the text as code, and as the forum supports HTML as well as BBCode and MarkDown, your < and > characters are getting interpreted as HTML.

You can escape them with a backslash, or, use the pre-formatted code option. :slight_smile:

<many><particles><in><my><system>

:wink:


See also;

Hey guys,

I tried both codes on this thread, neither are working - keeps saying The type name ‘MainModule’ does not exist in the type ‘UnityEngine.ParticleSystem’. Here’s what I’ve also tried:

GameObject smokePuff = Instantiate(benParticles, transform.position, Quaternion.identity) as GameObject;
ParticleSystem smokePuffParticles = smokePuff.GetComponent<ParticleSystem>();
smokePuffParticles.startColor = GetComponent<SpriteRenderer>().color;

The above SEEMS like it should work, but as soon as a brick is destroyed, it gives a Null reference error. Anyone have insights?

Your issue will be the order of events.

You hit a brick, deatroy it, make some particles and then try to set the colour to that of the brick… which you just destroyed… using the Destroy() method, not just in the game.

Consider destroying the brick after the creation of the particles, or, store the brick colour as a variable and then use that for the particles instead of referencing the brick.

Hope this helps.

Hi Rob,

Thanks for your insights. I looked over my code, and it looks like it is indeed set up to first get the color of the brick, spawn the particles, and destroy the brick last. I also tested removing the destroy command completely, still getting the null reference error. See full code below:

void HandleHits()
{
	timesHit++;
	maxHits = hitSprites.Length + 1;

	if(timesHit >= maxHits)
	{
		myGreatLevelManager.BrickWrecked();
		myAudioSource.clip = myCrack;
		GetComponent<BoxCollider2D>().enabled = false;
		GetComponent<SpriteRenderer>().enabled = false;

		PuffSmoke();
	} 
	else
	{
		LoadSprites();
	}
}

void PuffSmoke()
{
	/* my attempt at this... kept saying no object reference */
	GameObject smokePuff = Instantiate(benParticles, transform.position, Quaternion.identity) as GameObject;
	ParticleSystem smokePuffParticles = smokePuff.GetComponent<ParticleSystem>();
	smokePuffParticles.startColor = GetComponent<SpriteRenderer>().color;
	Destroy(gameObject, myAudioSource.clip.length + 1f);
}

Thanks!!

The sprite renderer is being disabled in HandleHits() before you then tdy to access it in PuffSmoke().

Tried commenting out disabling the sprite renderer, same problem. I did more testing and found that the error seems to lie not with accessing the sprite renderer of the brick, but accessing the sprite renderer of the spawned-in smokePuff object that has a particle system. I tested this by throwing in a Debug.Log command after every line of code in the PuffSmoke() method and found that the execution was never getting past the line of code that tries to access the ParticleSystem of the spawned-in object. I’m running Unity 5.3.4 if that helps:

using UnityEngine;
using System.Collections;

public class BrickScript : MonoBehaviour {

public static int bricksTotal;
public static int bricksDestroyed;

public Sprite[] hitSprites;
public int maxHits;
public AudioClip myCrack;

private int timesHit = 0;
private LevelManager myGreatLevelManager;
private ParticleSystem myParticles;
public ParticleSystem benParticles;

private AudioSource myAudioSource;

// Use this for initialization
void Start () 
{
	myAudioSource = GetComponent<AudioSource>();
	myGreatLevelManager = FindObjectOfType<LevelManager>();
	myParticles = GetComponent<ParticleSystem>();

	if (tag == "Breakable")
		bricksTotal++;
}

void OnCollisionExit2D ()
{
	myAudioSource.clip = myCrack;
	myAudioSource.Play();
	//AudioSource.PlayClipAtPoint(myCrack, transform.position);
	if(tag == "Breakable")
		HandleHits();
}

void HandleHits()
{
	timesHit++;
	maxHits = hitSprites.Length + 1;

	if(timesHit >= maxHits)
	{
		myGreatLevelManager.BrickWrecked();
		myAudioSource.clip = myCrack;

		PuffSmoke();

		/*
		if (bricksDestroyed >= bricksTotal) 
		{
			myGreatLevelManager.LevelWon();
		}
		else
		{
			Destroy(gameObject);
		}*/
	} 
	else
	{
		LoadSprites();
	}
}

void PuffSmoke()
{
	/* my attempt at this... kept saying no object reference */
	Debug.Log("PuffSmoke initiated.");
	GameObject smokePuff = Instantiate(benParticles, transform.position, Quaternion.identity) as GameObject;
	Debug.Log("GameObject smokePuff instantiated.");
	ParticleSystem smokePuffParticles = smokePuff.GetComponent<ParticleSystem>();
	Debug.Log("ParticleSystem smokeParticles set to smokePuff's particlesystem.");
	// ^ that line doesn't get debug.logged, therefore the line above it isn't executing!

	smokePuffParticles.startColor = GetComponent<SpriteRenderer>().color;
	Debug.Log("smokePuffParticles startColor set to this brick's color.");
	Destroy(gameObject, myAudioSource.clip.length + 1f);
	Debug.Log("PuffSmoke completed.");
}

void LoadSprites ()
{
	int spriteToLoad = timesHit - 1;
	if (hitSprites [spriteToLoad] != null) 
	{ //this is backup code in case there's no sprite @ the SpritetoLoad array value
		GetComponent<SpriteRenderer>().sprite = hitSprites [spriteToLoad];
	}
	else
	{
		Debug.LogError("Brick sprite missing!");
	}
}

// TODO Remove this method once we can actually win!
void SimulateWin() 
{
	myGreatLevelManager.LoadNextLevel();
}

}

Privacy & Terms