Logo with title ".Blog"

Briefs

Low-effort content for certain microblogging platforms.

Grass

Physically simulated grass.

Single triangle rigged with two bones. Lower bone is attached to a colliding part via BallSocket. Upper bone has a VectorForce to keep the whole thing upright, and an AngularVelocity to introduce some instability that simulates wind.

Some translucency can be simulated by rotating the upper bone by 180 degrees, which also rotates the normal of the top vertex.

One MeshPart can be rigged to fit up to 128 grass units, whereas Beams would have to be 1:1. But in terms of visuals, Beams have much more to offer than Decals.

A texture can be used, but artifacts occur on the upper edge because the texture wraps around and repeats.

you can get around this using the TextureLength property

@ChrythmDev, 10:23 PM · Jul 14, 2022

I guess that works, but the texture has to be upside down.

On whether using beams is practical: disregarding physics, most of the time goes into updating beam logic. Actual rendering is sub-optimal, but it isn’t the bottleneck. Not sure what causes LOD cutoff (it’s not affected by graphics settings). Might be a memory thing.

RemoteEvents

RemoteEvents will happily receive a giant dictionary from the client, happily deserialize it, and happily reflect it to Lua. This seems like it would be bad, but in practice, the client gets disconnected before it has a chance to send concerning amounts of data.

MeshID

Roblox serizes both the MeshID and MeshId properties.

<Content name="MeshID"><null></null></Content>
<Content name="MeshId"><null></null></Content>

Both have CanLoad and CanSave set. Does studio just let one override the other? Answer: Yes. The property that appears after overrides the one that appears before.

The Ownership Problem: A vaguely formed idea involving the fact that instances in the game tree can be accessed by anything at any time. If I knew what I was talking about, I’d write a post about it.

Source of truth

The DataModel as the single source of truth is an awful one, because the engine calls all the shots, while scripts are second-class.

Because the engine can be made to do nothing by default, I get around this by conceptualizing my collective codebase as a server, with the data model as a client. This does create two sources of truth, but the data model is usually a good little client that behaves as it should.

A consequence is that this “server” must be considered as a whole, so libraries must be made compatible with this model. But this is fine, because any 3rd-party library is already going to be incompatible in some way no matter what.

Assuming Roact doesn’t expose its own source of truth to be incorporated into the “server”, it could just be treated as another “client” instead.

If you bought a brand new house in a developing neighborhood, and you want free rocks for landscaping, start digging them out now. Search around your neighborhood while it isn’t filled in, too.

Physical URL

URL Present in Physical Book Tragically Broken by Word Wrapping

UpdateAsync

If UpdateAsync calls the update function again, the result of the previous call is discarded.

Because this is so simple to understand, the docs choose to not mention it anywhere. The result for me is years of UpdateAsync never quite clicking. One tiny sentence is all it takes.

DRY

Keyword of Don’t Repeat Yourself is “Yourself”. Just because libraries have been written for trivial things doesn’t mean you should use any of them.

Most of these kinds of libraries are, at most, collections of snippets. They are short, complete, and are not worth an entire dependency. Just inline it.

Duality

Sometimes you feel like spewing out a prototype, other times you feel like describing the entire thing in increasingly microscopic detail before any code is even written.

Thinking of a positioning system based off of the virtual memory technique, where “virtual” regions are mapped to “physical” regions. A physical region is addressed by place ID, then 3D position, allowing regions to be mapped to a single place, or spanned across multiple places.

Surveys

When a survey is paginated, it’s probably because of some statistical thing that involves preventing future questions from influencing current questions.

Starting to get annoyed by Luau making features available before they’re complete.

Incidentally, tagged unions aren’t refined by the else clause.

The really annoying thing is that the only way to find out a feature is incomplete is to get halfway through writing something only to have the type checker start slapping you with errors for things are logically correct.

If I have a tagged union of A | B, and if v.type=="A" then refines to type A, then logically, else should refine to type B. Yet I have to find out the hard way that it doesn’t.

Filtering

Filtering a list can be done in-place just fine. You wouldn’t use an immutable list because you need to filter it, you’d use it because to need to retain the original along with a filtered copy.

Using constants instead of literals in certain cases will reveal dependencies you didn’t know you had.

-- Bad: literals.
local things = require(Things)
RegisterThing("foo", things.FooThing)
RegisterThing("bar", things.BarThing)

local foo = GetThing("foo")
local bar = GetThing("bar")



-- Good: constants.
local things = require(Things)
RegisterThing(things.Foo, things.FooThing)
RegisterThing(things.Bar, things.BarThing)

local foo = GetThing(things.Foo)
local bar = GetThing(things.Bar)

From scratch

Making from scratch isn’t as fun. Better to take an existing thing and make it do something else. My first experience with Roblox Lua was turning a jetpack into a sword.

Easter eggs

Stop making easter eggs just to tell everyone about them. Those aren’t easter eggs.

Which is faster: table.unpack or table.move?

table.unpack is going to be dumping potentially tons of values onto the stack, while table.move can avoid the stack entirely.