transform.childCount not working as intended - unity3d

I am building my first game with unity, a simple break out game.i am intending that when the level has no children it moves to the next level.but it doesn't seem to work.in the code I put this in the update methode.
else if (_currentLevel != null && _currentLevel.transform.childCount == 0)
{
SwitchState(State.LEVELCOMPLETED);
}
break;
which call this code
case State.LEVELCOMPLETED:
Destroy(_currentBall);
Destroy(_currentLevel);
Level++;
PanelLevelCompleted.SetActive(true);
SwitchState(State.LOADLEVEL, 1.0f);
break;
but it doesn't even get into the first condition although in the editor i can see there's no Childrens.
PS:Sorry if it's not clear if any more details are needed I will add them.

I figure out what was wrong exactly, I failed to assigne the Instantiated level to the current level. I didn't add that part of code in the answer which made it very unclear.
In summary instead of
Instantiate(levels[Level]);
I added
_currentLevel = Instantiate(levels[Level]);
and it worked as intended.

Related

Very Basic Node Removal in Swift

I found some other questions about node removal in swift, but none of them seemed to be quite relevant to my issue.
I just want to do a basic node removal, for example:
override func touchesBegan(touches: NSSet, withEvent event: UIEvent){
let covernode1 = SKSpriteNode(imageNamed: "tester")
covernode1.position = CGPointMake(100.0, 600.0)
for touch: AnyObject in touches {
if self.nodeAtPoint(location) == self.fake {
button1++
button2++
}
if(button1 == 1 && button2 == 1){
addChild(covernode1)
}
if(button1 == 2 && button2 == 2){
//THIS IS WHERE I WANT TO REMOVE THE NODE
}
I have tried
covernode1.removeFromParent()
but to no avail.
The code runs the addChild part fine, but removal seems to be a problem. I even tried just changing the position of the node so it's off screen, with something like
covernode1.position = CGPointMake(-100.0, -600.0)
This did not work either.
Thank you.
Unfortunately I don't have enough reputation to comment on your original question, so this may not be an "answer" per se, but I'll try and diagnose what I think is going on, and hopefully you can clear up some points for me.
The covernode1 that you are trying to remove from the parent view in your if statement may be a different node than the one you added to the view when you called addChild(covernode1)
I think this is the case because when you say you are using covernode1.position = CGPointMake(-100.0, -600.0) and it still does not work, that makes me think that is a completely different SKNode object.
Instead, try declaring covernode1 outside of the function as a class variable. That way, when you actually instantiate it and refer to it in the function, it is grabbing the correct node you are looking for. Let me know if any of this helps. I'll edit the answer when I know a bit more from your response.
Also, are your button1 and button2 vars originally set to 1?
EDIT: Another question: Are you receiving any error when calling .removeFromParent() or is just "not doing anything"?
One simple thing you could do (kind of cheating but it will work) is to hide the node using
covernode1.hidden = true
Note
Also make sure the if statement actually runs because I don't know why the things you tried should not work. To test that, place a println("log") in the if block.
Hope that helps :)
From button1 and button2, I think you are trying to do this: On the first click, you add a SKNode. On the second click, you want to remove the SKNode.
Thus on the second click your let covernode1 = SKSpriteNode(imageNamed: "tester") is a different instance although it has the same variable name ! Thus the instance on the second click is not removable since it was not added to anything.
Try this,
if(button1 == 1 && button2 == 1){
addChild(covernode1)
self.tempChildCount = count(self.children) //tempChildCount is an integer
}
if(button1 == 2 && button2 == 2){
let childNode = self.children[self.tempChildCount - 1 ] as! SKNode
self.removeChildrenInArray([childNode])
}

Tansform.position assign attempt for 'Enemy(Clone)' is not valid. Input position is {NaN, NaN, NaN}

From my research I can see I am getting a vector issue (it looks like I divide by 0 but I don't do an divisions in my script).
I checked every script I have for positions and tried to catch it between trace statements. Couldnt do it. It looks like its in some update or fixed update but I have no clue where.
This error comes up SOMETIMES right as an enemy is killed.
I feel it has something to do with its position. Clicking on this error does nothing, but SOMETIMES it highlights the gameobject that got the bad transform passed to it.
Is there somewhere in your code I could get getting a NAN vector that I can look for?
Right as an enemy dies I will get a lot of these, and once its dead (destroyed) this problem goes away. It will play through a bit of animation, triggering the error each frame, and then when the enemy dies the error stops.
Clicking the error will only highlight the gameobject but will not open to a script where this occurs.
It comes up maybe 1 in 5 times whenever an enemy is killed...
Here is the enemy dying script (it doesn't set positions so the problem likely does not lie here)
public void killSelf()
{
_animator.SetBool("isAttacking",false);
_animator.SetBool("isDead",true);
StartCoroutine(processKillSelf());
}
IEnumerator processKillSelf()
{
yield return new WaitForSeconds(1f);//its a 30 frame animation
Destroy(gameObject);
}
Is there a way to FORCE unity3D to break on this error and let me look up the stack trace?
Not having the stack trace is the only reason I can't find where this is occurring.
I know this is late but I just had a similar problem and maybe it helps someone in the future.
As you already noticed this always happens if somwhere you try to devide a value by 0.
In my case I just couldn't find where I possibly divided by 0 that easy and unfortunately something like
try
{
transform.position = possiblyBrokenVector3;
}
catch
{
}
didn't catch it either so I couldn't set up proper brakepoints since it was called in Update.
What you always can do is actually checking the values for NaN. I directly made it an extension method for checking Vector3:
public static Vector3Extensions
{
public static bool ContainsNaN(this Vector3 vector)
{
return float.IsNaN(vector.x) || float.IsNaN(vector.y) || float.IsNaN(vector.z);
}
}
Now I can always check before I assign like
if(possiblyBrokenVector3.ContainsNaN)
{
Debug.LogWarning("Ignoring a NaN vector here!", this);
}
else
{
transform.position = possiblyBrokenVector3;
}
set a Brakepoint on the Debug line and finally step through the call history to see how the broken input value actually was produced.
Without seeing more of your code I can't say for sure but it sounds like reference is not being updated internally (ie. something is pointing to a vector that has already been destroyed.) I would poke around your animation code to see if that turns up anything.
For what its worth Object.Destroy has an optional second argument that is a delay timer. ( http://docs.unity3d.com/ScriptReference/Object.Destroy.html ) so you could re-write your code like this:
public void killSelf()
{
_animator.SetBool("isAttacking",false);
_animator.SetBool("isDead",true);
Destroy(gameObject, 1f);
}
and totally omit the processKillSelf() coroutine.
I found the problem:
It was not the character, but an HP bar on the character. The local scale of that HP bar was having one of the values set to 0 on death. Making sure the value is at least 0.1f fixed this problem:
float x = _hpBarMaxScale * health/healthmax>0?(_hpBarMaxScale * health/healthmax):0.1f;
hpBar.transform.localScale = new Vector3(x,hpBar.transform.localScale.y,hpBar.transform.localScale.z);

A way to check a BufferedImage repaint()?

I'm working in Eclipse and I want to know if I can make an if statement that checks to see if the BufferedImage has been painted/drawn onto the frame. For some reason, it's not painting the correct image because clickable regions are appearing on that picture when they are not supposed to.
For example, when I click the region to go from 4>5 everything is good. When I click from 5 to go to 4 I end up at 6 because the 'regions' from 4 are appearing in 5 (The image should always be painted before the clickable regions are shown) before it's even being painted. I want to restrict this to check if the image has been painted onto the frame first.
I really don't want to use anything else besides what I have right now (so no new classes being implemented to do this task), I really just want a simple yet effective way to resolve this. Here is what I'm talking about:
...
MouseAdapter mouseHandler = new MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
repaint();
if(n==0)
{
if(e.getX()>=459 && e.getX()<491 && e.getY()>=111 && e.getY()<133
{
n = 4;
}
return;
}
if(n==5)
{
if(...)
{
n = 4;
}
return();
}
if(n==6)
{
if(...)
{
n = 5;
}
if(...)
{
n = 0;
}
if(...)
{
n = 6;
}
return();
}
}
...
I think you might need to give a little more information. The problem might lie in how you repaint, not whether it was painted.
If you are running another thread as your main program, you might instead want to send the mouse events synchronously to that so that the main thread can process the mouse click and then repaint.
Another solution might be to override the repaint method and paint the buffered images there, but you may have done that.
Also, a little off topic, I noticed that you used for loops to determine if the mouse was clicked in a specific area.
You could shorten the code:
for(int i=459; i<491; i++){
if(e.getX()==i){
for(int j=111; j<133; j++){
if(e.getY()==j){
//action taken
}
}
}
}
To:
if(e.getX()>=459 && e.getX()<491 && e.getY()>=111 && e.getY()<133{
//action taken
}
This would take up less space in your code and less time checking every pixel.
Back to your question.
I dont know of a function to tell if a buffered image has been painted. The ploblem that you are having though might of might not be in the code provided. Posting the rest of your code would be beneficial.
Okay I found the solution, I forgot to come back to this question and let you know. The problem was that the mouse was double clicking for some reason. You could almost say it was 'recursive'. I decided to move the mouseListener from inside the paintComponent to outside of it, and surely enough that fixed it.

Code will not work without CCLOG in Cocos2D

I'm currently working on a game that will randomly generate a dungeon for the player. This is made up of a whole heap of different methods being called from different files. I seem to have the code working to be able to calculate how much space is available on the other side of the door.
There is a catch however; the code only seems to work when I am outputting to the console using CCLOG. I wrote a good chunk of the code without testing and decided to then work through it in steps to see how the code worked (I figured I would just get it to run without bugs and next I will check my values).
After I had established that the code was successfully checking available space in each direction, while listing the locations it had checked, I decided that I would like to remove the CCLOG output. Unfortunately though, doing this caused the code to stop working.
//First check "forward"
bottom = CGPointMake(startLocation.x + forwardDirectionModifier.x, startLocation.y + forwardDirectionModifier.y);
top = bottom;
do
{
currentLocation = CGPointMake(top.x + forwardDirectionModifier.x, top.y + forwardDirectionModifier.y);
tileType = [tileCache getTileType:currentLocation];
if (tileType == TileTypeFiller)
{
top = currentLocation;
CCLOG(#"Top location is %#", NSStringFromCGPoint(top));
}
} while (tileType == TileTypeFiller || top.y != 63);
This is a small snippet from the code; It is the section of code I think is most likely the issue. Essentially the problem is that if I comment out or delete the line CCLOG(#"Top location is %#", NSStringFromCGPoint(top)); it will stop working.
Here are some more details:
I have several little chunks of code like this, as long as I CCLOG in each one, it will be able to move to the next. If i were to comment out any of them, it would stop progress to the next chunk.
I can change the CCLOG to output anything and it will still work, it just has to be there.
I have tried cleaning the project.
There are more CCLOG's that aren't used inside any loops and they can be removed without consequence.
Does anyone have a solution to this? As far as I can tell, whether I do or do not output something to the console,it shouldn't have an effect on whether or not the code will execute.
Thanks in advance.
EDIT: At Ben Trengrove's suggestion, I am adding in further examples of where the CCLOG is being used.
This code immediately follows the previously listed code.
//Check left relative to door
farLeft = CGPointMake(startLocation.x + leftDirectionModifier.x, startLocation.y + leftDirectionModifier.y);
do
{
currentLocation = CGPointMake(farLeft.x + leftDirectionModifier.x, farLeft.y + leftDirectionModifier.y);
tileType = [tileCache getTileType:currentLocation];
if (tileType == TileTypeFiller)
{
farLeft = currentLocation;
CCLOG(#"Far Left location is %#", NSStringFromCGPoint(farLeft));
}
} while (tileType == TileTypeFiller || farLeft.x !=0);
//Check forwards from far left
top2 = farLeft;
do
{
currentLocation = CGPointMake(top2.x + forwardDirectionModifier.x, top2.y + forwardDirectionModifier.y);
tileType = [tileCache getTileType:currentLocation];
if (tileType == TileTypeFiller)
{
top2 = currentLocation;
CCLOG(#"Top2 location is %#", NSStringFromCGPoint(top2));
}
} while ((tileType == TileTypeFiller)|| (top2.y != 63));
What does your tile cache return as a tileType when there is no tile at currentLocation ? TileTypeFiller by any chance ? if yes, you have an almost certain never ending loop there, under the right circumstances..
EDIT :
please add a line after the loop
CCLOG(#"");
and place a breakpoint on that line. See if the program stops there.
So the problem has now been solved, it seems that in part there was a fault in my logic.
Here is what I've done that now works:
do
{
currentLocation = CGPointMake(top.x + forwardDirectionModifier.x, top.y + forwardDirectionModifier.y);
tileType = [tileCache getTileType:currentLocation];
if (tileType == TileTypeFiller)
{
top = currentLocation;
}
locationCount++;
} while ((tileType == TileTypeFiller) && (locationCount != 15));
CCLOG(#"Top location is %#", NSStringFromCGPoint(top));
The change is that I've switched to AND as opposed to OR. I also changed the second part of the while as I realised that due to my max room size, I never needed to check more than 15 locations in any given direction.
Thanks a lot to everyone that has helped. I'm still not entirely sure though how the use of CCLOG was somehow able to help get past a fault in logic but at least it is working now.

enum in Singleton cocos2d

What do you recommend me if I have two layers (which are added to a parallaxNode) and on each layers I've added sprites which I want to restrict the order that the player won't be able to remove sprite5 until it removes first the previous ones: sprite1, sprite2, sprite3 and sprite4 and so one.
I'm using Juan's example for dynamically touch detection
What will be the dynamical option for this?
UPDATE:
if([sprite tag] == tag_collection_1 && [sprite GetCanTrack]) {
//Set others to NO & call remove sprite method
[[TSprite FindByTag:tag_collection_number] SetCanTrack:NO];
[self removeSpriteMethod:touchLocation];
} else if ([sprite tag] == tag_collection_number && [sprite GetCanTrack]) {
// and so on
}
Use a fifo stack implementation. If you want to remove the sprite, you first check if it's at the bottom of the stack and when you do remove it, you pop it from the stack as well. Practically you will have an NSMutableArray and look at the first item if the object is in that position before you remove it. If you have added 1,2,3,4,5 in that order and want only to be able to remove them in the same order you check if the object you are trying to remove is at index 0 in the array first.