Assignment 3 | Extention

Let's get into it

Water

I started with figuring out the player buoyancy. Previously the script had used phyics to push the player up when under the water level and down when above the water level. This stopped working for two reasons, (1)When I used Unity's water simulation my script wasn't taking the simulation surface level (2)My script was using a Rigidbody as a reference but I needed to run a player controller as well, I found that these two components don't work well together when you're are only applying physics to one(This is just an assumption I've made).

Possible solutions

I tried using the second solution but I couldn't manage to find what was making the buoy sink. I then tried asking Chat GPT for help, but it was not helpful at all I'm not sure if it was because it was operating on a different version of Unity but the scripts it was providing were riddled with errors when I tried using them. This search for an answer to the buoyancy went on for roughly two weeks😡

When all else seemed to fail, I looked into the API of Unity's water simulation and found some samples on how to script behaviours. In the Unity manual on HDRP, I found a method on how to "FitToWaterSurface" :

using UnityEngine;
using UnityEngine.Rendering.HighDefinition;

public class FitToWaterSurface : MonoBehaviour
{
 public WaterSurface targetSurface = null;

 // Internal search params
 WaterSearchParameters searchParameters = new WaterSearchParameters();
 WaterSearchResult searchResult = new WaterSearchResult();

 // Start is called before the first frame update
 void Start()
 {
 }

 // Update is called once per frame
 void Update()
 {
 if (targetSurface != null)
 {
 // Build the search parameters
 searchParameters.startPosition = searchResult.candidateLocation;
 searchParameters.targetPosition = gameObject.transform.position;
 searchParameters.error = 0.01f;
 searchParameters.maxIterations = 8;

 // Do the search
 if (targetSurface.FindWaterSurfaceHeight(searchParameters, out searchResult))
 {
 Debug.Log(searchResult.height);
 gameObject.transform.position = new Vector3(gameObject.transform.position.x, searchResult.height, gameObject.transform.position.z);
 }
 else Debug.LogError("Can't Find Height");
 }
 }
}

This was a lifesaver 🙏

I tried applying this to the player(without the player controller) and they seemed to stick to the water really well. It is a little sad that at no point the player can see underwater or get any airtime from a big wave but I'm happy it's working😅

Then I asked Chat GPT to combine a movement and a looking around script with the current fit to water surface one:

Attribution: OpenAI (2023) ChatGPT (3.5 version) [Large language model], accessed May 16th 2024. https://chatgpt.com/share/8346202d-6ffb-43d5-9ca5-b03fb80e55db

THIS FINALLY WORKED, I've really condensed the effort I went to over the last two weeks to get his player to float but I was unbelievably relieved when I could actually play the game with varied water heights.🥹😭

This also meant because the movement was in the script I didn't need a character controller component, thus I could run one Ridigbody.

Once this was working I tried adding the old "proper" floating script to the buoys and playing the game but there were a bunch of funny bugs. One that would send the player ZOOMING and sometimes the buoy would float away, I have no idea why there was such a drastic difference in the bugs, maybe something to do with how far the player clipped into the model?🤷‍♂️

Although it wasn't fully realistic I just went with sticking the buoys to the water surface rather than true buoyancy.

Fog

My initial idea was to have clouds that came down from above and got darker, which obscured the sun. this turned out to be really difficult considering I needed the clouds to not be visible in the beginning then change materials and also cover the whole scene so as not to let any sunlight in☁️

I did a little Googling into how I could change the viewer's POV and the camera's render settings with fields and I found a great feature called volumes. These are emptys with box colliders that augment the viewer's vision in a range of ways. A sky and distant fog volume came default with the scene and I hadn't even noticed. I proceeded to add a second volume field that essentially increased the density and decreased the distance of the fog. It was really nice having the blended distance value meaning it would automatically produce a seamless transition into the fog. These were the settings I messed around with:

drawing drawing

This was a screen recording of me playing around with some colour grading. There's some really cool potential for creating a bunch of different atmospheres with this feature😮

Lastly, I added the sounds I had found on freesound.org and pixabay.com , I discussed this in a previous post

LIGHThouse

First to fake the lighthouse light I used the same process as the buoys when I made new objects and assigned an emission material to seem like a light. I did this because I couldn't find a way to make the lights bright enough and colour them.

Once I was happy with the light I started writing a script that would point a spotlight to either one of the three buoys. For this script, I felt like I had learned enough about C# from chatGPT and YouTube that I would be able to write it myself. I called for the input of a light and then used the "Transform.LookAt" component to make the light face an provided empty object. Then I wrote a completely unprofessional and janky script that would check:

If "On A" is true && "B Not triggered" = true Count 5 seconds move to B(an empty positioned at the second buoy) Set "On B" = true Else if "On A" is true && "B Not triggered" = false && "C Not triggered" = true Count 5 seconds move to C(an empty positioned at the third buoy) Set "On C" = true Else if "On A" is true && "B Not triggered" = false && "C Not triggered" = false && "A Not triggered" = true Count 5 seconds move to A(an empty positioned at the first buoy, staying in the same spot)

Then I just repeated this with "if on B" and "if on C".

I imagine good code is supposed to take as few lines as possible but for now, this clunky solution did the trick(the trick being, that the light moves from buoy to buoy in a circle but will skip the already triggered ones, effectively showing you where you need to go)

Then to my dismay!😧 Like a fool, I forgot to test the lights before forever writing the script. When I went to add the spotlight and trial the LookAt component I found that light could not penetrant through the density of fog I was using😥

I did some Googling and apparently, light cannot pass through the volumetric fields I was using, in an attempt to salvage some of the code I tried creating an emission material that followed the buoys like a halo (because for some reason emission can be seen in fog but light cant?).

This emission was way too bright and I couldn't adjust the alpha when using emmission😭 emission

This was a shame but I think after turning the sound distance up and the red lights up, the player will find it easier to know where to go.

Walls and lighthouse distance

First off, the walls on the map were too close to the edge. This meant when the waves got large the player could stand on the edge and see... nothing.

This was an easy fix, just moving the walls in a little. *Remembering the playable space needs to be 250x250 I left the width 70 units so the length could be above 250. (I think it ended up being 350🏄‍♂️).

Next continued the saga of distancing the lighthouse😣 As mentioned before in Assignment 3 | playtests I tried a parent to a specific axis method... I tried a force field... I tried a teleporter but nothing had the effect I wanted. Instead of moving the lighthouse(which would have been ideal). Plan B was to separate the island and have a bridge or connection.

I had seen these "water deformers" in Unity HDRP tutorials. I spent ages trying to find the water deformers in Unity, only to discover I was running an old version. I tried making a new project (With Unity's 6000.0.2f version)and copying the code for the deformers into the old version(previously I was running 2022.3.26f) but it wasn't compatible. So I migrated the game to a new editor version. Stupidly I forgot to back up and when I opened the game again I was welcomed with 28 error messages and apparently to make my game compatible unity had "altered" each of my scripts, preferences, and materials😵

I tried Googling each error and all the answers were either gibberish to me or required massive changes to my Unity settings, and scripts. I was so upset because there was no way to undo this either.

Just to manipulate some waterwater😔

I tried reverting it back but I received an error with the rendering engine and the scene couldn't display any water. I tried making a new project and importing the assets and scripts in but I was receiving the same issues.

I could see the issue was because the HDRP Wizard was supposed to "fix" all rendering issues but when I hit "fix" it would say "save and restart", yet no changes were made🤷‍♂️ In hindsight I see there must have been something wrong with the file either a corrupted setting or preference somewhere?

I decided to start again.

When restarting I thought it was best to stay on the old model because I knew the terminology for the scripts better. Just for fun I made a new 6000.0.2f version and tried the water deformer, It looked really cool🥲🥲

This process of resetting wasn't as hard as I thought. Because I understood the code I copied parts of it and altered bits I didn't need. Thankfully, my scene only had like three different assets.

While copying the code and reusing the assets I made sure to make backups and build games every minor change to act as a debug. There were no errors so building 5+ games feels like a bit of a waste of time now🫤. All up the rebuild took me about four-five hours. This was the new resorted hierarchy(with a few extra things)

heirarchy

Having a backed-up version meant I could do a little more crazy stuff without worry. I tried importing the script that the seagulls use in the Unity sample scene. These seagulls spawn in a box, move with the water(fit to the surface) then despawn on the other side. I thought this might be a cool feature to have for some clouds or fish underwater but when I tried applying it to my scene it creashed each time. Something in the parameters was trying to spawn like 1000 cubes in a one-unit range🤯 Wasn't really necessary but fun to try and a good example of why backups and saves are necessary (especially considering I don't think Unity auto-saves).

I had had enough of trying to figure out how to make the lighthouse non-accessible so I just went back to the invisible wall😔

The script to toggle the wall off was really easy. I wrote it myself and it just checked if the global boolean variables "Key.1" "Key.2" and "Key.3" were true then turned off the collider(these keys were set to true each time a buoy was triggered or the first time). (Since the buoys continued counting the triggers but not sending off the keys I added an easter egg if you trigger the buoys 100 times)🤥

Character switch

Next was the task of getting the character to switch. Milo mentioned to me in class that it would be odd if the player was a boat but they walked up the lighthouse.

This was really simple and worked really well. I used chatGPT to write a script that would toggle both player cameras and scripts. Then I adapted the code to (1) Tirgger on collision with an empty (2) Toggle the mesh of the person (3) Toggle the audio listener component on each camera (3)

ChatGPT printed script:

using UnityEngine;

public class PlayerControllerSwitcher : MonoBehaviour
{
 public MonoBehaviour playerController1; // First player controller script
 public MonoBehaviour playerController2; // Second player controller script
 public Camera camera1; // First camera
 public Camera camera2; // Second camera

 private bool isUsingController1 = true; // Tracks which controller is currently active

 void Start()
 {
 // Ensure the initial state is correct
 SwitchToController1();
 }

 void Update()
 {
 // For example, pressing the "C" key switches the controllers
 if (Input.GetKeyDown(KeyCode.C))
 {
 if (isUsingController1)
 {
 SwitchToController2();
 }
 else
 {
 SwitchToController1();
 }
 }
 }

 void SwitchToController1()
 {
 playerController1.enabled = true;
 playerController2.enabled = false;
 camera1.enabled = true;
 camera2.enabled = false;
 isUsingController1 = true;
 Debug.Log("Switched to Controller 1");
 }

 void SwitchToController2()
 {
 playerController1.enabled = false;
 playerController2.enabled = true;
 camera1.enabled = false;
 camera2.enabled = true;
 isUsingController1 = false;
 Debug.Log("Switched to Controller 2");
 }
}

I thought about how the boat could never walk up the lighthouse because its height was set to the water at all times, and if the player were able to escape the lighthouse they would sink(though this wasn't possible because of the fences).

Once I'd set up the character switch box and barrier wall all seemed well but when I playtested I found that the player would fall through the lighthouse, despite both having a Rigidbody?🤨 after tones of testing I realised I didn't check the mesh for holes in Blender🤦‍♂️ when I re-opened it I found that the floor had inverted normals, meaning the face side was underneath. I have no idea why the model on SketchFab was like this, especially weird because it was only the staircase, but I flipped it around and all was good😌

Then just for visuals, I thought it looked a little odd having the rocks just floating in the water so I added a mountain underneath and adjusted the water's light penetration. Modelling the rock mountain was really simple, I just took a rock from the existing model and scaled it on a different axis. One issue was that the two different objects(lighthouse and hill) were interesting which can create problems with collision, to prevent this I removed the colliders from both and imported a combined version with a collider but no mesh(When I combined the models in Blender it removed all the materials and rather than re-applying them I just removed the mesh, giving an invisible outline of the structure.)

Sunset

Finally(🥱) I wanted to add a nice finish. I had discussed earlier how the game should finish with a little more to go e.g. the lighthouse because it symbolises a future to explore(despite Jamie being adamant there you should be able to explore inside). So I wanted an end-game screen. I really hate it when games don't allow you to keep playing after you beat it so I wasn't going to trap the player in the lighthouse. I thought looking out onto the water could be nice but I wanted to make it a little more special so I played around with a volume box that changed the colours to something more orange and purple. I played around with using text and canvas to display a message but the brief wouldn't allow it🚫

Errors

I was talk'n a lot of shit about how other people's games were breakable(respectfully) but mine is definitely no exception, despite my best efforts.

When the player walks into a corner either in the map or on the rocks, there is a good chance they will suddenly incur a directional force in any random direction. 🤷‍♂️ I have no idea why or how this happens but it is very easy to pull off. Also if a player walks into the rocks on the lighthouse it is very easy to clip into them, I suspect this is because the position of the boat is calculated by the buoyancy script and not physics so when it moves into a mesh between script updates it can slip? maybe?

Final:

Video submission:

Onedrive to Mac and PC versions: https://rmiteduau-my.sharepoint.com/:f:/g/personal/s4089062_student_rmit_edu_au/EgUUfUnc5cFIlkD3vBe2Iz8BY3psD6eQBQsQbcME3Fk28Q?e=SoiG0s

Reflection coming soon...