[PC] Scraps: Modular vehicle combat

0.5.3.1

Today’s Scraps update doesn’t change anything exactly, but the install size of the game is now almost half what it was!

Basically there was a lot of duplication between the main game and server components. This was OK when the game was very small anyway, but it’s been getting steadily bigger, so I’ve refactored things so there’s no separate server app at all anymore. Now a server is just the main game with a server flag passed in, and all the duplication is gone. You can still host a game and play on it at the same time.

The last couple of weeks of dev have been a bit frustrating. I came up against an engine feature that I wanted which - my mistake - I had thought was in Unity 4 but was actually only introduced in Unity 5. Scraps has been halfway converted to Unity 5 for a while so I did a bit more on that conversion, tested the stuff I needed, and realised it still wasn’t going to work anyway. Not a real loss of time because I’ll most likely need to move the game from Unity 4 to 5 eventually anyway, but annoying because I want to get new content out as much as the next person.

I can actually show some work on content rather than code for once though. You may have seen the new pile of crates and barrels on the Test Map in the last update:

In the editor the crates look like the left image, but when the game is run they take on some random colour variation to look a little more interesting. Giving them all different Materials with different tints would blow out the amount of draw calls in the scene, so instead they all share the same Material, and the tint colour is set via the vertex colour on the mesh itself. Pretty simple code:

void SetTint(Mesh mesh) {
    // Tint is set via mesh vertex data rather than in the shader properties,
    // so that we can still use the same shared single material instance on everything!
    byte colour255 = (byte)(Random.value * 255);
    Color32[] colors = mesh.colors32;
    for (int j = 0; j < colors.Length; j++) {
        colors[j].b = colour255; // Setting the blue channel
    }
    mesh.colors32 = colors;
}

The meshes are simple so running through the array is super fast - but it only runs once on level load anyway. Then in the surface shader I use the blue vertex’s blue colour channel value to do whatever - it’s really just a way of getting information from the game to the shader.

// Any extra tint stored in BLUE channel  
// fmod is % (mod). Using it to map all possible RGB values
float4 tint = 0.7 + float4(IN.color.b, fmod(IN.color.b * 2, 1), fmod(IN.color.b * 4, 1), 1) * 0.3;
if (IN.color.b > 0) {
    c.rgb *= tint;
}

You may wonder why I set just the blue channel and then calculate a colour tint based on that rather than setting the whole vertex colour RGB and setting the tint to that value.

The reason is that a lot of things in Scraps are actually done this way - heat effects on vehicle parts, damage texturing on everything, and how shiny vehicle parts are (specularity) are all specified by modifying the different colour channels in the mesh vertex data, so that each vehicle can be shown with one Material and the environment can be drawn with another. So I need the red and green channels for other things. Otherwise every time something got damaged or heated up, it’d have to use its own Material and have its own draw calls, making graphics performance a lot worse.

I also made these barrels. The red one explodes of course. I wrote a generic script that I can attach to any world object to make it explode when destroyed and damage surrounding stuff.

Driving a vehicle by ScrapsEnthusiast there. Yesterday I also added subtle air control to the game, so that’ll be in the next update. It’s tuned more for gameplay than being realistic, but you can at least pretend it’s created from the torque of the wheels spinning in the air.

And I made some light beam/forcefield-style walls that I can use to create more subtle level borders for some levels. Functionally they work the same as the current walls.

For the next game mode I need lots of terrain, so I’ve been improving my terrain creation workflow. I can now take a basic low-detail terrain and put it through my Scraps-specific World Machine setup to get out a terrain fairly quickly with erosion and varied texturing.

OK, the bottom one still doesn’t look amazing yet, but that’s without any grass, fog, sky, etc etc. It’s a lot better than the top one considering the minimal manual effort involved. One thing that’s not obvious in the screenshot is that the “after” terrains also have more fine detail - so I can map out a fairly low-res base terrain and then run erosion on it to make it into a more fully detailed one.

