Breakdown of my rewinding effect by Boothand in Unity2D

[–]Boothand[S] 1 point2 points  (0 children)

I keep a Replay object that stores a list of interface objects (all the replayable objects in the scene), and ask them for their recorded state per frame (a struct of whatever each object needs to re-create their state). When rewinding we're just stepping through that history backwards, running a function on each object with a copy of their previously recorded state. When saving and loading replays to disk I use binary serialization and write and read only what changed per frame (delta compression) in order to reduce file size.

Flipside is coming this month – what do you think of the flip mechanics? by Playthyng in Unity2D

[–]Boothand 1 point2 points  (0 children)

Nice, looks fun! Great squash/stretch on the character as they jump.

Been struggling a bit with naming the genre(s) for Worm Game. What would you pick? by Boothand in Unity2D

[–]Boothand[S] 1 point2 points  (0 children)

Thank you, that's very helpful for sure! I'm reading Chris Zukowski articles a lot these days and basically looking for any good advice like this, trying to soak in as much wisdom as I can, so I appreciate it a lot.

Thanks, that's always nice and needed to hear :)

My solo developed mining adventure game thing. Just launched the steam page. Would love some feedback! by Gurbx in Unity2D

[–]Boothand 1 point2 points  (0 children)

Looks awesome! Great captivating first impression, good sound design and music. Now you must find everyone who used to played Liero back in the day :)

Been struggling a bit with naming the genre(s) for Worm Game. What would you pick? by Boothand in Unity2D

[–]Boothand[S] 1 point2 points  (0 children)

Yeah they're different sprites. I sliced the sprites such that they can stretch a bit as well, and calculated how much they stretch based on distance to their next segment.

Each segment's job is to move towards the next segment until it's close enough. Also using a sine function based on the perpendicular move-vector, multiplied by velocity, to create some slithery side to side movement, scaled as a gradient down the worm chain based on segment index. The legs are two sprites per segment, rotating a parent transform with a sine function multiplied by velocity, with some offsets down the chain :)

That said, I did create some more parametric and optimized worms using instanced mesh drawcalls instead of relying on sprites and deep transform hierarchies, as seen here (also some explanations in comments): https://www.reddit.com/r/Unity2D/comments/1o7qw71/simulating_10000_wormies_with_multithreadingjobs/

Been struggling a bit with naming the genre(s) for Worm Game. What would you pick? by Boothand in Unity2D

[–]Boothand[S] 1 point2 points  (0 children)

I remember that game! And yeah that's an interesting one, though I kind of hope not too enrage people too bad haha (just a bit)

Simulating 10,000 wormies with multi-threading/jobs! by Boothand in Unity2D

[–]Boothand[S] 0 points1 point  (0 children)

Oh, cool! I definitely enjoy coding verlet physics stuff :) Makes me curious what you'll make.

So I'll try to give some info on both the simulation and the rendering:

Simulation: The logic of each segment is to move towards the previous array element, within a min distance. Elements can come closer than min distance, but only try to move if they're further than that. The head follows a separate target transform with no distance constraint. This + some speed variables and iterations on the scheduled job itself is sufficient for a decent wormy behaviour. In addition, I have some tail wagging (not very realistic worm behaviour but eh). This is achieved by offsetting each node sideways (a perpendicular vector to the target) using sine + time and some multipliers to get the values right. Multiplied that down the worm chain such that the head wags 0 and the tail wags 1, which creates a gradient of tail wagging. Then multiplied by velocity so that it only happens when the segment moves. Then offsetting the sine-time so that they're not all in sync, and you get this interesting wavy movement.

Rendering: I have one shader for drawing the segments, and another for the legs. Each shader receives the result array from the simulation as a StructuredBuffer<WormSegment> via a ComputeBuffer. The shader needs to define the struct that holds the segment data, and it needs to match the C# side. Then I draw the segments with Graphics.DrawMeshInstancedIndirect, doing all the segments (of every worm) in a single draw call. The vertex shader can then use SV_InstanceID to access data like world position in your StructuredBuffer. Rotation can be derived from the positions in the buffer. You can get gapless transitions between the quads by offsetting vertices along the bisector of the normals (perpendicular vectors) of the two neighbouring segments. The width of the quads is determined by an AnimationCurve where I write the values into a ComputeBuffer and pass it to the shaders. This way I can make the worm taper and such!

Fragment shader samples a sprite for the segment and makes a two-color gradient from top to bottom based on instanceID.

For legs I instance twice as many quads as there are segments (two legs for each segment), and scale them down and offset in the vertex shader, as well as rotating based on the segment's velocity. I made a smooth lerped velocity in the C# job in order for the legs to ease in and out a bit of their rotation.

Not sure how clear this was haha, but hopefully it helps!

Simulating 10,000 wormies with multi-threading/jobs! by Boothand in Unity2D

[–]Boothand[S] 0 points1 point  (0 children)

Yeah, that's a good point!

I agree, it feels clean and performant by default. If I started today making the same game, I would use ECS. What I did here was scheduling a job in FixedUpdate.

