We managed to make great progress in the basic features that our simulation will need. We made a basic map layout, changed the lighting and skybox to make it nighttime. We also started on basic visual effects to simulate being under the influences, such as general blurring, motion blurring and vignetting. Although the effects are basic, they can easily be increased to make the game unbeatable by most players.
This week we made solid progress on our project. We began the week with a preliminary draft of a road and terrain. It consisted of a curvy road running through a forest, and the entire terrain was flat. By the end of the week, we had a much better looking map modeled on a stretch of road in California. The road features changing elevation, though at some points the road is still unrealistically steep, causing the car to fly into the air briefly. Once the elevation has been appropriately smoothed out, our map layout will be complete. If we choose to add an intersection later on, we might need to raise some land out of the water to form the intersecting lane.
Map area centered around Glenhaven, CA. This area was chosen due to easy terrain for a road, with interesting water and hills on either side.
USGS Terrain Height data (Accuracy of 10m) of area pictured at left.
Rendered terrain with road in Unity.
Driving is now set up to work with either a keyboard or an Xbox 360 controller, but in the final version players will be able to control the car using a steering wheel with haptic feedback. We put in the order for the steering wheel a week ago, but we're still waiting for it to arrive. Next week we'll implement this functionality since we should have the steering wheel by then. We will also wait for the steering wheel controller to fine tune the parameters for the vehicle script. This mainly includes the torque that gets applied to each wheel, whether we are driving a 4WD or 2WD vehicle, maximum turning angle, and maximum driving speed. Currently a simple user interface system in the car tells the user the currently playing song name and what their current speed in MPH. Eventually, we'll also want the steering wheel to have animated turning in game.
Rendered view inside vehicle as seen by the user in VR.
If you drive off a cliff and fall into the water, the game will now register that you've died, and you'll be sent back to the start of the track. If you hit something at high speed, you'll also be reset, but this approach is problematic because if the player is driving quickly and goes into the air for a tiny bit, then lands, the game will think that they've crashed. In real life, you generally don't want your car to fly into the air anyway, so this might not be a big deal in our finished game, especially after we've smoothed out the elevation.
We've implemented a few mechanics to simulate the alcohol consumption. One is vignetting, to darken the edges of the player's field of view. We've also added heightened motion blur, and regular blur. We haven't created any automated system for increasing these upon interaction with a user interface, but we do have the basics down. This will ease our transition into automating certain interactions and timings with scripts.
We managed to make great progress in the basic features that our simulation will need. Harshita implemented double vision and and basic audio warping effects. Dean implemented AI cars to spawn in driving the other direction and drive by waypoint to follow the road. Nathan added some polish and implemented daytime/nighttime level switching, increased the road width, and added road banking for realism. Nathan also implemented steering wheel animation so that you can see the wheel movement in game. Ryan added slow blinking. We decided to not implement haptic feedback for the steering wheel controller due to technical difficulties with the Mono framework, using deprecated APIs and time constraints.
One of the last visual effects we needed to add to complete simulated inebriation was the blinking effect. We want to simulate the user slowly blinking every few seconds for some added challenge. The reason we chose this effect was that when someone drinks too much, especially at night, they start to feel tired and have trouble keeping their eyes open. The first way we tried to add the blinking effect was by programmatically modifying the vignetting effect over an interval to simulate the eyes closing and opening. Unfortunately, the maximum amount we could shrink the vision with vignetting wasn't enough for us. After that, we got an asset from the asset store that simulated the blinking effect and set it to play in an interval when the user is driving while drunk (the effect is disabled when driving while sober during the day).
We also added double vision, an effect that can result from high levels of BAC. We implemented the effect by duplicating the main camera, setting one camera to target the right eye, setting the second camera to target the left eye, and rotating both cameras inward about the y-axis. That is, the camera targeting the right eye is rotated towards the left and the camera targeting the left eye is rotated towards the right, with both cameras at the same position. Since our eyes are able to converge for objects located at a distance, the effect is most applicable to nearby objects, such as the steering wheel, road, and nearby trees.
Alcohol also effects hearing, so in addition to visual effects we added audio effects to the radio music that plays in the vehicle. The effects include a lowpass filter, distortion, and a reduction in volume, and these effects serve to simulate diminished hearing. We use an audio mixer asset and send the radio output to this mixer to add the effects.
We intend to start with no visual and audio effects and then gradually increase their intensities as the BAC levels increase to reflect the actual progression of effects that alcohol has on vision and hearing.
The steering animation was simple to add into the game as the car model we chose had the steering wheel model separate from the rest of the vehicle. The animation script only had to rotate the wheel mesh around the z-axis. The wheel transform was (0, 0, 0) relative to its parent, so the transform could be trivially calculated using the axis input from the wheel which is between -1.0 and 1.0, and then multiplying by half the total rotation. In our case, our wheel can rotate 900 degrees in total, so we can scale the in game rotation to be between -450 and 450 degrees to match the wheel controller in real life.
Level switching was a combination of assets and basic scripting that was already there, but not combined in a cohesive way. Basically, our game has a LevelOrchestrator object that has a script controlling everything about level switching and enabling and disabling the necessary components in the scene for it. Since we have designed our game to have two levels, one during the day so the user can get accustomed to driving and one during the night where the effects of being under the influence will ramp up over time. There are several tasks the LevelOrchestrator must complete when doing the switch (which is done either by the F1 and F2 keys, or when the user hits a collider at the end of the day level). The orchestrator must keep track of the current level, put the player in the correct place with the correct rotation and velocity, and the orchestrator must also setup day or night specific objects.
The approach we have taken for night and day objects is to have all of them in the scene, but only enable them or disable them when required. This ensures simplicity because we are using the same map for both the daytime and nighttime track and just having the player driver the track in the reverse direction for the night level. The orchestrator must deal with changing the water shader for daytime, change the user's camera to the one that has the DUI effects applied to it, and change the skybox between day and nighttime. Other things include the lighting and the static police vehicles at the end of the nighttime level, which will be used as a static ending failure state because we do not want the player to "win" the game.
More systems will be added to this in the future, including kicking off the DUI scripts to increase the effects over time and having hooks for the post game level where we will show the user some statistics about DUI.
My task centered around adding cars to the road to make the scenario more realistic for the user. For the MVP we thought it would be easier to just have cars going in the opposite direction for the user because it would be easier since we won't have to care about the positioning of the player's car.
The first part of setting up the traffic flow was creating a "Traffic Spawner" script. The script would be used in that you would select a GameObject and after every n seconds, that GameObject. And so what I did with that script is attach it to a GameObject at the end of the track and every 3 seconds it would spawn a WaypointTracker prefab that would follow the circuit laid out for it. Although the prefabs will be spawning at the same place, since they will be spawning at different points in time, that won't look like that to the player.
The next part of creating the traffic flow was creating the circuit that I talked about in the previous paragraph. This part was pretty difficult for me and I'm still carrying over this task to next week. To create the circuit, I used the WaypointCircuit script in the Standard Assets package where I would set up way points on the track for the AI cars to follow. The part that was troubling for me was that the script would create a closed circuit which we don't want since we only want the cars to go one way without them having to loop them back around. To try and solve this I looked online for a different Circuit script that can create open routes rather than closed ones. Another idea that I got in lab yesterday was just to modify the WaypointTracker script and change it to check for the last waypoint and so if the car reaches that waypoint, then just call Object.Destroy().
This week we had our demo in from of the class. We polished our game to the point where it delivered a solid, cohesive experience to our classmates and collected some great feedback regarding what direction we should take the project. Overall, we now have a solid technical basis for delivering both drunk and sober driving experiences to our players. For the rest of the quarter, we'll mainly be focusing on improving the narrative of our game and making sure our players are taking away the right message that we're trying to deliver.
Previously, we had levels for day and night, but the only way to access these levels was to press the Function keys (F1, F2, etc.) on the keyboard. That obviously isn't an intuitive experience since the players will be using the steering wheel throughout the game, and we don't want them to need the keyboard or mouse for anything. Because of this, we built a menu that opens when the game loads, and let the user select whether they would want to play in daytime or nighttime. We further broke down the nighttime category with three different levels of difficulty. These difficulty settings each feature varying intensities of simulated inebriation. This way, the user will be able to navigate the game without ever needing to interact with the keyboard. In the future, we may add further control options to let the user jump back to the menu from within a driving level.
The menu screen
The way the different difficulty settings are implemented is that there are separate post processing profiles associated with each difficulty setting. When the user selects a level in the menu, the associated post-processing profile is applied to the camera in the car. Using this method, we don't currently vary the alcohol effects over the course of the same level. One thing we've considered is programmatically increasing the intensity of the alcohol effects while the player is driving their car, and if we want to do that, we'll have to augment this method of applying effects.
Car crashes have been a challenge to implement correctly and there are still bugs that are related to the way crashes are being calculated. New in this feature however, are car crash sound effects and the car lights on fire when you get into a crash. This is so it is very clear to the player what just happened. The simple system for calculating whether a crash has occurred is to see how quickly the speed of the vehicle changes over a delta of time. In the case of our code, we consider a crash to be any change greater than 5 mph over 20 milliseconds (a fixed update function call). It seemed to work fairly effectively most of the time. There is a glitch where when someone crashes during the day level, they are reset to the beginning of the day level. Due to changes in velocity and teleportation of the player vehicle, it considers there to be a second crash when none has occurred. In the next week I will try to determine the cause of the issue and fix it!
We updated the terrain by adding road signs to guide the driver. We included speed limit signs in both directions to indicate the maximum speed limit along the highway. We also added signs before extremely curvy portions of the highway that let the user know in advance that they should slow down on upcoming curves. Based on feedback received, we will make the signs shorter and more readable.
Minor audio changes (Harshita) : We named all the songs so that actual song names appear in the radio dashboard.
This week I finished polishing up the way point circuits for the AI cars and so the circuits should be finalized for our demo. I also worked on tweaking the values of the car controller scripts so that it looks more realistic. For the nighttime AI cars I also put on headlights for them so it looks a little more realistic. One feedback from the user testing was that it might be interesting if when the AI cars pass the player, their headlights flash in the user's eyes.
My primary goal for this upcoming week is to finish the final level that displays the DUI statistics after the user crashes. This is important to our narrative of dissuading users from drinking and driving. Some other things that I will be working on after finishing this statistic scene would be tweaking the visuals of the car models and the headlight flashing; both of these should be fairly easy compared to the statistic scene.
A couple simple features have been added this week. The first is ending the nighttime level when the player reaches the end. The second feature is a fade out to black and fade back in on level transition, this helps alleviate possible motion sickness due to the teleportation of the player because all of that happens when the user's vision is faded to black.
Overall, everyone seemed to really enjoy our game. Regarding the difficulty of the game, we got some varied responses. Some people thought that the daytime level was too hard, and that they
The main way we'll be improving the controls is that we'll reduce the sensitivity of the steering wheel. People typically said that they felt the sensitivity was too high and that they were having a hard time taking turns without going careening off the road.
Some people gave the opposite feedback, where they felt that the highest difficulty was too easy. Something a lot of people would like to see is a simulation of the delayed response time people have when under the influence of alcohol. To simulate this, we were thinking about keeping a buffer of user input, and then feeding that in on a delay when the user is drunk. To simulate more drinks, we can increase the delay.
Here are our notes on the rest of the feedback received:
This week we primarily focused on the educational impact of our project, while also finishing up the last visual effects.
During our demo, one piece of feedback we got often was that it would be good to have some sort of input lag on steering. When you're drunk, you move sluggishly, and the best way to simulate this without actually giving players something to drink is to put a delay on handling user input. The way I implemented this is that I created queues for all the different types of input (steering wheel, accelerator, controller, keyboard). At each update step, the user input is read an added to the appropriate queues. To introduce lag, the queues are pre-populated with a certain number of blank inputs. Each update step corresponds to a time increment of 20 ms, so we just calculated the the appropriate number of blank inputs to fill the queues with for each difficulty. The input lag levels we chose for easy, medium, and hard were 100, 200, and 300 ms respectively.
I fixed two bugs in relation to AI cars, one was the AI cars spawning without the correct path to follow, I added a simple part into the AI car spawning script that adds this to the spawned AI car. I also fixed an issue where the player's vehicle lights would turn off when near an AI car and this was simply a matter of the player vehicle car not having "important" priority lights so Unity would automatically disable them so as to not have too many lights in the scene. I also fixed a bug related to ambient lighting not changing intensity properly, which was fixed by changing to using Color instead of Color32 inside of the script that sets the values. Finally I fixed a bug related to collision detection with the vehicle and other objects where the user could potentially get trapped in an endless looping crash and not be able to continue. This fix required removing several outdated and unused collision handlers that would emit events in parallel with the current collision detection system.
The feedback that we received from the peer review included some major portions of work that other people have done or are still in our todo list, but I completed the things that were only tuning values. I decreased the turning radius, acceleration of the player vehicle, and maximum speed of the player vehicle. Some more challenging things I fixed were disabling the headlights during the daytime and making the road signs less tall. I also added volumetric fog by modifying the standard assets dust storm effect. I changed the effect tint from brown to white and changed some of the particle effect values to make it more realistic. I then duplicated the particle effect system multiple times to cover most of the low elevation road.
We want to have narrative to say why the user is currently in their situation. Thus we had to implement a system that shows narrative text to the user and also waits for their input so that we can show them more than several messages in a row. This code uses coroutines for fading text in and out as well as waiting for the user input. The problem with waiting for user input however, is that it runs an infinite loop if the user never presses a button. This means that I had to carefully make sure the coroutine was stopped before running the coroutine again. Only having one of these coroutines running at a time means that the code handling the messaging system simply stops and starts the coroutine every time we want to play some messages. This works for our use case but isn't particularly clean.
We also make sure in this code that the user cannot drive while the narrative text is displaying so we ensure that they read it.
As part of our narrative to dissuade users from drinking and driving, I worked on the final scene for when the user crashed into an obstacle (another car, a tree, the water, etc.). What would happen is that once they crash, it would wait for a few seconds before fading out and switching to another scene, that would show the outcome and some statistics related to DUI deaths. This was an interesting feature to implement because I was able to learn about the Unity Scene managers as well as the fading in and out of text. I still have to expand on this feature by allowing the user to go back to the main screen once they are done reading the text. Also, I was thinking of maybe having a list of statistics which are randomly chosen and displayed so that the same one isn't showed over and over again. Finally, I need to add music in order to enhance the pathos of the scene.
As part of our narrative to dissuade users from drinking and driving, I worked on the final scene for when the user reaches the end of the nighttime track and gets stopped at a police checkpoint. Similar to the crash scene, once the user gets caught by the police, the current scene slowly fades out and the final scene fades in. The final scene displays the outcome, statistics about DUI arrests, and an advisory message. For the final demo, I will allow users to be able to press a button on the steering wheel and return to the main menu from this scene. I will also add music to this scene that plays in the background while the user reads the text.