01/09 - MVP BABYYYYY! ๐ŸŽ‰


Bon appetit everyone, tonight we are BINGEING WINGS! ๐Ÿ—๐Ÿ’ƒ๐Ÿ—๐Ÿชฉ๐Ÿ—๐Ÿฅต๐Ÿ—๐ŸŽ‰

As of earlier tonight I completed what I had set out for my MVP: we have a VR rig that lets us pick up chicken wings and eat them to increase things, a glass of  milk we can drink to decrease things, a timer to keep us honest, and a strange little windowless environment that sort of sets the whole thing up like a weird SAW-style challenge. All in all this took me about 10.5 hours (I'm tracking everything using Clockify). It feels like AGES to get where we are but I have solved a lot of problems and learned a lot already so I feel pretty good about it. That being said, this was the simplest part so I'm a little bit nervous about trying to implement the much more complex elements of the game, but also excited because it only goes up from here. 

And to celebrate, we even have a LOGO (big up to Midjourney for making a rather gory looking wing - everyone I have showed it to goes "Eugh!" which is exactly the right vibe for this project):


And now, a summary of today's trials and tribulations:

First issue of the day was sorting out why the wing counter wasn't incrementing and why the PMZ didn't work, but the knock-off red collider did. 

Wing counter was easy peasy - I forgot I had initially set all the UI elements up with their own scripts in a subfolder, so the Game Manager's wingCount wasn't even hooked up to the UI and the wings were actually incrementing a different variable. Whoopsies. I decided to combine those other scripts into the Game Manager because that feels like an appropriate task for management, and it's easier to see it all in one place. 

FRAMEWORK ISSUES

Sorting out the PMZ took over an hour and a half and had me running down all sorts of rabbit holes. The first issue relates to the framework itself - I so carefully placed the PMZ where I was sure it would be visible to the player, but realized once the game was running, I couldn't see it. I thought to check the scene window while the game was running and realized it was floating about two meters behind and one meter above the player. This absolutely baffled me - I had made the tracking camera the parent of the PMZ so they should be moving tightly together. 

After playing around with it more, I got more and more confused - I would place the player rig in the scene, but whenever I ran it, it would be in a different place. Additionally, when I tried with the headset on, it would load the player in yet ANOTHER place. Here's where I spent AGES playing around with all of the undocumented fields in the player controller component and eventually realized that there's some back-end stuff going on that moves the player height around based on different factors (height of the collider capsule, Y offset, if there's a HMD connected), and then did some trial-and-error to get it to a place that functioned. It's not perfect yet but you can lift a wing in the general area and it does the thing.

COLLIDERS, PT. 2

I sorted out the framework issue and had the PMZ floating beautifully in front of me but it still wasn't registering the collisions. After some more research, I realized I had wrongly interpreted something I read online: in a previous post I mentioned that child objects can't register collisions unless the parent has a rigidbody. This is WRONG. As I realized today, the collision WILL issue, but all collisions with children will be interpreted as collisions with the parent object. "Don't talk to me or my son ever again" sort of thing. In this case, the collision script runs by looking for the PMZ tag. The PMZ child object has this tag, but its parent does not. The parent object is the player controller, which is tagged Player-- I don't want to mess around with this because a) this framework uses a lot of scripts I don't understand and the tag is probably relevant and b) I have some ideas for other collisions on the player that would do other things and require different tags. 

The solution I discovered is to add a rigidbody to the child object, which will force it to check its own collisions. I did it, and it now works! Time to leave the nest and check your OWN collisions, PMZ. I'm a bit nervous about having a new rigidbody in the mix because they seem to me to be little buckets of chaos but I will cross my fingers and hope it doesn't go awry. 

LACTOSE INTOLERANCE

With that stuff squared away, I decided to tackle the milk next. It's sort of a riff on the functionality of the chicken wing, but with a few key differences:

1 - Instead of adding to heat and impressiveness, it subtracts;

2 - Instead of a binary state change (meat or no meat), I wanted the glass to hold multiple sips, represented in the mechanic as well as visually;

3 - Wings can be eaten as quickly as the player can manage it, but since the milk is a precious resource, I don't want it to be all chugged away without a thought. That means adding a delay function.

#1 was very simple to do. #2, on the other hand - I have to admit I am absolutely ashamed of my approach to this, I should probably go back and find a better way when it's not midnight--is more challenging. Storing how many sips left in the backend is easy enough, but the visual representation took a bit more doing. First step was to create the required visuals, which I decided to do by modifying a polyperfect glass of milk using the ProBuilder tool. We have a full glass (3 sips left), 2 sips left, 1 sip left, and empty. 

I wanted to activate the corresponding glass depending on how many sips are left and deactivate all the other ones. I KNOW there is a much better way to do this instead of ham-fistedly deactivating GOs that won't even be active in the first place, but this dirty bus ride still got us to the same stop so that's what I'm using for now. 

void UpdateMilkVolume()     
{         
switch (sipsLeft)         
{             
    case 3:                 
        milk3.SetActive(true);                 
        milk2.SetActive(false);                 
        milk1.SetActive(false);                 
        milk0.SetActive(false);                 
    break;              
}
}
etc.

I'm more pleased with the rest of the milk system:

void milkTimer()     
{
     timer += Time.deltaTime;
         if (timer < milkDelay)
         {
             isReady = false;
         }         
         else
         {
             isReady = true;
         }
     }
 void OnCollisionEnter(Collision col)
     {
         if (col.gameObject.CompareTag("PMZ") && sipsLeft > 0 && isReady == true)
         {
             Debug.Log("so quenching");
             sipsLeft--; //minuses one Sip from the glass
             GameManager.impressiveness -= 10f; //reduce impressiveness
             GameManager.heatLevel -= 20f; //reduce heat
             timer = 0.0f;
             Debug.Log("The Milk is ready = " + isReady);
         }
          if (sipsLeft == 0)
         {
             isEmpty = true;
         }
                  UpdateMilkVolume();
     }

This is all the progress of today; I think tomorrow I will finally let myself off the leash and brainstorm all the potential fun and polish elements I could add, then prioritize and make a game plan for moving forward.