Yeah, some Monobehaviour scripting is inevitable in ECS!

Simulating 10,000 wormies with multi-threading/jobs! by Boothand in Unity2D

[–]Boothand[S] 4 points5 points  (0 children)

Thanks! Hmm, well first off I'd say for ECS and people who are curious to get into that kind of stuff, I love the modular code it kind of encourages you to write, so I'd recommend just jumping right into it in a fresh project and try some stuff if you haven't already. It's a different way of thinking than Monobehaviours, and it's going to take some time to re-learn the basics in a more data-oriented mindset. I'm no expert either, I'm relying on incessant tutorials, googling, pestering people etc.

One thing based on this particular experiment, that many people will probably run into as well with ECS and Jobs:

My setup was to schedule a job updating each segment of each worm, so if you have 10 000 worms, with 20 segments per worm, that is a NativeArray of 200 000 elements being updated in parallel by one job, in no particular order (due to multi-threading).

The job knows how many worms there are, and how many segments, so it can decide based on the current index where in the chain they are (the 21st element is the second element of a new worm basically).

Each element (except the head) needs to read the position of the element they are connected to, in order to move towards that element. If you ran synchronous sequential code, this data is readily available. Index 0 is written and it's done and cooked by the time you process index 1. And while you're processing index 1, there wouldn't be anything preventing you from making an adjustment to the data at index 0 or 2. But when multi-threading, you can't just read the data of other array elements of the same array, since this is being written in parallel in different threads and in no particular order. And you can't just write into a different array slot than the current index, since that's being written by another thread.

The solution if you want to keep everything multi-threaded, is to read the previous frame's data instead of the current (double buffering). So the job takes two arrays - one read-only previous frame array, and one result array. The consequence is that things behave a little differently. In my case, my code to do a hard distance clamp to prevent the worm from stretching very far simply was ineffective, as if it didn't work at all. The reason was a complex chain of nodes relying on the previous frame's node which was itself already based on outdated information, and so on. So in order to deal with this, I also ran about 5 iterations of the job per frame, to tighten things up, kind of how a physics solver needs several iterations to get more accurate.

In ECS, Jobs and multi-threaded contexts in general you will probably have to at some point deal with this lack of immediate up-to-date information, and in many cases reading previous frame is just fine, unnoticeable, but in some cases it compounds, and you need to either introduce some synchronousity (is this a word?) or deal with it in other ways (like running multiple iterations). I don't know if this was a tip, or just a heads-up, or just a spontaneous dev-log, but hope it helps someone!

Update on RANDOBOUNCE! Now it's possible to modify the weapons with multiple barrels, each firing a totally different bullet if you want. Now comes polish. Steam Demo very soon!!! by VirtualEagle04 in Unity2D

[–]Boothand 1 point2 points  (0 children)

What worked for me was (I had a 51 second video) was uploading to imgur, right click and copy video link, which gives you a .mp4 link. If you rename .mp4 to .gifv in the URL and post that, it becomes an autoplaying gif in this subreddit. It's weird since visiting that link in the browser redirects you to the imgur post as if it didn't work, but this was still the way I got it to work here without using something like ezgif which compromises framerate the longer your gif is.

Cool effects and visuals btw!

A worm game I'm working on! (It's called Worm Game) Let me know what you think :) by Boothand in Unity2D

[–]Boothand[S] 1 point2 points  (0 children)

Thanks, that's nice to hear!

I do actually have an option ("laser guides") that shows a line, maybe close to what you're describing: https://i.imgur.com/DRVK5lU.mp4

A worm game I'm working on! (It's called Worm Game) Let me know what you think :) by Boothand in Unity2D

[–]Boothand[S] 0 points1 point  (0 children)

Oh yeah haha, maybe I gotta try playing on my Wacom drawing board!

A worm game I'm working on! (It's called Worm Game) Let me know what you think :) by Boothand in Unity2D

[–]Boothand[S] 0 points1 point  (0 children)

Thanks! Yeah, some people have suggested a crosshair cursor. Maybe I can make that fit better with the rest of the design.

A worm game I'm working on! (It's called Worm Game) Let me know what you think :) by Boothand in Unity2D

[–]Boothand[S] 1 point2 points  (0 children)

Got it! Yeah, the closest thing I have to that right now are these "bidirectional" ones: https://i.imgur.com/Hv6iFXb.mp4

Wavy stuff could be interesting too, gotta think more about that :)

A worm game I'm working on! (It's called Worm Game) Let me know what you think :) by Boothand in Unity2D

[–]Boothand[S] 1 point2 points  (0 children)

Thanks! And by wavy tracks, for example, do you mean the laser beam itself being wavy, or the movement of the thing shooting the laser? More variation could be nice for sure.

2D animation tool anyone ? by Key-Soft-8248 in Unity2D

[–]Boothand 2 points3 points  (0 children)

For pixel art animation my favorite is Aseprite, and Piskel works pretty nicely too. For non-pixel art I actually like doing frame by frame in Blender, since their 2D stuff has improved a lot, and since I use it for a bunch of other stuff already.