Working with my friends at SADfab I designed some brake cooling ducts to fit into the popular Garage Vary lip for the first generation miatas. Like my air intake design, the first step is to do a 3d scan and find out what space constraints I was going to be working with. The duct exit needs to be a 2.5″ OD to work with common 2.5″ silicone cooling duct hose. After a scanning, some quick measurements show that there is more than enough cross sectional area at the smallest part of the duct opening:
The first step was to print a test piece in order to verify the accuracy of the scan:
After verifying the fit, I mocked up a few different designs. This part is much more straightforward than my air intake system since there is no bend involved, and it’s not packaged into nearly as small of a space. In order to perform well the duct needs to do a few things:
1) Smooth transition between different cross section shapes. Abrupt changes in the surface can lead to turbulence in the flow path.
2) Create a continuous taper in cross sectional area from the large opening to the smaller 2.5″ outlet
3)Provide a positive fit into the bumper opening
4)Come up with a solution to mount the duct into the bumper and lip.
I settled on a dual wall design where the outer wall of the lip is a direct fit for the bumper, and the inner wall acts as the flow surface. For mounting I decided to use m5 countersink bolts with nylocks. In order to reduce the effect of intrusions into the air stream, I created raised bosses for the counter sink hardware and then blended them into the flow surface.
SADfab should have kits for sale soon. More information on their facebook page:
Over the last few weeks I have built up the gameplay systems for tools and fasteners in Wrench. I talked briefly about what my plans were for the fasteners in my last post, but now that the systems are finished I can show it off in detail. This video is an overview of how both the ratchet and the fasteners function in Wrench:
I designed a 1/2 drive ratchet that borrows the chunky silhouette common on ratchets from the 1930s and 1940s but with a modern machined look. This image is an in game capture dropped onto a background in photoshop.
From a gameplay perspective, a ratchet is a great starting point for developing other tools. With only a few changes, the ratchet code can be re-purposed into a combination wrench, a torque wrench, or an impact gun. Some of the interesting gameplay features in the ratchet:
- The ratchet reads the socket size from the fastener and automatically spawns the correct socket- No hunting for sockets.
- Dynamically adjustable ratchet stiffness that ties into the torque calculated at the fastener. Using some basic assumptions about how strong the player combined with the length of the tool I can approximate how much torque the player can overcome. The player won’t be able to use a 5″ 1/4 ratchet to install a crank bolt (they can try, it just won’t go well). Stiffness only increases on the forward stroke, this makes the ratchet mechanics feel free/unloaded while the forward stroke feels like you are doing some work.
- Fully simulated 60 tooth ratchet mechanism with sound + haptic feedback as you pass each tooth. Backlash between teeth is simulated, on a reverse stroke backlash is generated until you hit the next tooth. When the direction changes back to forward, that backlash total has to be used up before the tool will apply any rotation to the fastener.
- The ratchet attaches to fasteners with my EventUseItem input (a button press). Holding that button triggers a different event which I am using to swap from tighten to loosen. The LED on the ratchet indicates the ratchet direction.
In my last post I spoke about the art for fasteners. To recap, I build them with correct dimensions, including thread pitch. Since I have that data for every fastener I use it to accurately simulate fastener functionality. In my final implementation, fasteners are simulated in 5 phases. I will be using joint analysis software to generate accurate curves for ever fastener:
- 1- Attachment.
When a fastener is first placed into a joint it reads a variable called Rundown from the install location. This number represents the distance the fastener can move inward before the head begins to seat on the part. Reading this from each joint allows the same nut or bolt to be used in different joint configurations. This phase represents the first 10 degrees of rotation. During the attachment phase I allow the player to remove the fastener from the joint. The joint sends the fastener a variable “IsTorqueCritical”. Torque critical fasteners will need to be installed with a correct torque or bolt stretch amount. Non critical fasteners just need to be made tight.
- 2- Rundown.
During this phase the fastener can no longer be removed. In the rundown phase the fastener isn’t generating any torque or bolt stretch. This phase represents tightening the fastener until it becomes finger tight.
- 3 – Seating.
This phase is a short period where the head of the fastener and the part are being forced into alignment. The fastener begins to generate torque but there is no appreciable fastener stretch or clamping force.
- 4 – Stretch.
During the stretch phase the fastener is fully engaged with the part and it begins to generate a stretch value. Torque increases linearly through this phase. Fastener stretch is simply (DegreesRotation/360)*ThreadPitch.
- 5- Yield.
The fastener is stretched to the point of plastic deformation. This is what happens when a fastener is over torqued. Torque and clamping force drop off until the bolt fails. I haven’t fully settled on what I want failure to look like. Mostly likely the fastener will be considered junk and the player will need to get/purchase a new one. I will not require players to attempt to extract a broken bolt since I don’t think there is an entertaining way to make that happen. In some applications over torquing could be used to damage the part being clamped- If you use a 1/2″ impact to install head bolts on an aluminum head, you are going to have a bad day.
In addition to building art content for the cylinder head I have been working on improving the systems for part assembly and I have begun building the fastener object class so that I can start implementing tools.
For my assembly systems I have been working on a flexible way to allow a single part to be installed in multiple locations. This will be used for most fasteners but there are also many other parts that should install into many locations. I had a simple system in the prototype video but it wasn’t flexible to cover all use cases and this new system is much more robust. The trick to making a single part snap to multiple locations is both setting is both doing the actual part snap, and making sure you have a system to correctly store bools in order to run logic around install status. I’m using Unreal’s socket system to snap parts together- A socket is just a transform, there is no way to query a socket and see if it is occupied. If every single part in an assembly is unique and can only be installed in one location, you can simply make a bool for each socket, and then set the corresponding bool when a part is installed or removed. If you don’t actually know what object or what location on an object a part was installed, managing the bools becomes more challenging.
The solution I have come up with is using an intermediary Child Actor Component (CAC) any time I want one part to attach to many locations. A CAC is an instance of a blueprint that is spawned as a child object at run time. In my use case, each CAC is just a null static mesh (cube with visibility turned off) that has a socket I can snap to, and a single bool to indicate if that CAC slot is occupied. In this example, the hub object can snap to either the left or right uprights. The hub is actually snapping to the CAC object that each upright contains. The hub doesn’t need to communicate with the upright- On install/removal it only changes the bool on the CAC (called MultiBool). The upright is then responsible for checking the CAC, reading the status of MultiBool, and then settings its own hub installation bool to match MultiBool on the CAC. I’m checking the CAC for it’s bool status once every .5 seconds, I could probably make the check even less often since that bool isn’t actually used by the hub for it’s install or removal logic.
Here is a video of the wheel studs, front hub, and uprights all using this system:
I have been prototyping the fastener object class. The fastener object class is a subclass of the main snap part class with a bunch of added information:
Int: Fastener head size. Used to automatically swap sockets or wrench sizes to fit the fastener
Float: Fastener length
Float: Fastener thread pitch
Float: Major Diameter
Bool: Is torque critical fastener?
Float: Target clamping force
The art for every fastener in Wrench is accurate down to the thread pitch. I keep notes when I build fasteners so I know the dimensions. By including this data in each game object I can do a bunch of interesting things. First, I can make the visual representation of tightening from loose to finger tight appear accurate. If I know both the thread pitch the bolt can be moved inwards the correct amount per degree of turn added- This will make the number of turns to reach finger tight accurate. After the fastener is finger tight I can simulate an accurate clamping force based on how many degrees it is turned past finger tight, bolt length, thread pitch, and major diameter. That calculation can be re-purposed into torque wrench settings or bolt stretch gauge readings. Most fasteners in the game will not be torque critical, but they will all generate and store a torque value. I’m not planning to penalize the player for over/under torquing non critical fasteners but I can flag important fasteners (every internal engine bolt, lug nut torque, axle nut…) with the bool to see if it is torque critical and then penalize the player appropriately.
Recently finished art for the cylinder head fasteners:
I spent my last few weekends building a new bed frame and took the opportunity to use VR to iterate on different design sketches. This image shows some of the ideas I brought into Unreal to evaluate. A few were clearly too tall, or only interesting from an unrealistically low viewing angle. Eventually I settled on the design with the wood trim and hidden rear legs. This bed frame is reasonably light and very stiff, thanks to the semi space frame design.
Fabricating the frame was straight forward. This is all 16 gauge 1″ square tube. I made notch templates from my 3d files. The wood is mahogany finished with waterlox. When the finish is fully cured I will knock it down to a less glossy surface. I also cast some low profile urethane rubber feet to protect my floors and not ruin the look of the front legs.
The finished bed in place:
I do all of my work in a 570 square foot attached garage. The space needs to function as a photo studio, mechanics shop, a metal fab space, and occasionally I do composites work. In the last few years I reached a point where I had too many tools and parts to store and there was no way to get my space picked up and organized. Building content for this game involves storing a lot of parts which has made the problem worse.
This panorama is a good before picture. The 4×8 OSB box is a composites curing oven I don’t use anymore- it was the first thing to go. The back wall has a bookshelf for cans, a filing cabinet, and junk piled around it. I decided to build a storage rack to make better use of that space.
The total dimensions of the storage rack are 100″x62x24″. The bottom of the rack holds long stock, the next level up holds bins which are each large enough to hold a shortblock. Above that I have small parts bins, then a shelf for cans, and storage for the monolights I use for scanning. I can probably sneak some small shelves into the negative space between the lights.
This is the finished rack. I also added some t8 lighting on a switch:
All of this new storage has allowed me to reorganize my space. The area I use to work on cars is now much cleaner:
The back wall of my shop is more open and usable than it has been in years:
The prototype video got a huge reaction, way beyond my expectations. Different versions of that video have been viewed over six million times. It is really vindicating to see such clear evidence that there is an audience for this kind of game.
In the last few weeks I have been fixing bugs and improving the software side. This week I am back to building new content and my next task is the engine. I have a spare 2001 engine on a stand but its been cleaned up for install in my car. Building a digital version would involve complete disassembly, aggressive cleaning, then surface treatments on all the parts that would get scanned (block, oil pan, head, valve cover). I don’t want to fully disassemble the 2001 engine that is ready to be dropped into my car- That leaves me with finally doing my 1995 to 2001 engine swap and using my old 1995 engine. The earlier year engines are also a better fit for Wrench since I can skip the complexity of the VVT system.
My car is particularly easy to work on with the modified front end, removed popup headlights, and lack of accessories (no ac, no power steering). Here are some images of the engine coming out:
With the engine removed, I need to thoroughly clean every part, and take good notes so I know where everything goes. I measured the threads and length of every fastener so I could more quickly model them and identify re-use. I will probably end up adding a bolt head size to the measurements in another pass since I will need that to know what size wrenches will fit the fasteners in game:
This is the head after a first pass of degreasing. I’m using simple green (not aluminum safe, but this head will never go back into a car) and a cheap pressure washer. The surface treatment I use for scanning will absorb any oil and turn dark. The surfaces need to all be very clean.
I’m going to try and finish the cylinder head before moving onto the bottom end, which will have a similar number of parts.
The last two weeks have been busy. I finished my first large prototype milestone and have officially named my game Wrench. I am entering the phase of development where I want increased exposure. If you have been following my development, please share this.
My friend Matt Kohr put together this logo for me:
I also spent some time using Unreal’s new spectator screens for VR to make this video showing off the prototype:
Lastly, I added a media section to this blog where I will stick high res images of the art. Among the images I uploaded is this 4k wallpaper image that shows all of the parts currently working in the game:
I ended up making substantial changes to all of the gameplay systems and added a bunch of new functionality which I will detail in another post later.
The next step is taking all my art content and getting it set up with the pickup and snapping system I have already posted about. For VR, it’s best to do as little as possible in tick events. Current VR headsets run at 90 frames per second and future headsets my run at higher framerates. For that reason, I built all of my functionality to work using Begin and End Overlap events. Basically, when car part type objects intersects another car part object it executes the system of communicating between parts to find out what is or isn’t installed, and then runs the logic to allow install or removal of the part when the the correct criteria are met. This seemed to work well in testing but when I started implementing my content I quickly noticed the status of what parts were installed, allowed to be installed, and allowed to be removed were not being updated reliably. This manifested itself as parts that said they could be removed when they should have been captive, or the game erroneously preventing installation. My game is essentially a whole lot of pieces trading and checking yes/no values. Figuring out where the systems were breaking down took me a few days and these were the major causes:
I stopped using overlap events for pickup since it wasn’t precise enough (I detailed that one of the other posts). When the player pulls the trigger to pick up an object I use a sphere trace instead of an overlap. I was still checking overlap of a capsule collider in order to set the hand status to “can pickup” which is a subtle hand animation and a recoloring of the pickup indicator to show if an object can or can’t be removed or picked up. I had this capsule on it’s own collision channel and the parts had extra collision boxes on a matching channel. I had thought having separate channels would prevent any interference. In retrospect, the event is On Overlap, not On Overlap of Channel. Any time there was unintended overlap event from this capsule collider the execution loop for snapping and updating variables would get disrupted. Depending on the shape of the collision volumes and way the parts were being held, this problem may or may not have manifested which made figuring out what was happening confusing. The solution I came to was to replace the capsule collider with a trace at a regular interval (every .2 seconds works well)
When two parts overlap I do a sphere trace that is about a meter wide to get references to nearby parts. When I set this up I accidentally used simple sphere trace. Unreal has two categories of traces. A simple trace which only returns the first actor it hits and a multi trace which returns a list of all the actors that the trace intersected. In testing I didn’t notice the mistake because I was only working with a few objects at a time and the actor it returned happened to be the correct one. Switching that out for a multi sphere trace allowed me to loop through a list of actors and get information from all of the nearby actors. Like the last issue, this one presented itself intermittently depending on position of all the actors in the area.
This one seems obvious in retrospect but took me several hours to figure out. When the overlap event begins, I get references to nearby objects and check the necessary objects to see what is or isn’t installed. For installation, I check to see if the parts it attaches to are currently installed along with any specific criteria I decide (does the player have access to it? Is it realistic or practical to allow install?). For example, if the player installed a coilover shock in the car without a spring in it, I’m not going to allow them to install that spring until the shock is removed from the car and the top hat is off of the shock. AllowRemoval works the same way, I check nearby objects and decide if the part is captive or should be allowed to be removed. After the part is snapped in place, I change the part’s status to Installed. Other parts check this installed status when their overlap events occur and the system seemed to work well. The issue is that for AllowRemoval this doesn’t actually make sense.
None of these issues were particularly difficult to fix but they way they interacted with each other made figuring them out challenging. Because they were intermittent, it was hard to tell where one issue started and another began. When it seemed like I knew what breaking the game, the fix didn’t do what I expected, or the debug messages seemed to be firing without a clear reason. The takeaway for me is to test my systems with more complicated content that replicates how the game will actually work and don’t assume that a system is only broken for one reason.
I am moving on to implementing these systems with all of my art content. This means I am making hundreds of copies of the child class BP and editing the details for each part. I did some cleanup and color coding to make that process quicker: