Michael Wingfield

LD 42

Reality vs Feel

EventfulHorizon_realityVfeel.png

Something interesting happened in the middle of LudumDare42 this last weekend. I had just finished my work on a black hole shader (in the above image on the left) that was going to be used in our game. (pretty much copied and pasted from this helpful youtube video)

But although the effect was actually really cool, it just didn't fit the way I had hoped it would.

In our game, a black hole chases you around the level. If it gets too close to you, you get sucked in and die. I know that in real life, black holes warp the light around them so you end up seeing what is behind them on the edges and then absolute blackness in the center. The black hole shader that I had implemented did exactly that, Woo hoo! The problem was it lacked the sort of feeling I was going for. The "real" black hole sort of pushed and smooshed the world around it. I needed something that would actually give the player the feeling of being sucked up into it. So I had to make a choice, use what we had already implemented that was "working" and was actually more realistic OR go back to the drawing board to find something that matched the feeling I wanted.

In a game jam, that decision is a tough one to make. You only have so many hours to finish and submit your game, so any detour can really slow your progress and lead to cutting other features. On the flip side, though, you typically only get one chance for people to play your game. If it isn't right the first time, you just don't get a second chance.

I decided to attempt to redo the effect because it was just too important to the feeling of our game. With some pair programming help from Logan ( @bitdecay ), we were able to come up with a simpler, less realistic, but overall better feeling shader (in the above image on the right). As you can see in the picture, on one side, the world is sort of smooshed and warped around the black hole, and on the other you can see the world is sort of being pulled and stretched towards the blackness. In the end, that pulling effect created a much more visceral experience when you get caught by the black hole. You can actually feel the anxiety when you see the world at the edges of the screen behind you start to stretch because you know the black hole is now right on your heels.

Sometimes in games the importance of realism just doesn't trump the importance of the feel of the game. When someone plays my game, I don't want them to think "Hmm, that shader effect sure was accurate." I want them to say "Wow, I can't believe how close it was to getting me!". Experiencing something that makes you feel will almost always create a more lasting impression than something that makes you think.

Thanks for reading, and I hope you will check out our game: Eventful Horizon

Losing Progress Sucks

EventfulHorizon_checkpoints.png

One of the members of our team (@shadoninja) said of our level design,

"Make the level so we can beat it trivially, and that will be the right difficulty level for everyone else."

That is not to say that everyone else is not as good as we are at playing games, it is just to point out that after hours and hours play testing our game over and over, we will inevitablly be better at it then the average person who picks up our game for the first time. We know where the next platform will be, we know how long it will take for the black hole to reach us, and we have mastered the physics of the movement mechanic. Making a level for someone who doesn't have that experience is hard to do. And really, we did make an effort at every step of design to make our game as accessible as possible to everyone who played it. But to be honest, even with that in the front of our minds, I think we still made our game too hard.

It isn't so much that we wanted to make the game easy for everyone, just to make it accessible. When someone tries out our game for the first time, I'd like to see them complete it. We put a ton of effort into the beginning and end of our game, and I don't have full confidence that everyone will get to enjoy that last part.

I believe the main reason for this is that after someone dies for the first time and is brought back to the menu screen to start the game over from the very beginning, they become immediately deflated. Unfortunately, we weren't able to get a checkpoint system into the game before the deadline. Which means, every time someone died, they had to start from scratch.

Every. Single. Time.

I imagine that after starting from the beginning more than a time or two, the player will just give up and chalk it up to "That game was too hard" and then move on to the next game without ever having reached the final ending. :cry:

After the deadline, I decided to put some effort into creating a checkpoint system (pictured above). I made it so that if you reached a specific area (green circles), that on death, you would spawn back to that point and the black hole would spawn somewhere (pink line) along the path (teal line) behind you. Watching someone play this version of the game was much more satisfying. There was no longer the deflating sensation of losing ALL of your progress. It turned stress and frustration into fun.

All of this to say, taking away progression from a player should be a technique used extremely sparingly in a game. We missed the opportunity to make our game truly accessible this time around. But hopefully we will take what we've learned and apply it for the next jam.

Thank you for reading, and please play our game: Eventful Horizon

LD 44

Animation Exasperation