The latest Scraps update adds a little air control, a save format upgrade, tweaked weapon hit forces, and a terrain graphics upgrade.

Full changelog:

2016-3 - 0.5.4.0

  • Terrain graphics upgrade. But no more switching to greyscale terrain when in low grav mode I’m afraid
  • Magically, vehicle save files are now also PNG image screenshots of the vehicle itself
  • Separated weapon recoil and hit force, so they don’t have to be the same anymore. Reduced hit forces in general - should help with Medium Cannon spam in particular
  • Rewrote the weapon movement range calculation AGAIN. More bugs fixed with it. Hopefully very correct and consistent now
  • Added a little air control: Pitch = Throttle forward/back. Roll = Throttle + Steering. More engine power gives more control
  • Finally the test map side road is actually 100% flat, right up to the ramp
  • Updated uLink and Steamworks.NET to their latest versions
  • Added grass density graphics option
    Bug Fixes:
  • Tooltips now update their text to match language changes without requiring a restart
  • Fixed mass from held wreckage not being subtracted after wreckage was offloaded on evac
  • Stopped evac pad ambient sound from playing when the pad is turned off (Test map)

Air control

I showed this off in the last update, but now it’s live. You can control your pitch with throttle and your roll with turning. You can’t control yaw - it’s a car, not a plane OK? Practising in Low Gravity mode is a nice way to get the hang of it.

Recoil
Weapon recoil and hit forces used to always be the same, which was arguably more realistic, but it meant that if I wanted a big kick on a weapon it also had to have a big hit. Often because of hit angles and multiple shots hitting in one spot, the hits would end up even worse than the recoil.

I’ve changed it so that I can set them separately, and reduced some hit forces. Hopefully there’s less of a problem with Medium Cannons and Plasma in particular throwing vehicles around now. Of course you can still push your enemies around to some extent.

Save Format

Those are actual save files. When you save vehicles now they’ll end up in a new format, which is also a png image - so now it’s easier to see what a vehicle is if you’re sharing it around.

The easiest way to see your vehicle saves is probably to open the Save/Load dialog in the game and click the button at the top right which takes you straight there.

Hosting these on an image host will most likely break them - you can try, but you’re probably better off using a file host of some sort. Anything that won’t try to modify or re-encode the image file.

Dev note: There are several ways to do something like this. Gimbal has awesome image saves, as does the Spore creature creator. One potential method is to use the image’s metadata fields to add your custom data, although sometimes those have size limits. Another method is to use something in the image itself that’s invisible or hard to see, like something in the alpha channel or the least significant bits. Or even just extend the image to have the data encoded in an extra part of it, using all the available colour data.

However, I’ve done this with the dumbest and simplest method possible: Just dumping all the save data at the end of the file! It was one of the options I’ve read about so it’s not totally unheard of. Sure image hosts will probably break it but all those other methods get broken by image hosts anyway. Seems like as long as you still end the png part of the file properly (works for JPEG too!), every PNG reader that I’ve come across reads the files with no problem. Scraps just ignores the image part and looks for my special marker, then starts reading the save from there.

Graphics
Scraps’ terrain graphics have always been pretty meh, and I wanted to get a better system for new stuff, so I’ve also back-ported that to the existing maps.

What’s actually better? Well, there’s nice perlin shadowing on things (how much there is varies with the terrain texture):

Although I had to get rid of the black outline FX on terrain.

Bumpy stuff is… bumpier:

And you can see there that the grass is better too, not just denser. The default Unity grass shader is a simple cutout thing: It takes a texture and says OK, if the alpha value is above whatever, I’ll show that pixel, otherwise I won’t show it. That gives really crisp but jagged looking grass. It also means that when the terrain engine tries to fade out distant grass, instead of getting semi-transparent grass you get grass that sort of gets cut down more and more at the edges.

I did a literally one-minute edit to the grass shader to make it do “proper” transparency, and the difference is huge!

I don’t think Unity has updated their grass shader for a long time. There’s a comment about Mac OS 10.4 in there. I was sure I must’ve killed performance as a tradeoff, but if anything the grass performance seems to be slightly better. Here’s my replacement WavingGrass.shader and WavingGrassBillboard.shader if any Unity devs want them, it’s like jumping from 2002 to 2012 in one fell swoop.

There’s also now texture blending based on heightmaps:

What’s happening above is, when there’s a mixture of two different terrain textures, it used to just blend, but now it’ll show the higher parts of the texture first (based on a greyscale height map I supply it), so the new texture sort if “raises up” out of the other one as it increases in opacity. For Unity devs, most of these new features come from using Tomasz Stobierski’s Relief Terrain Pack (it’s not exactly drop-in-and-your-terrain-looks-amazing, but it is very good once you bend it to your will).

I also wrote some custom terrain editing tools of my own to let me make stuff faster:

The heightmaps and splatmaps (texture layout) used there are pre-created - my tools aren’t that amazing - but it automates a whole bunch of stuff that was previously tedious. It also means I can edit heightmaps and splats and basically just click to update. Without much more work a terrain like the one above starts looking pretty good:

Still working on a new single-player mode.

  • Main Menu layout changes
  • AI players now show in the server info
  • If an AI player gets kicked from a game by a human player joining with no free slots, when a slot is free again they’ll now come back… for revenge
    Bug Fixes:
  • Fixed rotation range calc bug
  • Fixed “aim sphere” rotation range visual bug
  • Fixed null reference exception that occurred on dedicated servers in no-GUI mode with the new terrain
  • Fixed music player playing the wrong track if the track was changed and then changed back to the original track while the original track was still fading out

The main menu looks different, but it’s actually the same functionally. The main aim is just to sort of encourage starting games that other people can join, but it also makes room for introducing a new game mode later.

Equivalents:

Playing single-player:
Old: Singleplayer
New: Play->Start A Game, have “Allow other players to join” unticked.

Joining an Internet game:
Old: Multiplayer->Internet->Join A Game
New: Play->Join A Game

Joining a LAN game:
Old: Multiplayer->LAN->Join A Game
New: Play->Join A Game, select the LAN tab

Hosting an Internet game:
Old: Multiplayer->Internet->Host A Game
New: Play->Start A Game, have “Allow other players to join” ticked, and set to Internet

Joining a LAN game:
Old: Multiplayer->LAN->Host A Game
New: Play->Start A Game, have “Allow other players to join” ticked, and set to LAN

“Allow other players to join” is ticked by default, but it remembers what you last set, so if you always play Singleplayer for instance it’ll stay unticked once you’ve set it that way.

I just wanted to do a small fix-up update today to tidy some things up:

2016-3 - 0.5.4.2

  • Some performance improvements, mainly on CPU (the previous terrain graphics upgrade made CPU performance worse)
  • Added some grungy texture to scene objects in general
  • No more lag spike (one-frame FPS drop) the first time wreckage spawns
  • Added a little help dialog thing when first playing a game to point out adding AI players
  • Added hover tooltips to the server list that show the full game name, in case it doesn’t fit
    Bug Fixes:
  • Got rid of grass growing through evac pads on the test map
  • Missing button click sounds added to lobby screen
  • Fixed AI info in the server list going away after 30 mins when the lobby refreshed

By the way, I’m also aware that running the game in DirectX 9 mode (if you don’t have a DirectX 11 compatible graphics card) at the moment causes some issues with how the terrain looks. I’m looking into it.

Super secret new content preview, #1/10.

1 Like

Scraps got through to be one of the games in the Play By Play exhibition in Wellington later this month.

Play By Play is a new little games expo this year, started by a few locals: http://playbyplay.co.nz/schedule/

It should be a pretty cool showcase of locally-made games. Stuff like Swordy, Poly Bridge, Automation… and there’s an Australian games section too!

