itch.io Spring Selects Series A
On Sale: GamesAssetsToolsTabletopComics
Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
Tags

[Devlog] Shodo (Unity)

A topic by SuperSpasm created Jan 08, 2017 Views: 897 Replies: 10
Viewing posts 1 to 6
Submitted (1 edit)

Hey, I'm Jonathan.
I started working on an android project a a few weeks back (really rough prototyping, code was completely unmaintainable)
but I wanted to join the jam, so someone on discord gave me the idea to build it again from scratch for this jam.
So I am! never made a Devlog before but I figure this could be a good outlet for successes and failures.
I'm making it with an artist (Lena) that I met irl, it's her first game ever. I'm also fairly new to dev and this is my first time tackling mechanics as complex as this.


some quick info about the game:

-Platform: android
- Engine: Unity
- Genre: 2D platformer (?)
- Theme: Japanese/Chineese caligraphy and art
- Core mechanic: drawing caligraphic brush strokes on screen that act as platforms.
- Basic story: a Monk finds a dying wolf (or some sort of cainine), helps his soul ascend to heaven (?)
and is followed by the ghost/spirit of the wolf. it's your job to keep the monk from falling to his death(lemmings style)


My goal in this jam is to be motivated by the deadline to finish a bare-bones version of the game with a few levels finished!


Edit: added the fact that I'm doing this in Unity. seemed relevant

Submitted

WARNING: technical rant incoming!

So my basic implementation for the Shodos (brush strokes on screen) is to use a LineRenderer and a PolygonCollider2D that are continuously updated by pointer position (either mouse or touch).

I'm basically mimicking a TrailRenderer (+Collisions) with my LineRenderer. I don't use a TrailRenderer though because then I would have less control over the vertices of the trail (which I have to keep in sync with the collider), and also because TrailRenderer "remembers" the time it took you to draw each segment, and I want it to "erase" and resize at a steady pace, regaurdless of how long it took to draw the line.

