Everything posted by Oafkad
-
Overthinking is a killer.
I did update it a smidge. if (data.UniqueID != Accessor.ReturnComponent<HandlerMoosecat>().UniqueID) { return; } I can only assume this will be a faster comparison than the full classes, I bet if we look it up the answer is "No those are exactly the same speed."
-
Overthinking is a killer.
I had been mulling all the different ways that we could validate if the actor receiving an event response is the one that should be responding. But seeing as our act calls are unique per actor I can just do a simple equivalency check. if (data != Accessor.ReturnComponent<HandlerMoosecat>()) { return; } It is literally this easy. At the start of my act function I just compare the incoming data to the same data that is on this state machine. If they match its the same object that made the call, if not it is just another live actor that matches the type. You might think "Will this scale?" and the answer is basically yes. We'll have a finite number of actors, Humans, Moosecats, perhaps eventually other magical creatures. But each time you are looking at a single new handler for probably hundreds of variants of that thing. This should mean that going forward while I do need to add additional support it ends up being a few lines of code to cover me for that entire new family of critters. I don't know why I was overthinking this. But starting tomorrow we can run the test on multiple cats. I'm very optimistic and now I've gotta go discard some changes.
-
Brainstorming - A better lookup
Currently for the cats I am simply doing a lookup of behaviors in the scene and checking for those that implement the satisfier interface. In doing this I can tell if they are something that *could* satisfy the curiosity or needs of a cat. Classically this hasn't been very efficient in Unity and I'm not even sure I need to do it. If we think about it, when assets are created or "destroyed" I'm actually just activating and deactivating them. If we lack a sufficient number of "pooled" assets then I create a new one and add it to the pool. Eventually when a player has played long enough they reach a point where no new assets are created or destroyed. This means I've actually got collections of every possible asset already in the spawners. So what I'm thinking we'll do is create a central hub that has all of our spawners and their pools, then we can pass in the ID of the kind of thing we are looking for, food, play, rest. From here we'll check for a source that is available and active in the scene. Once those needs are met that object will be assigned to the cat and vice versa (thus removing it from the available pool). If either the asset or the cat is adjusted in any way this will break the link. The cat will become free and the item will be free for other kitties to interact with. The only things this won't cover are objects that will be in the world while I'm building, but we can always write a script that skims all that data when a zone is finished, if we assume the items cannot be removed. If they can be removed then simply skimming the map on load and seeing if anything is not currently tracked will be sufficient. The last note for future me, I will want this container to live in an SO that is reset on load (when in editor), because we need it to persist between scene transitions, assuming we do full unloads. Time will tell.
-
Oooh a piece of candy...!
Our little buddy is finally coming together! The Moosecat will now transition between Idling, Wandering, and Traveling to precise needs. These will also transition between one another as you'd expect. I still need to take care of the listeners for multiple Moosecats but I'm real excited! We are finally getting things actually going. Just check out how fast this little one is going? Look at that terribly slapped on trail renderer for effect!
-
Pineapples and Apples growing from the ground, like nature intended.
Alright I need to do a few things tomorrow. We need to add in a declination (or veto) feature to our event system. That way I can do things like cross reference uniqueIDs or other data to see if an event should be respected by all listening assets. Once this is done we can then move into the next step of finishing up our wandering system. That will get us pretty close to having the baseline logic system done and allow me to move onto other work. I still want to add a few debugging adventures and have Moosecats travel to them when they can't satisfy a need. I also need to think about how kitties will act if their target gets taken by another cat while they are on the way. I suppose we could add little images of their faces over the asset so that the player (and other kitties) magically know they want to use that thing. I'll think about it. I want it to be fun and simple to track for folks. As far as the title goes, we've got spawning done for now. It spawns random food at random points across the central navemesh which is where I'm doing all of my work.
-
Nobody goes hungry tonight.
I've been adjusting some of my work. We now have a food spawner. It currently spawns the food at the base of my player's feet. This has consequently meant that with each spawned food I was a little bit higher in the air. Needless to say...I ended up being QUITE high up. So I suppose tomorrow we'll work on making it spawn around the map instead of under my feet. Then we can have kitties searching it out!
-
Saturday - Improving the Event System
Per usual it is late at night and I'm writing this up. So I'll try to make this quick. But we have a few enhancements that were finished today. The first was that I can now add and remove listeners when entering and exiting states. I haven't fully tested it at scale, as we don't have a scale TO test at. For now it is sufficient that I experience no errors. The next update was with the event system that I use. The problem was that adding events at runtime to the event listeners would result in an empty field instead of a populated one. This doesn't matter at runtime for builds but in editor it is very annoying. Here are some before an afters to help visualize the issue: Now we can easily see what action the callback is! This is really helpful for making sure things were assigned properly. I've precompile flagged the change so that it won't actually be part of the runtime builds. I've also enhanced the Component Collection system so that we can add components to the collection lookup tables at runtime. This isn't super exciting but it DOES mean I can find these listener objects trivially on all my actors and game states. This is huge for me and I'm pretty happy about it. Tomorrow we'll hook up some spawners for food, so that our kitties can enjoy tasty targets raining from the sky. Then I'll add an "adventure square" this will be our stand in for the front gates of the Manor. Cats that can't satisfy their needs will walk over to this square and leave on an adventure. Those adventures will be for finding more food, or for finding some entertainment. In this way our cats will never end up stuck starving for fun or food Neopets style. Instead they'll take the initiative to solve it themselves. This will be slower than doing it yourself but it means you could let the game run overnight if you wanted and you wouldn't come back to furious or starving cats (but I repeat myself). We'll also see about adding the ability to sleep in any open square when all beds are taken or missing. Finally I need to remember to add in a distance check when our cat picks a target. If the asset is too close it actually won't generate a path because the target is already beside it. We'll need to perhaps have the cat just immediately transition to interaction state in those situations.
-
There was no response.
Alright, we've shifted away from needing response objects. I believe this will be fine. One thing I need to sort is having our kitties enable and disable their listeners as their states change. This will help reduce the number of objects listening for certain event calls. I can't imagine this will have a HUGE impact but its one less variable when testing out new systems. That'll come tomorrow. But for now? I need to go get some sleep, it is mighty late.
-
Transitions standardized! Almost time to move back to Kitty Logic.
Alrighty! We now have our standardized transition system for the state machine. Conveniently this helped me discover an error with prefabs and adding components. That is now fixed so we are golden. Additionally I found a bug in the unique ID system (again? Yeah, I know) and that is now patched up! It is such a good time looking through your code, patching up holes, and adding new systems. If you can ever find the energy I really recommend it. More gifs are incoming probably next week, but for now have a lovely night!
-
State your business! I demand a response!
Tonight I worked a bit, admittedly not as much as I wanted, on the response system of our state machine. I need to update it for two reasons. The first is so it has the same rad component access that my actions do, but ALSO because I want to standardize how we switch scenes. Why? Well if I do this I can actually write a script to visualize the state machine and how each thing transitions! If I do that then I can even post them here. Start generating something akin to automatic UML diagrams. It'll be fun! So hopefully soon you'll see that. It is critical I fix this now before moving on further for the game because having state transitions all willy nilly will make debugging later a nightmare.
-
Alright, maybe you eat a little too much.
Alright! We are getting closer and closer. The cats now will correctly search out a source for their needs. Unfortunately, I forgot I had critical set to 25% so the moment our kitty ate a few things were obvious to me. eatingEverything.webm The cat ate BOTH food items in range. Very cat like but unintended. The cat immediately went towards the ball because that status was ALSO in critical. So at least we know it transitions through states properly. The cat then...ate the bed? Huh...I didn't know that was an option. I guess I'll be looking into that tomorrow.
-
Mondays are balls.
niceballs.webm I've begun work on the interactable logic for non-consumable items like balls, beds, doors, etc. I was feeling a bit silly after I added them so I gave them a bit of physics. This revealed a really amusing problem with the inverse kinematics in our fella. You notice that he just steps ON them instead of walking into them? That's because they are so short he knows he can hop right on up there. That's a definitely mistake and very amusing. I'll save that problem for later. For now we've got some nice shiny, somewhat bouncy (shockingly dense) balls. For now I'm going to have interactable objects set your needs that it can satisfy back to 100% instantly. We can add in routines and other logic down the road. When you are developing try and design things a bit like a chain. Each link being made to easily disconnect and add a link between them. As long as you keep doing this you'll never be screwed when a new idea comes along. Well, almost never. Also don't be worried that you might be your future's worst enemy. You will be, just accept it, and try to enjoy yourself. Every single person alive has made mistakes that will haunt them for their entire life, for one reason or another. If you find someone that hasn't I imagine they'll be an insufferably boring or empty person. Doesn't mean it doesn't suck! But yeah, important to remember while developing. I might start posting guides on every little thing involving development in a separate section. So if you are interested in learning that may be coming soon.
-
Next comes sleeping and fun.
At this point I think the food portion of the Moosecat AI is good. We'll need to hookup our interaction state but I want to wait for that until after we've put in a bed object and some kind of fun object. This will be my project for tomorrow and tuesday. Because at this point it is late on a Sunday and I'm kinda tired! I've been up very late the last few nights working on the game and I'm very excited to see where it is. kittygoesfoodhunting.webm Our little buddy got hungry and went searching for food. Obviously its a bit rudimentary, they are not set to stop at their interaction distance, nor do they call interact yet. But once they do it'll feel a lot more fluid. The plan is pretty simple. When a cat realizes they have a need that must be met they'll start searching one out. If any are available they'll make their way to that thing and get to interacting. If a cat has no needs that are urgently needed, they'll just wanted towards some random part of the map. Along the way if they see something appealing that is open for interaction they'll change their target to that and wander over to it. Then they'll interact with it until the need it satisfies is complete (or the item is consumed in some cases). After this they'll return to idle, check their status, and then transition into wandering after a short delay. This delay might ultimately be different from cat to cat but I'll worry about that later. The end result is that if you have a few dozen kitties around and you zoom out, you should be able to see them regulating their lives and trying to live their best cat lives. Obviously if you have a task you've asked them to do, they'll return to that instead of idling following the satisfaction of a need. We will have relationship meters for the Moosecats and the player but I don't know if we'll let them go into negative. I feel like that would betray the nature of the game. I'm also mulling over how to solve the problem of a need not being satisfied. Perhaps kitties will travel into town to get taken care of there. Or go on a special adventure that ultimately satisfies the need. Like wandering to a mountain hot spring to relax, or a famous sushi diner to get some food.
-
When to fix a bug?
Well I'll be a monkey's cousin! I figured it out! Let me take you on a journey! public static Dictionary<System.Guid, IUniqueID> _idCache = new (); So we've got this dictionary that is used in an editor script correct? What happens is when we create new assets, or load the project in editor, we check if this cache is currently empty. If it IS that means that you likely just opened Unity for the first time. Or maybe your power went out because the breakers are stupid...guess which one happens here sometimes. Now this is fine, but how do we know when an asset is *deleted*? That's a good question, we can't check if the deleted item matches an ID in the dictionary because its already destroyed by the time we know. All we know is where it used to be and that it was destroyed. However we DO know something was deleted. if (deletedAssets != null && deletedAssets.Length > 0) { //Clear out any null entries that snuck in. foreach (var IDKVP in _idCache) { if (IDKVP.Value == null) { _idCache.Remove(IDKVP.Key); } } } So what we do is iterate through the cache, which is quite large, and remove all of the null assets from it. Could we do this more efficiently? Probably. Will we? Probably not. Because this is an editor only tool and at least for now it isn't even remotely close to taxing my PC. This logic won't be in the delivered game and is literally compiled out at build time. So, then, what was I doing wrong? I was checking and removing deleted assets *after* I did the "Is your ID already in here?" Check. Ok, well Oaf...I still don't get it. Each new asset gets a new ID, so how would these things end up with the same ID as an old asset. Simply, they couldn't unless... You switch scenes. When I would leave one scene and come back I've got a static dictionary sitting in my memory. This means that initial check that checks every, single, asset goes "Holy cow! This ID is already taken! Lemme assign a new one!" So in the end it reimports all 178 or so assets that currently exists. Now that I've flipped the deletion logic to before the iterating through looking for duplicates we solve the issue. No longer are there x null copies of every asset in the dictionary. Now the only things in the dictionary during any check is a valid object currently loaded in the scene or related to those scene loaded assets. So huzzah! That's a bug down! Now I can get some rest.
-
When to fix a bug?
So today I noticed I've got a mistake in the logic for assigning IDs to assets. So my question is how much time should I put into fixing it now? Would it make more sense to just move onto other work and simply make a note that I need to fix this? That's kind of a hard question for me to answer. I'm sure it'll just annoy me until I do solve it. Perhaps just in terms of mental health it might be best to handle it now. If not, perhaps I should start a section for this game that is known bugs. Then as we solve them we can update the bugs as fixed. That could be fun for tracking how many things are good (or bad). And it allows me to have the fun part of bug fixing without actually using Jira again. Forced to use it for work, would rather not do that at home.
-
Builds are Working! That's good.
For you this image might not spark much. A few test assets in a world where a lot of the logic is invisible. But for me this marks a moment that I should have done ages ago. Actually building to device! The good news is that my new systems for serialization and referencing across items is working. We generated our player at the right location, our item, and our Moosecat. So my progress while making the game actually saves and loads properly when I open it up in builds. That's pretty cool for me. Starting tomorrow we should be able to do some cool gifs of the cats searching out food and gobbling it up. No animations for now obviously but all of these systems provide the foundation for something that has me very excited.
-
The Beauty of Control - Back to Editor Nonsense
Unity doesn't let you serialize Guids without a lot of headache. Odin Inspector makes this easier on serialized monobehaviors and serialized scriptable objects, but guess what? Did you guess? Yep! You can't use the monobehaviors in prefabs. And that's what I'll need them for 99% of the time. So I had to get sneaky, smart, devilish even. Ended up finding a wrapper for Guids and doing some seriously heavy edits on it. The original was fine but it could be finer. I've now got it so the "serialized" part that we see in editor doesn't actually get built at compile time (since it won't matter anymore). I'll test it out on a build this weekend but I'm optimistic. Everything passes the glance and sweat test. I'd say smell test, but that reminds me of the term "code smell" and I hope I'm never a big enough douche bag to actually say that without being ironic. But I digress! Wait that sounds smarmy too. Oh no. Anyways, very productive night. Also helping my wife with some coding challenges she's having. Very busy, but feeling very good.
-
Need Needy Kitties
We've officially got a container of all the supported needs in the game. These come with a decay rate, and urgency cutoffs. Even cats made before this work was introduced will work with it, which is a design scheme I'm planning to keep carrying forward. This should mean as we move into alphas and betas we might not need to clear data unless we want to. Tomorrow we'll start work on having the cat searching out their needs. I'll make a "bed cube", we'll have them try to eat, and then I may try to have a cat meet up with another cat to talk. But we don't have emotes yet for that last bit, so I suppose it'll be in a debug log once they reach one another.
-
Editor Scripts are a dangerous drug.
Tonight I found myself wasting a lot of time on two things. Oxygen Not Included (market research, I swear) and editor scripts. The latter was definitely a genuine waste of time. What I was trying to do is not urgent or necessary as I'm the sole engineer on the project. Once I broke out of that hole I started working on the status update action for the state machine of our kitties. We've now got a container within the cats that houses the state of their needs, what that particular cat thinks is urgent or critical, and how quickly their rate decays. What I haven't decided on yet is how long an in game hour will be. This will likely dictate the true update frequency of these stats. Because checking the stats of every cat, on every frame, for every stat on those cats, will end up being a lot of loops every single frame. Depending on our max cat limit that might not matter, but I'd like to not go so overboard in the beginning that I require some kind of complex overhaul just to make things work. So instead we'll just check if a new hour is upon us, and if it is we'll do the check. Another option is that I could have an event that fires each time an hour has passed in the game. We fire off an event that all of the characters are listening for. Then that adds the substate of status checking. It checks all the statuses. If any are in need of satisfaction it will update the target on the kitty and set their need target to that. I just convinced myself of this now. I'm gonna add that to notion, good plan for future me.
-
Idle Moosecats - The Beginning
Alright! We are getting into it! I needed to work on a few things today. The first was the container for needs. This will house the identification for that need, and then the various stats required to track the needs progress. We have three levels, fine, urgent, and critical. Anyone that has ever taken care of cats knows that this is already one to two stages too many. With the container created, tomorrow we will create the various need artifacts themselves. These artifacts will then be housed inside of a collection that helps us connect those need IDs with the ones on our cats. Because of this somewhat loose connection it means that we can add new features to the kitties at any point in the future and your cats will just have those new needs added to their data on load! I'll be sure to have them default to 100% when added. Nobody would want a kitty to be suddenly sad because of a new feature. Once this is finished the next course of action is creating the...well action. This action will updated every tick or so, whatever we decide that to be (I was thinking once a second), and it will iterate through all of our needs, depreciating them by their decay rate. Once they cross those thresholds mentioned earlier we will have them try to satisfy those needs. Naturally we'll give you tools to do it yourself, but I think this will go a long way to making our little friends feel alive. More to come tomorrow!
-
Designing before doing? What madness is this!
Alright, I'm sick today which is fun. But I wanted to write an update regardless. Tonight I began designing the AI for the Moosecats. Now this isn't AI as it is being used currently in marketing. I'm literally trying to build up a wants, needs, and problem solving system for the Moosecats. The end goal being that if you don't give them dedicated things to do they'll act a bit like a little living critter. There are currently 8 obvious states that we will need. I'm working through the truth tables and what we need to track to keep this all sensible. The ultimate goal is that each state is fairly dedicated. We want actions to not be enormous and we want everything to make sense at a glance. The hope is that in this coming week we can make enough state actions that our Kitties will do some fun things. The next thing I'll need to design is the objects they "act" against. Each time we hit one of those hurdles this coming week and month I'll write about what needs to be done and how I'm thinking we'll solve it.
-
A Distant Feeling of Statefullness
Also, to respond to myself with one last thought. You may have noticed a couple of the cats stopped hunting me down. This was half correct. They should have stopped once they were close enough but not stopped forever. It looks like the distance calculations are off in some way.
-
A Distant Feeling of Statefullness
I'm reminded today of a Stephen King book and film called "The Langoliers" as I stare off into the distance and wonder what is approaching. It could be a great many things. A friend, a foe, something beyond mortal comprehension. I stand and wonder. Squinting a bit as the objects grow bigger. They are moving quite fast...which does leave me wondering. Have...have I fed the cats today? Oh god... inthewrongpartoftown_50Percent.webm Run while you can! Also, I suppose I should mention. Individual state machines for actors is up and running. In this example we have five Moosecats that have initialized and then switched to "wander". Since I haven't setup the logic more than that their "wander" target is always the player. That won't always be the case. Additionally we'll need to turn off collisions because otherwise they will hunt you to the ends of the play space and then kick you off into the infinite abyss sparta style. Which is amusing, but I don't think that's a healthy play pattern. This particular update to the state machines was a little challenging. The system I use is excellent for a single layer per "state machine" but in the case of actors like the cats, you have N layers. And once N > 1 we had a cross talk problem where the last cat would take over as the sole owner of the state machine. Now each instantiated actor will generate their own state units and transition, read, and adjust their own states without any worries of it hitting others. Tomorrow I'll do a bit more state work on the cats so that we can give them a few locations to travel to, and perhaps see about having them eat something. Adding in some kind of "thinking" time before they do things, a value, like hunger and other traits, that will be variable per cat.
-
State of the Machine
Tonight was VERY productive but it is also very late. So I'm going to just keep this brief. Our state machine has been updated for both the game and the Moosecats. It is considerably better than it used to be. I'm very excited. I also made it so I can just select the kind of action I wish to add, it will find it, create one, place it in the right folder with the state that will be using it, and add it to that state. No more searching through an asset creation menu, in fact I am likely to remove them from the menu altogether. This is just so nice. I'm going to likely do the same with other systems that need some "kind" of thing! bythepowerofgreyskullSmol.webm
-
The next step begins - Code Cleanup Day!
Now that we've got Adventures completed it is time for me to start up on the next operation. The first step towards the upcoming journey was to clean up my code. I went through and added precompile flags where I was missing them. I also updated some attributes that weren't doing what I needed them to do. All the while looking for places where I was missing code comments, or where I could improve an operation. These are really nice ways to relax, especially when work is hectic or exhausting. One of the last things I did for the night was I added an editor function to generate a Moosecat near the player. This way I can test our the upcoming state machine work and other systems without needing to manually type in a position or copy and paste values around. We need the cats to walk around. Why? Well, this same motion logic will be featured in our NPCs as well. We want them to be able to have schedules, to walk from one place to another. In an ideal world we'll also have them change their plans depending on their needs. But you need to walk, before you can run. With this in mind, I've convinced myself. Starting tomorrow we'll begin building the AI for the Moosecats. We'll keep it abstract enough that any major changes to the game design will still work. And on the way out for the night, I'll leave you with this. While setting up my "Nearby Moosecat Spawner" I might have goofed a line. woops.webm