Scraps please don’t crash because I won’t actually be there to check on it.

1 Like

Congrats on the nomination - well deserved!

1 Like

I’m not going to push this because I hate it when games win on popularity or nepotism, but you can vote for your favourite game on the list here, and one of them is Scraps:

1 Like

This reminds me of Robocraft. Nonetheless good job and well done!

1 Like

Yeah, it was a little unfortunate that not too long after I started Scraps, Freejam first announced Robocraft, which really is quite similar. Although Scraps has much more of a focus on functional, inter-dependent parts and physics.

Didn’t win at PlayByPlay but that’s all good; here’s

Super secret new content preview #2/10

I made some stationary gun turrets to use for the currently-in-development new game mode.

I’ve also written some simple AI for them.

Note that generator and those heat-sinks: They also have inter-dependent functional parts like vehicles. Here’s a demo video of everything where I explain what’s going on:

By the way, I didn’t really mean to take two weeks between super secret new content previews - subsequent ones may be closer together. I managed to reproduce a stack overflow crash that I’ve been seeing sometimes come up in automated error reports, but haven’t been able to reproduce myself until now. So I’ve been looking into that as well and it’s been a bit of a rabbit hole.

At the moment if you run Scraps for more than an hour or two in one game (without quitting to the menu and starting a new one), and there’s heavy action like seven AI all fighting, it might occur. It shows itself in a way where the game will still be running but it’ll be behaving strangely and weapons won’t seem to do damage anymore.

It’s proven very elusive and frustrating to track down. The stack overflow doesn’t include a stack trace or any additional information with it. I think it’s related to a memory leak but the memory leak itself is proving very difficult to find. A leaked object like a vehicle mesh would be easy to detect, but instead it’s data on the heap and the Unity engine allows me no way to see what’s on the heap, just that the heap size keeps growing. I’ve spent too long trying different things and checking old versions already so I’m going to keep working on new content by day, and hack apart a branch when I’ve got time in the evenings, until I’ve unveiled the culprit there as well.

This week I made a flying drone enemy type.

They track you, zip around the place, and are fun to shoot.

Initial tests were interesting, almost boids-like:

I found that for the drones I could use a surprising amount of the same code I used for the turrets which was nice. Apart from the actual flying code, a drone is pretty much a turret that moves. And similarly to the turrets I showed last week, they’re made of functional parts just like vehicles. Here’s a group of them where the one on the right has lost its heat sink and is starting to overheat, and another gets it heat sink shot off:


(sorry for the huge gif! Webm support will get better one day…)

I gave the drones some basic AI. I won’t claim it’s anywhere near as interesting as Dave’s vehicle AI but it doesn’t need to be in this case. They don’t “fake” their flying though, they thrust around with real physics, so of course you can shoot or crash into them to throw them off. Hitting stuff way up in the air is tricky and not really good fun, so I’ve designed them to hover along close to the ground.

You can see the physics at work in this scenario when I first gave them weapons…

Yeah so, standard recoil is a bit much for them. Hence I must confess they are cheating a little now: It was either spend ages writing some smart AI that’d attempt to counter weapon recoil while flying somehow, or just let them have less recoil on their guns. I hate it when AI gets to cheat (vehicle AI never cheats by the way, it only sees what it can actually see and collects only scrap that it really collects) but the pragmatic choice here was obvious. So the drones you see elsewhere in this post are using specially engineered reduced-recoil MMGs.

See you next week.

Super Secret New Content Preview #4/10

Scraps vehicles so far always ostensibly have a human driver in a cockpit. Even if they’re actually controlled by the AI, there’s a cockpit that a person can fit in.

I wanted some mini vehicles as a sort of starter enemy, more like a ground-based fancier version of the drones I showed earlier. Easy enough to code because they’re still vehicles, but different. Instead of a human driver in a cockpit they have a Brain CPU.

It’s still a key component of the vehicle so the vehicle is lost if it’s destroyed, like with the standard cockpits.

