Tuesday, 25 August 2020

Effects and Polish

Nearing the end of the project I'm now adding final touches like environment effects, sounds, tweaking gameplay and cleaning up any code.

Code

While doing the latter, I've managed to actually increase the fps! It's mainly due to the grass; theres around 400 individually placed grass objects. Each with an enemy script for how they interact with the player i.e. cutting. So because some 400 peices are constanly checking if they've been cut or not it bogs down the game quite a lot, I think it goes from 90+ fps to nearly 40 fps, which is a huge drop.
I had an idea though, because the grass deosn't need to check their status until the player is right within their vacinity, I added another code to check exactly this and enable / disable if close enough, lo and behold it works!
The game is more that 60fps again, its still a bit slower due to the sheer amount of grass objects, but its instantly better.


The code is insanely easy, no more than 3 lines. I guess 400 objects checking their distance to the player once a frame is much more efficient than 400 objects checking their behaviour state many times a frame.

Also I added in the random Rupee code I discussed in a previous post, seeing how the grass is working in game, figured might aswell clean its code up and add random chance to spawn one.


They now have a 1/10 chance to spawn, which feels about right.

Effects

I've also been working on implementing effects throughout, such as wind streaks, waves, clouds etc.

In this scene you can see all of the previously mentioned working in tandem. 
The waves and clouds are both particle emitters and both replicate how they look in Windwaker. The wind streaks were a bit trickier, these are actually line renderers. I initially modelled the wind and animated the texture to scroll through, giving the effect it's moving. Though when I spawned them, the material was shared, so they all scrolled at the same time which looked aweful.
After many hours I asked a friend his opinion and he coded a small script creating the same effect using maths, which is beyond my skill set.

User Interface


The interface is pretty much complete. Hearts, Rupees and Swim Gauge all work. The button text is next, I simply need to change these at runtime depending on current situation and is easy enough. 

Hardest aspect was the Swim Gauge. It has many things going on, for example when the player enters water it gradually depletes, there's also a sheen that flashes over it. Then to top it off, it needs to be reset upon entering the water.
Most of this was achieved via masks, the gauge drain was done with a square mask, its pivot set at the bottom and it's height reduced over time.
It does have two more effects, which I havn't included because I don't think they're warranted and would look quite complex and out of place for the demake. These were a particle emitter firing off little spheres above it and then the whole globe would flash red nearer to death (I may include this yet).

Sounds

The final aspect of this project is the inclusion of sounds. I wish I had done this as and when I needed them, but it doesn't matter. 
A nice and easy way to fire specific sounds I found is using animation events. These are little triggers I can attach to any animation frame, which then tells a script to do a particular function.


If you look at the timeline above, near the 0:17 mark you can see I've added an event to trigger "Swim", which is as he does a breast stroke. I then have a sound manager script I made and added it to the player, which solely waits for these events, which can trigger from any animation:


Other sounds are easy enough and can be place on prefebs and triggered when needed.

Finishing Up

Once these are done the rest are just little tweaks! It's pretty much complete as is (minus sounds). I may see what else I can add in the mean time.

Sunday, 23 August 2020

Creating and transforming an Interior

As part of the playable vertical slice, all the huts on the island have interiors. Most have nothing special in them and are just for exploring. But to keep in theme with demaking, here is the process.

To begin, I use exactly the same method I do for any 3D assets. Stages / interiors are just one large model anyway, so I find an interior I need, convert it to a readable format and put it in-game:

The stage has correct UV mapping after extracting so that's a big relief. It's missing materials though, so next I'll go through all the textures and re-assign them all.

These scene is much more vibrant now. The textures are pretty crisp too... Unity by defualt imports any texture at a resolution of 2k, originally these textures are around 128x128 or lower, which is a huge difference. So I manually go through and change them all to something similar to 32x32 or lower, because this was the maximum size for most N64 textures.

Next I make the level playable by removing any collision information for the model and then whiteboxing it myself:

The scene is now playable! Now to remove the collision boxes renderer so they dont display but still retain their bounding boxes and then I'll add some props / entities to bring it alive a bit more.

Now the scene looks ready; it has things to interact with, collisions, props, skybox etc. Now because of the collision boxed I placed before the camera also works within this environment.

But, as I discussed during some of my design research, some interiors from the N64 Zelda's are static, meaning the player has no control over the camera in the scene. To accomdate this and because I have numerous interiors, I've allowed free camera movement in most and some I've placed static cameras.

For this interior in particular, because it isn't too complex I've given it a static camera, right in front of the door against the wall. I've also replicated how these static cameras work, so instead of moving, the camera will just look at the player.

Whilst implementing this I came across a bug, so I had to add code to fix it.

When starting a conversation I disable all camera and player input, after the conversation I re-enable these. Because the new static cams are the same as the normal cameras, just with their logic disabled, when a conversation is ended it re-enables this script, making any static scenes freely-moveable!

To fix it, I added a bool check to the end conversation routine:

if (cs.moveCam) { cam.enabled = true; }

I then added an inspector element to make it quicker to toggle this for any current and future NPC's dialogue.

For this particular instance though this should be set to False!

The final result:

The only thing I wish I had time more time to do would be to remodel aspects of the interiors. But... as is after analysis most of these models are close or fall withing N64 polycounts, which means originally Windwaker could have effectively been released on the N64 if some limitations were included such as fewer effects and less open-world style gameplay!

To-Do

As I near the end of my project, I've summed up the last few things to tackle:
  • Add Aryll
  • Add Seagulls / Crabs
  • Fix Wind Spawner
  • Decide what to do with Rope Bridge
    • Maybe Add Woods
  • Remodel Outset for better collisions
    • Maybe Add Link's House Basement
  • Rig Demade Link and import into project
  • Add UI buttons (A for interactions and B to attack)
  • Add Links Sword
  • Try get swimming working
  • Add Sounds to stuff!
  • Create Title Screen
I've done the majority of the project. At the begining of the holidays I got a head start with prototyping stuff and I've also been able to re-purpose stuff I've made for both Silent Hill and Rush 2049, such as scripts.
However, due to circumstances and family, I missed a huge chunk of time, weeks even. So I won't get as far as I hoped. But I'm still on track to meet my initial goals. Would have been nice to add a second island and sailing.

Interactivity


Zelda games are well-known for their smaller interactions within the environment. Being able to cut grass, chop tress and even smash pots!

Over the last couple of days I've been trying to nail down these mechanics as best as I can. So far I've got trees working, I've got grass working to a degree (my method causes a drastic fps drop simply because I've placed over 500 grass objects as theres no simple way to go about this). And now, I've got pots working too.

All of these objects share the same mechanic, in that they are essentially "enemies". As such, I've coded a means to allow interaction between them and the player based on a simple AI code provided with the engine.

In the inspector on the right I've scripted on to the existing code to allow for item spawns! This is independant too for each object. so I can set whether or not its able to spawn anything upon death and also attach any prefab I want to spawn at said time.

My code checks when the enemy is dead, if its not allowed to respawn (pots and trees cannot), it then checks to see what type of "enemy" has been destroyed. It's not exactly clear in the code, but trees in the game have a rigidbody, which alows them to topple over, where as pots are static and dont move.

So checking which is which on death the spawns and obect set in the inspector if allowed and if its a tree will add physical force to simulate a sort of jump.

You can also see a check that tells the game to spawn an item set in the inspector if its allowed to. This would work with anything, but ideally it needs to be something that can be picked up otherwise everytime an enemy is destroyed any object instantiated would just clutter the game.

So for now, I made a few Rupee prefabs, that in turn have a check I scripted to allow for them to be either statically placed or if spawned, spring upwards like they do in the game.

By default, the bool spawn is true, so that when its instantiated via the enemy death it will automatically bounce upwards. When manually placing these all I need to do it disable spawn, and then it will behave exactly as it should in the world.

So together, these provide the basis in which objects can be interacted with in game. And is easily expandable, seeing as any prefab can be spawned.

I was dabbling in random ranges as in the games it usually is by chance when a object is spawned, but for the purposes of this project it's not entirely needed. I may add it for grass, because manually setting over 500 grass objects to spawn or not spawn anything will be very tiresome.

In the enemy script it would look something like this:

int rnd = UnityEngine.Random.Range(1, 3);
if (rnd == 3 && spawnPickup)
    {
    Instantiate(spawnItem, transform.position, transform.rotation);
    }


This would give each object a 1 in 3 chance of spawning an item. I could go even further and have mutliple spawn items to choose from. So the code would reflect this:

