As mentioned in our previous post, we are officially shuttering Tuttle Games and turning a new leaf (heh) with Late Leaf Games. You can check out the new website (still under construction) here. See you around!
Back in March, I briefly wrote about a possible rebranding. Now, we’re finally doing it! Terry and I have formed Late Leaf LLC. While that’s the legal name on paper, our Late Leaf Games brand will be our vehicle for developing all sorts of games going forward. This includes:
- Video/computer games
- Board/card games
- Live-action adventure games (sometimes known as “escape rooms”)
- … And anything else we can think of
This means that we’ll be moving to a brand new website, and activity will pick up on our Twitter account. I’m excited to become a bit more involved in the community and begin releasing more than just prototypes and small concepts. Terry has been tinkering in MagicaVoxel for our first project, which is (appropriately) a blocky voxel version of Water Balloon Drop 2D, which itself was based on an older browser game called Water Balloon Drop 3D. We don’t have a title yet, but it will be a free iOS game.
I’m not sure if we will be keeping this website up (in its current form, at least) as an archive, but look out for one last update in the coming days confirming the new website so you can follow our progress!
Okay, it’s more like taking a step back from it for a while, although the few things I learned in the past several weeks have been interesting.
It turns out that Sync Transform (as opposed to Sync Rigidbody) is way more up-to-date, but the trade-off is in the choppiness. I’ve read that a reasonable send rate of 10-15 per second is standard, and other players’ paddle movement simply looks like a slideshow. Check out the footage below:
I’m aware that there are some other approaches to networking, like ditching Network Transform (or Network Rigidbody), instead issuing all client movement as commands to the server. The server would then RPC all four paddle positions to all clients at all times. Of course, the client’s paddle would have to appear to move in real time while it waits for the RPC information.
With the choppy-but-accurate method you see above, I actually was initially happy to see that I could indeed move around paddles with code (client-side) in case I wanted to smooth other players’ paddles out. For example, suppose I see your paddle moving to the right during frames 1-12. On frame 13, you start holding Left, but I only get that information on frame 18. As far as I’m concerned, from frames 13-17, I have to just guess that you’re still moving right, because historically you were moving right. Even if we Lerp moderately, your position on frame 18 is probably very different than that far-right position that I figured you’d be in, and it’ll look goofy. And that’s not even the worst part: the way I had it in my experiments, the (authoritative) server would actually declare ball collisions based on the predicted/estimated positions of other players’ paddles.
Maybe it’s a cop-out, but I really do think that if I’m using Unity, I should be able to use UNet as intended, and I see no reason why I shouldn’t be able to use Transform Rigidbody on paddles with a high send rate. I’m not scared of rolling my own, but is that the best use of my time? In the end product, I would simply ignore complaints from people with ~60 ping or more, because the game is designed to be played locally anyway, and the action is super time-sensitive.
Throw in the random Unity Services bugs I’ve been running into (it suddenly doesn’t recognize my game or company name, so I have to re-register the service, etc.) and ultimately, I don’t think I can use UNet for this. That means Pong 4 Pals will never see online multiplayer, unless I switch to another engine that has a viable plug-and-play networking solution.
Anyway, back to this Udemy course on Blender I’ve been taking in the mornings. I want to start cranking out some decent-looking low poly assets for my projects so I can stop using the “need an artist” crutch!
This week I’ve been diving head-first into Unity’s networking system. I’ll admit it’s a bit daunting to try to develop a good netcode solution for something like Pong 4 Pals (or whatever I’ll end up calling that game), but I’m going to give myself a few days of tinkering to see if I can whip up something decent.
Here’s what I have so far, which is no good. Movement is client-side, so it feels very smooth when you’re moving your paddle back and forth. In contrast, colliding with balls is authoritatively server-side, meaning that you may have moved a few inches to the right, and think you hit a ball coming your way. But the server doesn’t know that you moved those few inches, and so it thinks you missed the ball completely. Thus, initially, on your screen, the ball banks off your paddle safely, but only for a fraction of a second. Immediately afterward, it corrects its position/velocity by curving around and circling back into your goal, once the server updates it and says “nope, this ball went straight in.”
In the following footage, the bottom paddle is controlled by the client:
I’m still pondering what kind of model works best, without any complicated buffers of multiple input frames or fancy interpolation. I’m tempted to increase the network update rate a bit, and then experiment with syncing each transform (instead of each Rigidbody), either through something like a SyncVar, or what I’m doing now (the “Network Transform” component).
I’ve uploaded a new build (v0.3) for Urban Parking Simulator, which squashes two tiny bugs:
- When you successfully enter a valid parking spot (hence winning), and your current momentum makes you crash into a car, you no longer confusingly lose and win at the same time
- Timer no longer ticks down after you’ve lost for some other reason
These silly win condition problems took only a few minutes to fix, but it made me think (yet again) about how spaghetti-like my code was, even “for a prototype.” Earlier this week, I spent a few days thumbing through some “intermediate” Unity features/concepts, such as ScriptableObjects. I also brushed up on delegates and events. I’ll be playing around with these in some simple hello-world kind of experiments in the next few days.
Urban Parking Simulator’s second prototype is out! You can download it now and play with a friend.
You can read more about it on the project page, but I wanted to take some time to jot down a few notes.
Apart from being able to vent my frustrations about finding parking…
- Unity’s built-in image effects (from Standard Assets) are actually super cool and easy to use. You just drag and drop, and the different parameters are all very easily manipulated through scripts. It was a lot of fun designing the camera drone view.
- My “procedurally generated” parked cars came out all right. Basically, the level itself has no parked cars initially. Each block has a script that, at runtime, spawns parked car prefab instances along each of its four sides. Then, another script shuffles all 1000+ of them, and pseudo-randomly picks a handful to be turned into green spots or red spots. If a green spot is too close to the starting point, it will turn red.
- The drone losing signal when it strays too far from the car works surprisingly well in practice. This encourages players to really cooperate and simply use the drone to peek one block over or so.
- The time and distance bonus conveniently sets up a money system, meaning players can upgrade their drone/car for better performance and increased bonuses.
- I hacked together the car “physics” to allow for much better handling (less ice skating)
Upon revisiting this project someday, my to-do list would probably look like this (starting with the highest priority):
- Add some rudimentary sort of traffic (other cars that cruise by, pedestrians crossing, stoplights)
- Implement two actual lanes on two-way streets
- Randomize the spawn point (“home”) and orientation
- Allow (or require?) actual parking in the spot
- Build out money/upgrade system, which in turn unfolds a riveting story about a promising startup (“Uber, but for parking”)
- Procedurally generate everything, from crosswalk markings to stop signs to one-way signs to varied building dimensions to…
In the meantime, enjoy! Let’s see what we can work on next.