Before this jam I tried to make my own LineRenderer from scratch for this purpose (using a Mesh and setting my own vertices, uvs and triangles). but that lead me down a rabbit-hole of Vector math and unforseen situations. I ended up with something that mostly works (minus texture mapping, didn't want to waste more time fixing uvs), and I abandoned it because it was getting way out of scope.

anyway how I'm doing it now looks like this- I break down each bush stroke to "Slices":



with each slice having a Vector3 Center (that goes to the LineRenderer), two edges in a Vector2[] Array (For the PolygonCollider), and a width (that defines the edges).

(Slices are perpendicular to the direction that the line is going at the particular moment they're calculated)

I also made a Slicelist class that holds a list of slices as well as lists for line vertices, polygon vertices, and widths, and it synchronises between them (the idea is that besides the creation of Slices, all vertex-level stuff (adding slices, resizing, deleting) is done using SliceList methods, so that the Shodo class can be much more readable and editable)

Anyway, I'ts not really functional yet, but it's getting there. I just hope it's not going to be too unoptimised since I have to use List.ToArray() 3 times per frame for each of the Shodos I have on screen (to set them in the actual LineRenderer/PolygonCollider2D)


So yeah, sorry for the technical rant, but this feels like a good outlet to not let this stuff just sit in my head, so it's probably not gonna be the last haha

Also if anyone has any comments or suggestions I would love to hear them

(+1)

Doing List.ToArray three times a frame should be alright, assuming they're not nested calls or something crazy. I like the implementation you've done with the slices, looking forward to seeing how it works out.

Host

:Oc ohhh dang i'm not too familiar with line + trailrenderers to give any advice but this looks like an interesting solution so far! i'm curious to see it implemented!

Submitted(+2)

So I've gotten a bunch done since I last posted here, so far the systems are working surprisingly good, though the Shodos still look a little off and the monk can get stuck in them.
I figure I'll chronicle some of the technical stuff I did and put with progress gifs at the bottom for a TL;DR version.

#region Technical Rant

So since my original implementation idea I came across a bunch of problems. most of them were small bugs in my code, but the biggest issue I had was the PolygonCollider2D.
at first I just set a bunch of points into it (my Slice.edges) as vertices (that were supposed to match the bounds of the LineRenderer that you see, so what you see is what you collide with.
However, since I'm an idiot and can't read documentation properly, I assumed the order of points passed to collider didnt matter, and it just created a convex shape from whatever you plug in.
Not so. each path is cyclic, so you should end up where you started. this created intresting collisions, as seen in (A).

So I figured I'd try making lots of paths, each one a little BoxCollider2D-like rectange that was self contained. what could go wrong, right?
wrong. apparently having hundreds of paths being set every Update() is not the best thing for your game. I was getting crashes and hangs like crazy.
it took me the better part of a day to figure out it wasn't a bug in my code,but rather a constraint of the engine that was causing the hangs.

After that I had to refactor, which ended up being a good thing because I cleaned up the hell out of my code.
after going back to using a single Path for the polygon, and setting the logic up so it goes around the line (and not just iterating over Slices), it just worked. (B)

So now that the actual Shodo object was working, I started working on implementing multiple Shodos at once.
I wanted to pool my shodos to avoid memory issues from instantiating new Shodos constantly.
my implementation for that was a class that is structured as so:

 public class ShodoPool{
  private Queue<Shodo> availableShodos;
  private Queue<Shodo> detachedShodos;
  private GameObject shodoPrefab;
  private Camera mainCam;
  
  public ShodoPool(GameObject shodoPrefab, Camera mainCam, Transform shodoParent)
  
  public void StartDrawing(ref Shodo currShodo)  
  public void StopDrawing(ref Shodo currShodo)

  private GameObject CreatenewShodoObject()
  public void UpdateShodoQueues()
  public void AddToPool(int amount)
  private bool NotOnScreen(Shodo shod)
}

So this is my first time making an object pool. I have no idea how they aare usually made, but I'm happy with how this turned out.
it basically recycles Shodos into the detached/availableShodos Queue.
The detachedShodos Queue for shodos that are not currently in use by the player, but may still be rendered.
when a Shodo has either erased itself completely, or is off camera, it will move that shodo from the detached queue to the available queue.
I start off filling the pool with 3 Shodos, and more are created if they run out when

The pool is used by ShodoManager to abstract the recycling of Shodos,
and ShodoManager handles adding points to the currently used Shodo by grabbing mouse position.
This is done either every set time, or in Update as soon as the mouse has traveled a minimum distance. (to avoid stacking points close together at odd angles, which looks and acts terrible)

Today I worked a bit on the monk's AI (very simple, I want him to stop when close to an obstacle, and to jump when theres a gap with no platform underneath.
I thought of doing an arc-raycast type thing for him to check if he can jump before he tries, but after some consulting on Discord, decided it's simpler to just jump whenever theres a gap. The monk is basically a Lemming anyway, he's not supposed to have particularly intelligent AI.

#endregion

TL;DR- some progress gifs!

(A) first attempt at collisions, didn't go to well

(B) refactored collisions, Much better!


(C), (D) Multiple Shodos Recycled via Shodo Pool


(E) Monk jumping when reach gap

(F) Stopping when path blocked

(G) Using Shodo to block falling objects


Onwards-

The biggest thing that bothers me with the system right now is that sometimes a Shodo is drawn that is lumpy or has some edges, and the monk will get stuck on it. I'm thinking of doing a pass on the polygons vertices once per frame to smooth them out. we'll see how it ends up.

Also- we need to start thinking level designs and systems to support them! maybe an "ink level" to limit how much you can draw

I know this was a while ago, but for quite some time I've been looking for a solid solution like this to be used as a trail for melee weapon attacks. Is there anyway this can be made available for the programming-deprived? Honestly, I'd be willing to purchase. Please let me know.

Submitted(+1)

By a trail for melee weapon, you mean a trail a melee weapon leaves behind that blocks/ harms enemies?
The shodos can get messed up when they're too small, so this might not work.
I might be able to modify the script for it to work but not in the near future.


You should try the asset store, I remember seeing a solution for line collisions there.
If that doesn't work remind me in a few weeks, I might be able to help out :)

(2 edits)


Wow! I'm very surprised you messaged back so fast after such a long while! I am very grateful.

Basically, I'd like to use it as a trail renderer. A character attacks with a sword, and a shodo is drawn from the tip of the sword. It would just be a visual effect and wouldn't need collision. How long should the shodos be to avoid getting messed up? I only plan to ever use it for long lengths since the sword animations would be long.

I check the Unity asset store frequently and I can't find a weapon trail system that can deliver the fluid quality that you have displayed here.

Anyway, I'll be sure to remind you in a few weeks. I'm really happy that you replied back.

Hey, SuperSpasm! You told me to remind you in a few weeks. Do you think you'll still be able to help me out?

Submitted

Hey! I'm kinda swamped atm but might be able to help out a little bit.

my discord is @SuperSpasm#8098 (I'd pm you my email but apparently itch has no messaging system)

hit me up, maybe we can work something out

Alright, I sent a friend request as "Graff/Mo"!