int rnd = UnityEngine.Random.Range(1, 3);
if (rnd == 3 && spawnPickup)
    {
    int rndnew = UnityEngine.Random.Range(1, 3)

        switch (rndnew)
        {
            case 1:
            Instantiate(spawnItemA, transform.position, transform.rotation); break;
            case 2:
            Instantiate(spawnItemB, transform.position, transform.rotation); break;
            case 3:
            Instantiate(spawnItemC, transform.position, transform.rotation); break;
        }
    }

It might not be the best way to script it, but it would work and could be expanded to add a new pickup everytime a new one was created.

Saturday, 22 August 2020

Chop Chop

Whilst finalising little bits here and there, I decided to try implementing cutting!

I wasn't going to include anything like this, simply due to lacking the assets to do so. But now it's in I'm glad, makes the overall experience feel fuller.

Friday, 21 August 2020

From GameCube to Unity Workflow (EXTRA)

(Read previous post first) Continuing on from my previous post about the process of extracting models from the GameCube to Unity, there is one more piece of additional information / process which I stumbled onto today.

Whilst exploring .arc files in the extracted game directory, I found that some of these files are completely broke or corrupted. Extracting them returns null folders / files, some of which are crucial.

In my case I was missing three types of foliage; bushes, trees and grass... These are pivotable in re-creating the overall feel of Outset Island.

After doing some research, I stumbled upon a couple of users with the same issue. In this thread, the user explains they believe they have found the .arc file containing various foliage. The use states that "Kusa.arc" translates to grass in Japanese, as with most .arc files here its safe to assume they are given Japanese names. The only downside is, this particular file is one of the few that is broke. I even ripped my own copy of the game (in my previous post I stated how I just downloaded a copy instead) to see if that would work, to no avail.

So it would seem this particular file is inaccessible with the current tools available...

At this point I realised I can use the same method I used for my Rush 2049 Remake. For Rush I used a set of tools used primarily for "ripping", these are used by modders and 3D printing hobbyists. These tools work by capturing all 3D and texture information currently on screen and exports them as a scene for 3D modelling software. I won't go into too much detail as the last link (method) goes through this in more detail.

Basically, I was able to capture a sceen in-game with all the foliage I needed:

After I cleaned them up a bit, they now look great. Originally all their normals were inverted, so they wouldn't render correctly. So I edited them and exported them for Unity.

Similar to the treasure chest in my previous post, the textures were off, so fixing these and rescaling the end result is pretty satisfactory:


From GameCube to Unity Workflow

The process of getting 3D assets from their source is rather long and pretty tedious (well at first it is). Even having gone through the process many times, its still confusing and doesn't always work.

To begin with, the original game needs to be extracted. Because I already own the game I downloaded and iso version just to make it quicker. Now with an iso of the game, its time to use an emulator, in this case I used Dolphin. Through Dolphin there is an option to "dump" the contents of the game, this is because the iso / files contained within are encrypted, dumping them allows them to be read in their source format.

Now with a dumped version of WindWaker, it is now possible to browse the files and locate what is needed.

For my particular uses, the "res" folder contains most of the assets needed. In this location there are sub-directories for stages, props and other misc assets. Browsing to just the objects is where all the 3D models can be found.

First couple of things to note here are, one: these are all "ARC" files and two: none of the filenames indicate what they contain / or are not English.

After some research I found out that these arc files are useable (thanks to the modding community), through a set of tools I can essentially browse through and see what is what. But this part is the most tedious, because again none / most are not English and another problem is that some wont work or are corrupted.

So, to begin, I will grab an arc file, in this case I shall use "Dalways.arc" (I have no idea what it is).

With this file, I've placed it with the tools needed to extract it, to make it easier for now.

To extract it or any other model, it needs to be dropped on "rarcdump.exe". Doing so will decompress it into it's original folders (very much like a zip file). Though for some unknown reason, this specific arc file will not decompress. This is because some individual arc files have additional encryption on them, as such they need to be dropped on "yaz0dec.exe" first to remove this lock, creating a new version of the arc file "Dalways.arc 0.rarc".

Now with this new un-encrypted arc file, it can now be dropped on "rarcdump.exe" to extract it.

Now with the new folder we can explore its contents!

Still the process isn't over!

