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.
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.
<many><particles><in><my><system>
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();
}
}
Can you .zip the project up and upload here for me so I can take a look.
Also, is your “Smoke” a prefab?
If it helps, I further worked to isolate the problem by seeing if the script could access the Transform property of the smokePuff object that gets instantiated, instead of the ParticleSystem, to see if the problem lay with the particles. The below code threw the same error:
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.");
Transform smokePuffParticles = smokePuff.GetComponent<Transform>();
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.");
}
And to double-check, here’s my Smoke prefab (this is what’s dragged into the benParticles spot in the Brick’s inspector). Transform and ParticleSystem certainly seem to be there!
Just saw your comment - zipping in one sec.
ok… will take a look…
I think the public ParticleSystem bensParticles;
needs to be public GameObject bensParticles;
but will take a look and see…
Just PM’d it to you.
Grabbing…
Ok…
Resolved…
As mentioned above, change the following line in Brick.cs;
public ParticleSystem benParticles;
to;
public GameObject benParticles;
When you do this it is changing the type, as such, if you look in the Inspector for each of the three bricks in the Hierarchy you will see a “Type Mismatch” error for the Bens Particles variable. Fix this by dragging in the Smoke prefab again.
Run the scene.
Assuming all good, don’t forget to make the same changes to the Brick prefabs.
Yes, it works now!!! What I don’t understand, then - why do we need to cast the smokePuff GameObject “as GameObject”, when benParticles was declared as a GameObject, and we are declaring the smokePuff as a GameObject? I tried removing that part and Unity said it was just an Object, but we declared them as GameObjects?
Ok, so this is going to be all about types.
In this line;
GameObject smokePuff = Instantiate(benParticles, transform.position, Quaternion.identity) as GameObject;
You have declared a variable called smokePuff
of type GameObject.
The Instantiate()
method returns an object of type Object, so in order to use your variable you need to cast what is returned as a GameObject.
The issue with what you had was that you were declaring bensParticles
as a ParticleSystem, but actually it wasn’t a ParticleSystem object that was being passed in through the Inspector, it was an object of type GameObject which had a ParticleSystem component.
Hope this makes sense
See also;