I made it a micro chassis to use, that’d be too small for a normal cockpit.

To be clear, the CPU cockpit and micro chassis aren’t player usable, at least not with my current plans. They’re just for fighting against. Look how cute it is though.

I’m going to be away on family business for a few days next week (actually I’m already away now!) so I’m not sure if Super Secret New Content Preview #5 will make it on on schedule next weekend. But I’m hoping I’ll get enough work time in that it will.

2 Likes

Super secret new content preview #5/10: Road Encounter

A small taste of things to come.

Super secret new content preview #6/10: Less of a preview, more of a discussion

For the first couple of days this week I was working on something that I then decided against. I’ve got other work done but it’s not really ready to show, it’s mostly just code that doesn’t visibly do anything yet. So let’s talk about the other thing I was working on because I’m interested in what people think as well. I do apologise that this isn’t much of an interesting “preview.”

Part Wreckage
Ever since I started working on the scrap wreckage system for Scraps, I intended there to be two types of drops. When you destroyed parts, you’d be able to collect general wreckage that was like cash you could spend on parts during a game, after using an Evac Pad. That part’s in the game now. But there was also meant to be a chance that a whole part would drop when you destroyed one on an enemy. They’d have some amount of damage already applied like say 0-50%.

This got left out initially just so I could get the game out a bit sooner, but I wanted it for the new game mode. Some code was there, and I started adding the rest to get it all working. I got as far as having the part wreckage spawn, but not as far as making the interface for you to spend it, before I changed my mind.

My original idea was that if you picked up a part, it’d now be a free part to use on the Build screen (if you used an Evac Pad - if you died you’d lose it like with wreckage scrap). And so you could end up with a conglomerative scrap creation built of all sorts of scavenged parts, and I figured that’d be cool. But I weighed up the pros and cons again as I was restarting work on it, and I came up with:

Pros:

  • Interstate '76 did it and it was cool. At the end of each mission you’d get salvage parts you could use to slowly upgrade your car. They’d have damage to repair as well. And it was fun.

  • It’d make enemy drops basically like a loot system in an RPG, which is a time-tested effective system. General scrap drops are like coins and part drops are like gear/items.

  • It’d encourage interesting builds and often it is limitations that end up inspiring real creativity. Plus it’d provide more variation to the game in general. Work with what you’ve got, try new things, and building ridiculous vehicles out of a bunch of scavenged parts is well within the Scraps philosophy.

Cons:

  • Interstate '76 is a different game to Scraps, and while it worked well there, you couldn’t buy parts at all – it was all salvage. So the parallel doesn’t quite apply.

  • It could prevent interesting designs as much as it might encourage them, forcing people to use certain parts rather than follow their ideas. I’ve seen that Robocraft (a game with a similar concept to Scraps) recently switched from a money system to a loot drop system, and everyone hates it, because they can’t build what they want. Part drops would similarly stop people from building what they want.

Ultimately I’m thinking it’s actually a better idea to leave things as-is. If I did do it, I’d certainly make it optional in melee mode (the current game mode). If I really want some special weapon to drop from some special vehicle, it could instead drop a “token” that simply unlocks that special part as available to build normally (i.e. buy it with scrap).

Someone reminded me about selling parts. Selling parts is another complication. If you put a part on your vehicle and then delete it, you get its current value back. But if you can sell salvaged parts for full value then the feature is almost pointless! - the only benefit vs. just getting scrap directly would be that you can’t buy damaged parts so maybe you could use something that you couldn’t afford new. If you can’t sell scavenged parts for their full value, that’s gonna be confusing if you’re removing things from the vehicle to get scrap back. Not to mention complicating the code. I think this feature was a dumb idea from the start.

