Dev Diary 012: Can't Do It Alone

  • warning: Creating default object from empty value in /home/buckman/public_html/neo/modules/advanced_forum/advanced_forum.module on line 492.
  • warning: Creating default object from empty value in /home/buckman/public_html/neo/modules/advanced_forum/advanced_forum.module on line 492.
  • warning: Creating default object from empty value in /home/buckman/public_html/neo/modules/advanced_forum/advanced_forum.module on line 492.
  • warning: Creating default object from empty value in /home/buckman/public_html/neo/modules/advanced_forum/advanced_forum.module on line 492.
  • warning: Creating default object from empty value in /home/buckman/public_html/neo/modules/advanced_forum/advanced_forum.module on line 492.
  • warning: Creating default object from empty value in /home/buckman/public_html/neo/modules/advanced_forum/advanced_forum.module on line 492.
Matt Barton's picture

Well, I'm sad and sorry to report that my little Unity project has come to a grinding halt. It's agonizing, but even though I was making huge leaps towards realizing my game design, I've finally hit that wall that I just can't get over by myself. I've been working for two days trying to overcome it, but I sadly just simply lack the skill and the knowledge. I've ended up with a show-stopper glitch that I just don't understand, and the behavior just seems entirely random...It's either get help with this or give it up.

Here's the deal. Although the system works great at first...Occasionally a block will suddenly switch into "orphan" mode. I've stared at my code until I just can't stare at it anymore. I've combed through it, commenting out each component to try to find the culprit...Just can't do it. I've tried, and tried, and tried to no avail. I can't find a pattern in it; it just...does it sometimes. It just seems entirely random!

I can't find any logical reason why it doesn't work, so that leaves me to think it's either a glitch in Unity itself (unlikely) or just really bad optimization on my part. I suspect the issue is unnecessary collision checks and bad update routines--that is, out of ignorance, I'm asking the computer to run so many checks that it's overtaxing the system, resulting in missed collisions. To combat that, I've tried to reduce the updates, but nothing has worked.

It made sense to me, for instance, to only check for ophaned blocks after one has been destroyed. Seems logical, right? Yet, I'll be damned, no matter how I tried to position the code, it just wouldn't execute. Apparently the block destroys itself before running the orphan check code, and maybe I'm missing something obvious, but after trying hundreds of things, NONE of them worked.

I hope someone with more skill can help me out. I'm attaching my enemy script code here. It started off neat and well organized, but after hours and hours of exploratory surgery, it ain't very pretty. At any rate, I'd love to get some help and get this project back on track.

**Update** Maybe it's just me, but for some reason, I can't seem to replicate the error in this web browser version of the game...I can assure you, though, it most definitely occurs when I play it in the Unity editor. More mystery.

Unity Web Player | WebPlayer

AttachmentSize
Enemy_Script.zip2.73 KB

Comments

Chris Kennedy
Chris Kennedy's picture
Offline
Joined: 08/31/2008
Hey Matt

Hey Matt. I played the game a bit. It is my first experience with it.

I haven't looked at your code just yet, but could you describe your approach to "checking up on" your blocks? When you say that a block switches to orphan mode, does this just happen regardless of what the player is doing at the time? If player doesn't move at all, does it still happen? What is your criteria for determining if a block should be in orphan mode?

n/a
Eigen (not verified)
Hey, Matt. I'm not sure what

Hey, Matt.

I'm not sure what "oprhaned" means exactly, is it when the block(s) don't have enough neighbors? Nothing really jumps out in code, but I noticed one thing. You should ALWAYS explicitly initialize your variables to a value. Different languages and different compilers assign different default values, which might be something that was in memory at that spot or not, you may never know. It might not be "false" for booleans or 0 for integers. Where-ever you init your code, put orphaned = false there. Just to be safe. I know that's not the culprit, but just in case.

You could do the same thing without using physical raycast checks actually. Make an array of booleans somewhere in your program, something that all blocks can share, basically array[width * height] and when the block is there, it's true, when it's cleared or it falls down, it's set to false. Then have each block know it's index in the array and you can simply check if the neighbor is there or not.

Eg. is the left block there? ... if (blockArray[myIndex-1]) ... or is the top block there? ... if (blockArray[myIndex - width]) ...

Does this make sense? It'd cut down on the physics check which might easily fail under certain circumstances.

Good luck :)

Anonymous (not verified)
uninitialized variable
Eigen wrote:

Hey, Matt.
You should ALWAYS explicitly initialize your variables to a value.

That's probably the cause the problem.

The contents of orphaned are random. It may be initialized in MarkOrphans(), but not in every case. Unless that is fixed you will encounter random behavior in Update() and OnTriggerEnter() where orphaned is read.

Some notes on style. Totally ok. Just consider indenting the contents of methods and class names are always upper case and method names always lower case. These conventions make skimming through the code easier.

Emualynk (not verified)
Hey, I've started looking at

Hey, I've started looking at the code, I'm guessing you launch one thread of Enemy_Script by enemy block from the look of it, and the problem might have to do with synchronization of the threads.
Would it be possible for you to upload the whole project? (or well the part where you create the threads and launch them).

Eigen (not verified)
Yes, threading might be an

Yes, threading might be an issue. What would help in this case, is if there was a "manager" object, which owns, manages and checks all the blocks, so that each block would not have to do it individually. There you could have the array of blocks and it'd be easier to keep track.

Tom Hudson (not verified)
This is the sort of thing

This is the sort of thing where I'd take the opposite approach and not try to distribute the intelligence of "am I an orphan?" to every single block, let alone use a mass of threads. Lots of pain, lots of synchronization to worry about; I'd expect the code to be more comprehensible and far more efficient if it's in one place running once per frame-containing-a-relevant-event.

Then again, I don't grok Unity, and the one proof-of-concept I "shipped" with it made the client happy but was hackish, so this may be the best-afforded approach.

Your code is mis-indented, which makes it harder to read, un-commented, which is OK for a personal project but not when you're asking us to critique, and could use a naming convention - I disagree with the above poster on *what* the naming convention should be, but anything helps.

Matt Barton
Matt Barton's picture
Offline
Joined: 01/16/2006
Hi, guys, thanks for the

Hi, guys, thanks for the help.

I initialized the orphaned variable, but unfortunately that didn't seem to help.

I figure some type of array solution would help, but I'm just not competent enough to work out how that would work in code.

Orphans are what happens when there's a block that is no longer capable of making a match 3. It's not just a matter of looking around for neighbors, because it could still make a match if there's a neighbor of one of THOSE neighbors.

Imagine an L shape configuration of blocks, and you hit the lower right. The way I have it set up now, the code first checks to see if there are two neighbors. If so, it's not an orphan, move on. If there's only one, then it jumps to the closest block and checks for neighbors. If there's at least 2 (since it will include the original block), it's not an orphan, move on.

This code works brilliantly most of the time. It just seems like after while the computer just gets tired or something, and it starts making mistakes. I suspect that it could be some kind of "synchronization of threads" issue like Emualynk states, but I'm just a noob here. I have a parent object for the blocks with its own parent script, but I don't really understand the logic of their relationship. I tried moving the check orphans function to it, but couldn't get it to work, and I could never figure out how to get it to recognize or modify the child's orphaned bool.

n/a
gilgamesh (not verified)
Constructor
Matt Barton wrote:

I figure some type of array solution would help, but I'm just not competent enough to work out how that would work in code.

Obviously there is a bug. Design decisions like using arrays should not depend on a minor bug in your code.

Matt Barton wrote:

It just seems like after while the computer just gets tired or something, and it starts making mistakes. I suspect that it could be some kind of "synchronization of threads" issue like Emualynk states, but I'm just a noob here.

Could be both uninitialized variables and synchronization issues at once. Should for example collision detection happen in one thread and the rest in another, OnTriggerEnter() might sometimes be called before Start(). OnTriggerEnter() would see again a random value in orphaned. Always write initialization code in a constructor Enemy_Script(). This will be called first under all circumstances. Don't abuse Start() as a constructor.

TripHamer
TripHamer's picture
Offline
Joined: 07/31/2010
skimmed thru the code...

If there is not a neighbor to the left, right, up, or down, it becomes orphaned? And your checking for that every frame?

It probably would be simpler to just keep an array of bytes ( [3][6] ) and initialized them all to one at start and when one get destroyed, change it to zero and only when that happens, check the array for an orphan.

That's one idea perhaps.

n/a
Matt Barton
Matt Barton's picture
Offline
Joined: 01/16/2006
I think I have managed to

I think I have managed to solve it...!

I was thinking about what Triphamer wrote and went back in to try to find a way to only check for orphans when something has been destroyed. I already have a "destroymode" bool, so I just said to check only when that was active.

So far, so good. Haven't had any rogue orphans. I'll test it a bit more, but I think I'm set.

n/a

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.