This directory now contains all the information such as textures, materials, animations and 3D models needed.

  • bck = animation information
  • bldi = 3D model
  • bldm = 3D model
  • brk = unknown
  • btk = material animation
  • dbz = unknown
  • <extra>bti = textures
Thankfully there a couple of model viewers created for exploring these files!
So going into "bldm" and loading the file "boxd.bdl" (bdl is Nintendo's native 3D export file extension) with said viewer I am now able to see exactly what this entire arc file consists of.


So, it turns out "Dalways.arc" is in fact where the games treasure chests are located. In the same "bldm" folder and even "bldi" there are other chests and variations too. In addition to this, if I go to the root folder and look in the "bck" folder, there are animations that can be used. If I drop one of these into the viewer with the model loaded, it will now show what it does:


Now that I've established what this file is, that is has variations and even animations I can now move onto converting this into something native for windows, that in turn I can use in Unity.

To do this, there are three methods, each with pros and cons:
  1. The first is another model viewer named bmdview2, its much more basic than the one used above. But it does offer the option to export any loaded model and textures. Whilst this is the quickest method of exporting it does have one big downside; animations. It will not display or export them.
  2. The next option is Blender. a user has created a plugin named Blemd, based on the extraction tools used earlier (yaz0dec and rarcdump). This allows Blender to import the model file with textures and animations which then can be exported at a standard fbx. The downside to this method, is that it will just completely refuse to import on certain models causing Blender to softlock.
  3. The final method is similar to the previous one, this time we can use 3DS MAX and a similar tool named MaxBMD. Works exactly the same as Blender, this one has the same issue with softlocking, but will sometimes open ones Blender crashes on and vice versa. Both allow for animations to be imported alongside any rigging / bone information to be added.
In this case I shall use 3DS MAX. Running the plugin allows me to browse to where I extracted the "Dalways.arc", I browse to the bldm folder and open "boxd.bdl".


Once I press Import, the plugin now creates a new directory where the bdl file was. In here the plugin stores a save of the scene, the exported textures and the converted animations.
Now that it's finished the scene is loaded, the model is present and textured. A Character modifier is applied which allows any of the saved animations to be imported onto it.


Simply browsing to the new directory the plugin made (\Dalways.arc 0.rarc_dir\archive\bdlm\boxd\Animations) and selecting any will present a window to allow it to be applied to the model.

Its best to note that Max and Blender approach this differently. Blender will batch apply any and all animations in the adjacent "bck" folder and when exported can reduce the amount of files. Max on the other hand only allows for one animation per model, importing more or trying to append more will result in errors and / or a softlock. But from my experience, Max's import method is more accurate with its animations...

Now the model has been imported and it's animation applied, its now ready for export and fir use in Unity! A simple File > Export > FBX will suffice.

Now we have a Chest asset in a native windows format, one that can be read by any 3D application as fbx is the standard for 3D assets.


Once the chest has been imported into Unity, its ready for tweaking. It has lost it's material information, this is due to no textures being imported. So quickly browsing to where the MaxBMD plugin exported the textures and animations I can easy drag these into Unity.


Now that the texture is in Unity, the model has now automatically applied it to itself. Depending on the model it may look fine, but usually this needs editing. The texture's properties are more often than not usually incorrect too.
WindWaker uses a lot of mirrored textures (see the MaxBMD importer screenshot, 4 images above) to save on storage space, so when imported to Unity the textures will look out of place:


This happens because Unity automatically sets any imported texture's wrap mode to "Repeat", this is so that the texture will be tiled if stretched over a large area. But in this case we don't want it to. So changing the Wrap Mode to "Mirror" will fix the issue and display the texture as intended:


Finally, now the material / texture has been fixed, it's time to look at the animation.
On the Chest's inspector window, browsing to the animation tab will show it has one animation, the animation I manually imported in 3dsMax via the Character Assembly modifier.


As you can see, the animation is playing in the preview to the right. If you also look at the top of the preview is the animation name "boxopenbox". If I browse back to the original arc folder I decompressed, in the "bck" folder is said animation!

The final in-game result:


To conclude, the process is very long and tedious. I've mastered my own work flow to be as efficient as possible. But still, it takes a long time because none of the original files express what they contain. How does "Dalways" translate to "Chests"?

Given enough time, it would be possible to explore and catalogue all the files properly into a spreadsheet for easier browsing. At any rate, this is my process, maybe it will help some modders out in the future!