I like the concept of the idea, but it does seem like it would work better one way or the other, as it could get quite confusing with collected items vs purchased items.
Personally I like the freedom that the current system gives you, so I think you would need to somehow add the ‘collect full parts’ feature into what is currently there…and from your latest post it sounds like that could make things a bit too complicated!
Possibly this could work as a way to give players additional things to purchase that are not normally available? IE the NPC drops some cool bit of gear that isnt usually available, and picking it up gives you a ‘token’ that makes that item available for you to purchase (using the usual system).

Now there’s a name I’ve not heard in a long, long time.

1 Like

Yeah, that’s my idea basically. Maybe in a singleplayer game an AI drops a “super cannon” or whatever and you can now build it for the duration of that game. Or maybe you unlock a cosmetic thing that you can use everywhere now.

Super secret new content preview #7/10: “Procedural and hand-crafted”

This update is going to end up giving away a bit about the new game mode but that’s OK, I’ll explain everything at preview #10 and that’s not too far off anyway.

So, in the new game mode I wanted levels that are a bit different every time. Each one short but always something new. The standard solution to that is to use procedural generation, and have the code create something that’s different every time. But procedural can also mean bland, generating the same things with the same rules in different places, and for every game where it works well there’s one where it doesn’t.

I’m taking a sort of a hybrid approach here which with some luck will almost give you the best of both worlds. Here’s a complete map for one “world”:

That’s big - it’s over 7km long. But when a level generates it just takes a small chunk of that complete terrain, starting anywhere along it, and putting travel in a forward or reverse direction. I’m still tuning the exact length that’ll be, but it’s in the region of 1.5 or two kilometres.

Then within that area, things get more complicated.

Throughout the whole level the road is your guide.

Spawn on the road, leave on the road.

Within the level I can hand-place scenery, walls, turrets, enemy vehicles etc. A lot more stuff than the level will actually need. Then I tell the level generator OK, spawn some stuff in the level for a total of about x amount of scrap, and about 60% of it (or whatever) should be in stuff that attacks you, and the rest should be harmless (like crates). It then looks at all the groups of things and probabilities within the selected section of the map and decides what to spawn.

I’ve set it up so I can pack the entire contents of the level up so instead of having a bajillion things spawned in the world and then deleting most of them (which would waste a bunch of time and RAM), everything in the level is stored only as information about that thing, and then only what’s selected is spawned. Everything can be unpacked (basically, spawn everything) so I can edit it, and then packed again for in-game use. In Unity engine terms it basically stores the prefab used, the position and rotation, and then any other custom information that particular thing needs to configure it.

But the key feature is that I’ve also set it up so I can create everything in groups with custom spawn probabilities. Here’s an example of one group of things that could be selected to spawn:

This whole thing - the roadblocks, the turret, and the two crates - has a “normal” chance of spawning so it has about as much chance as anything else to be selected. If it’s too close to something else that’s already selected, or its scrap values don’t work out with what the level needs, then it probably won’t be chosen.

But within the group itself, it can choose different subsets of things to spawn as well. This subset will be chosen as soon as the level generator looks at it, so that it can know exactly what scrap value it’ll have.

The roadblocks in the middle are set to always spawn the concrete barriers OR the wooden walls, but but never both. So it’ll never actually look like the above in-game.

Neither the crates nor the turret are guaranteed to spawn at all, even if the group is chosen - you could get just the roadblocks. But somewhere between zero and all three will be chosen, with one of the crates in this case being a rarer spawn than the other. I could also set it to only spawn one thing out of three, or 1-3, or 0-2 or whatever. And the spawners can be nested so one of the choices could be another spawner with its own mix of guaranteed things and sub-choices.

But even as it is there are 16 possible combinations of just that one small set.

For AI vehicle spawns, I can now define patrol paths so they can patrol around, or just sit and wait.

Right now most of the code for level generation is done, as is most of the stuff to put in the levels, but I still have a lot of work to do in actually populating levels and in the actual framework of the new game mode. Sometimes it feels like things are progressing at a decent speed, sometimes it doesn’t, but rest assured that I’m working on it.

See you next weekend.