I have the wall opening now, but I started by doing something kinda dumb.
At the moment the project contains the results of a bunch of experiments, many of which have shown me the wrong way to do things so they need to change. One of those are doors and lifts.
Up until now I’ve had separate components for doors and lifts that move with animations. I’ve been planning to merge them together into a “Moveable” class that doesn’t use mecanim. That will enable me to determine their behavior from a map file, and will mean I don’t need a folder full of animations and animator overrides. I thought I’d kick that off with the moving wall.
The trouble with moving the wall like the doors, is that if it just moves up the same way the other doors do, the top will rise over the roof height which I don’t want. In Doom the top of the wall stays at the same height, just the base moves up.
In Doom most of the wall textures start at the top and tile down, but the textures for doors start at the bottom so that as the base moves up, the textures move with it making it look like the whole object is moving. To replicate that behavior I need to move some vertices while keeping others in place. But doing that stretches the textures so I also need to adjust the UV map. So I copied the wall object and moved the vertices and UVs to where they should be when it’s open. Then I created a morph component which blends the vertex and UV positions from one object to another. I’m thinking this is great, because it will enable me to move doors and lifts in essentially the same way that Doom does (I’m also secretly super chuffed with myself because I’ve wanted to be able to morph UVs along with vertex positions for as long as I’ve been doing 3d animation and just realized that I finally have the ability to make that happen).
I got the morpher in and working beautifully, but as I’m looking up towards the sky watching the door open I realize that as cool as it is, I didn’t actually need to do any of that.
See, early on when I first got the level geometry into Unity I came across a problem. Looking out the windows I could see the end rooms.
Doom creates walls between the camera and the offending rooms, and projects the skybox onto it. I tried a few things, and ended up using the VR/SpacialMapping/Occlusion shader (This only works in forward rendering, and isn’t necessarily my final solution, but works for now and sticking to forward rendering keeps things viable for VR down the track). The ceiling of my sky mesh is the same height as the top of the walls, so anything higher than the wall automatically gets clipped by the sky. This was already happening with the other hidden door, I just forgot.
I figure moving an object is less intensive than adjusting vertices every frame, so I added start and end positions as well as the morpher to my Moveable component so I can either move the game object or morph the mesh (I’ll be interested to see if moving the doors and lifts will cause problems in any other maps. I suspect that most will be fine, but there are likely to be a few fancy ones that require morphing).
Lightmap Switching
The other difference between the walls and the interior doors, is the lighting needs to change when the walls open.
At the moment I have the interior doors lightmap static, but not casting shadows. So they receive shadows, but the surrounding walls are lit when the door is open. This works reasonably well so far for the interior doors, but doesn’t work for the wall doors because of the sunlight. So for this map I need 2 different bakes, one with the walls closed and one with the walls open.
I quick search revealed Laurent Harduin’s lightmap switching tool - exactly what I needed. I read through the instructions. It looked like it might also help with another problem I’ve had. I find that for some emissive surfaces I want them more emissive for baking, but less emissive to look at. With a bit more time spent learning shaders I’m sure I can come up with a solution, but for now I’m changing emission settings before and after baking which is a pain. I thought about writing a script to do the changes for me, but if anyone else has a better solution please let me know.
When I actually went to implement it though, I realized the tool was setup for static scenes with light changes such as changing time of day. Instead of saving different lighting solutions and baking them into a single static scene, I need to have the same lighting solution with different scene layouts, so I did things a bit differently.
-
Instead of saving scenes with different lighting solutions, I saved 2 empty scenes: E1M1LightBase and E1M1Light01 (I put an empty game object into each just in case). These essentially act as names for the folders that will contain the lighting data.
-
In my main scene I added the LevelLightmapData component to a new game object and added my 2 empty scenes to it.
-
I baked and stored E1M1LightBase.
-
I opened the walls and baked and stored E1M1Light01.
-
I added the LightingScenarioSwitcher and customized it to trigger when the switch is hit (this works ok because the switch is in a different room to any of the lighting changes).
I nervously hit play (It all seemed to work, but things rarely work properly the first time) and BAM my sun disappeared. What? Ok, something wasn’t quite right, but I tested the switch anyway, and the lighting swapped. Yay! So it’s kind of working, but why is the sun disappearing?
In a Doom map, nothing has backsides, so without adjustments this scene suffers from considerable light leakage. I mean it’s horrible:
I will need to come up with a different solution when I switch to realtime GI, but for now Shadowmask mode is my saviour. It removes most of the light leaks.
After a bit of investigation I realized the lightmap switching tool wasn’t storing my shadow masks. Luckily it wasn’t too difficult to add shadowmask support. I rebaked and it worked!
After testing I realized I need to have 3 lighting solutions, because the little wall closes again. Unfortunately there’s no easy way to ensure that change isn’t seen, but in most cases the player will be on the outside of the wall so it’ll be hidden.
The other great thing about storing lighting this way is also that I can muck around with the lighting as much as I want, and know that when I hit play, it’s going to look right. I can also store multiple versions of lighting and quickly swap between them to show a colleague or a client.
Anyway, that’s my update for today.