Thursday, January 24, 2013

I Feel So Dirty


I wanted to make note here of a new milestone in cheap hacks, which coming from me is saying a lot. So, apparently, you can't destroy an instantiated prefab from within a coroutine. This poor S.O.B. had the same problem I was facing, and nobody had a good answer for him. I fully grant that this could be just a knowledge failure on my part, but I have not been able to determine why Destroy(thisThing) works perfectly well from inside a standard function, but fails silently from inside a coroutine, even though the code after it executes perfectly well. I'm sure one could track this down to some intersection of Unity's particular object system, the way its prefabs work, and its use of C#'s IEnumerator returning functions as the basis for coroutines (for instance, I suspect it might work fine in Javascript), but I don't think I'm that someone, at least not this evening. When I find someone else has encountered the issue that's blocking me, and has appealed to the Greater Internet about it, and has received no succor, I tip my hat to that brave pioneer and then I reach for my hacking axe.

So, when you need an object destroyed at an exact point in a coroutine, but you can't do it from within that coroutine, what do you do? If you're me, you make a new C# script called cloneKiller, and when you instantiate the prefab you also add the script to the clone with

ck = clone.AddComponent<cloneKiller>();

cloneKiller contains a single function, called KillMe:

public void KillMe()
{
if (gameObject!=null)
{
Destroy(gameObject);
}
}

and in the middle of the coroutine, I simply call

ck.KillMe();

 I know, that's absolutely ridiculous, and I should be ashamed of myself, but it works. . . actually I'm going to go ahead and make that statement the official motto of this blog.

Monday, January 21, 2013

Down With OOP

While my job slowed this project way down, I do manage to fire up Unity at least every few days and I'm still making progress on this game, although at this point it would be hard to tell from looking at subsequent builds, because I've finally decided to refactor some code.

I feel like I've been through a small level-up experience. It started about two weeks ago, trying to finish the interaction between the player and the first enemy. I had a small "Kick" function in both playerControls.cs and enemyControls.cs that would apply an impulse to either character when they came in contact with a "bad" object. The function was slightly different for each, but contained some repeated code. I then got into making a "Flash" function to flip a character's sprite renderer off and back on, separated by a tenth of a second coroutine yield, to give that classic effect of a character strobing to indicate they've been injured. I realized that this function would be identical between the characters, which made me look closer at the animation functions for each and realize I was basically writing a really long, complex script twice, simultaneously, changing a few variables and conditionals each time. It had to stop.

Thankfully, Lynda.com's Prof. Allerdice had provided me with the answer: Inheritance. I made an abstract  "Character" class that implemented all the major functions for all characters, then subclasses "Enemy" and "Player" to break out specific behaviors like patrolling, etc. by overriding virtual functions. The result is a much cleaner working environment, where the Player and Enemy scripts are both clear and compact, and I never really have to touch the Character script. Also much lower bug rate and general stress rate from trying to implement the same thing twice each time.

I have all the bits and pieces of Death together, save for the enemy's "crumbling into bones" animation, so next it's time to tie all that together, then move on to loot and pickups. I can't see the end yet but I think maybe I see the middle out there somewhere.