Roguelike2d example Walls fail to cast correctly in Player:OnCantMove

Hey guys,

got the tutorial working on my PC running windows 7 professional, unity 5.0.0.f4. everything works, food counts down, character and enemies animate correctly, enemies attack player and players animations and enemies also work. The problem is the internal walls: they are supposed to take damage, and in the OnCantMove of player, when its a wall thats passed in, when I try and cast it in Player:OnCantMove:


protected override void OnCantMove  (T component)   

		{  

			//Set hitWall to equal the component   
 
                        //passed in as a parameter.   

			if (component != null) {   

                                // test works and the gameObject exists, so its actually there  

				GameObject test = component.gameObject;  

  

  				if (test.name.StartsWith("Wall")) {  

					
		    		Wall hitWall = component as Wall;
                                // now hitWall on the other hand here
                                // is null in the debugger

===========
Its basically an exact copy of all scripts from the completed section, and everything else works. So why does hitWall return null when I attach to the process and check on it during runtime. I even tried converting Wall to a MovingObject, and after adding the appropriate code (so wall could move, but in this case doesn’t), I get the exact same error: than in Debug, when it gets to Player:OnCantMove, when the player is attempting to move into a wall, the casting to Wall fails and hitWall is null.

Also note in the OnCantMove of Enemy the Player is picked up and cast correctly:
Player hitPlayer = component as Player;

this line actually casts the Player correctly, and both animate, and the player takes damage.

Any suggestions? This code is driving me crazy!

So: some important facts about C# generic functions:

  1. when attached with the debugger and debugging through the script at runtime, you can tell whether you have a correct object passed of Type T if, for example the object is a Player, then it will looks like this:

So click the play button, then open up a script (so MonoDevelop opens), the click on the Menu Run->Attach, then click on attach to process.

In Enemy.cs, go to the OnCantMove function and add a breakpoint right after retrieval of the component line:

Player hitPlayer = component as Player;

now play through until Level 3 and wait for an enemy to swing at you. Note that when he does your screen should look like this in the watch value:

(note put two breakpoints is safer, then hit F10 to step over that assignment line. Then the value should be:

44010-validtemplatepass.png
In the OnCantMove of player I’ve changed the attemptmove line to:
AttemptMove(horizontal, vertical);

That way the player can now attack and kill enemies (I’ve had to add hit points to enemies too, but thats particularly easy adding a public int hp and adding a function to enemy to damage himself called DamageEnemy.

Now that works: however when I pass in a wall, because its the wrong time in AttemptMove in player (which I’ve now set to Enemy, it fails. And a failure looks like this:

Now you see how it says Wall6 Clone and then UnityEngine.transform? Thats the debugger’s subtle way of saying the object failed to pass correctly. So my question is this: should I pass some sort of list here? Or just make all objects enemies, so that I can destroy walls if they are of type enemy, etc etc. The only problem I have with that later is adding NPCs (non player characters), and then having some interaction with them doesn’t make sense to place them in the ‘Enemy’ category.

so would it be best to somehow have a list to interact with? Or can I do an AttemptMove from player and have it cast correctly when I attack a wall?

Let me know. I hope this question helps with clarity on debugging Template passing functions… and I hope someone out there has a solution for me :slight_smile:

OK, so far, I’ve got enemies working and dying. Now I’ve added a new prefab called house, and I instantiate them on the map, and they have their own animation controllers, and they don’t move as of yet, and I can destroy them. The only issue I have is on the AttemptMove in Player script I have to add another attemptmove line:

AttemptMove<Enemy>(horizontal, vertical);
AttemptMove<House>(horizontal,vertical);

and then do cases for them in the OnCantMove of Player based on the name of the object passed in. Which is silly for so many reasons. My question is this: do I have to have everything inherit from Enemy, and then do subset code of each enemy which could include things like moving walls, stationary walls, lava flows, etc? Or is there some way to call AttemptMove in Player with

AttemptMove<T>

such that it figures out the type (as you’d figure C# generics should) and then do the appropriate damage to said enemy, or talk to said NPC?

Let me know