(TLDR: I created a sweet script that means I don't have to do 300+ steps for our future game jams, find the link to the script below)

Goal: Add 1 new character to our Isometric Game in Unity

four-characters.gif

Steps:

  1. Create sprite strip (make sure all cells are the same width and height)
  2. Import Texture2D into Unity
  3. Set Sprite Mode to Multiple
  4. Click Sprite Editor button (don't forget to save the changes to Sprite Mode)
  5. Click the Slice option in the top menu
  6. In the Type dropdown, select Grid by Cell Size
  7. Enter 16 for width (Pixel size X) and 32 for height (Pixel size Y)
  8. Click the Slice button
  9. Repeat steps 1-8 for each direction your character is facing for both Walk animations and Stand animations (total of 8 sprite strips)
  10. Take a deep breath, because you are not even half way done
  11. Right click your Animation folder in your explorer and create a new Animator Controller
  12. Click on your AnimatorController and open up the Animator tab in the Unity Editor
  13. Right click in your Animation folder again and create a new Animation
  14. Make sure to name your Animation object based on the sprite sheet it is going to be associated with (DownLeftWalk, DownLeftStand, UpRightWalk, UpRightStand, etc...)
  15. Click and drag the newly created Animation into the Animator tab window that you have open
  16. Repeat step 13-15 for each of your sprite sheets
  17. Now create an empty GameObject in your scene (or you can use a prefab)
  18. Add the SpriteRenderer and Animator components
  19. Drag the AnimatorController from step 11 into the Animator.Controller slot
  20. Open up the Animation tab (different from Animator tab) while you have the GameObject selected (that part is important)
  21. Now you should have a dropdown in the Animation tab that has your list of Animation's, if not, go back to step 20 and try again
  22. Select one of the Animations from the drop down
  23. Navigate to the folder you have your actual sprite sheet asset in
  24. Click the little arrow to open up your sprite sheet and show all of the individual sprite frames in the explorer
  25. Shift-Click to select all of the frames out of the sprite sheet
  26. Drag the frames from the explorer and drop them into the Animation tab
  27. You should see the frames listed one-by-one in the Animation tab
  28. Click the play button in the Animation tab to view the animation (don't forget to navigate back to the Scene view) and you can now adjust the speed of the animation by changing the Samples number in the Animation tab
  29. Repeat steps 22-28 for all of your Animations for this character
  30. (Optional) Our animations looped, so you need to go into each Animation object and select Loop Time and Loop Pose

No biggy. Now just do this entire process 13 times (1 for the player character, and 12 more times for each NPC).

sheet-example.png

In total, I spent just shy of 3 hours working on this task for our jam (not including the time to actually make the sprite sheet, that part was done by our artist, or the part where I had to actually LEARN how to make all this stuff work in the first place). This list, I feel, really highlights the downside to using Unity for our animation framework. There is just such an incredible amount of overhead to get just a single animation into the game. And honestly, since we only do this process once every few months, one of us has to relearn it all from scratch each time. We've probably all, during one jam or another, sat there reading through Unity docs and watching youtube tutorials trying to figure out how to configure everything just right so that Unity will allow us to play our 2D animations.

I'm sure there is a really great use-case for such a complex animation system somewhere in 3D land, but for all of us who are using Unity in just 2 dimensions, we could really use a better process for this. So, after this jam was over, I decided to investigate how it could be done.

AssetPostprocessor to the rescue!

In Unity, you can set up an Asset processing pipeline where scripts are run when specific types of Assets are imported into the project. After much fiddling, I've found a half-way-decent approach to automate MOST of the busy work.

Check out my gist to get the full file: https://gist.github.com/Kenoshen/494a83028e8c6509087172c21fefcef4 (put it in Assets/Editor)

Instead of doing that entire list manually, this script will run every time you import a new sprite sheet into the project. It slices the texture (given some texture naming conventions), creates the AnimatorController and each Animation, adds the frames of the sprite sheet into the Animation, and adds the Animation to the AnimatorController. All together reducing your work down to dragging the appropriate AnimatorController into the correct GameObject Animator component.

If you were like our team and were constantly battling with Unity's Animation system, I hope this script helps you in your future work.

Good luck and happy Jamming!

PS. Check out our game: 2nd Bank

hero.png