Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Curating data-driven world state

Discussion in 'Scripting' started by Sendatsu_Yoshimitsu, Aug 23, 2017.

  1. Sendatsu_Yoshimitsu

    Sendatsu_Yoshimitsu

    Joined:
    May 19, 2014
    Posts:
    691
    I'm working on a traditional RPG, and trying to work out the most felicitous workflow to position "filler" NPCs who don't tie into the quest system, but just wander around the world and provide interesting dialogue when spoken to. About 20-30 NPC positions and dialogue need to change in response to world state, usually the day changing, which means I need some kind of centralized data file that tracks where and when NPCs should move around the world.

    Right now, I'm managing it by creating one CSV for every single day of the year over which the game takes place. The spreadsheet only contains a key for each NPC, their new spawn point, and their new dialogue. Whenever time advances the game pulls the CSV matching the new day and iterates through the NPCs, changing all of the requested characters' behavior.

    This works, but it's super-duper laborious to write and manage; I'm managing hundreds of spreadsheets, and each individual spreadsheet can have several dozen characters with new behaviors. I can't really see a way to improve my workflow beyond creating a custom editor, which is far too large an undertaking for the results; is there any obvious improvement to this setup I'm neglecting, or is something with this large of a scope inevitably going to be extremely laborious and error-prone to curate in data?
     
  2. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,670
    I think you're taking a wise approach by defining the behavior in data and not in code or in values on components.

    What if you define some of that data more procedurally? For example, a NPC might have this info:
    • Locations: a set of transforms such as Home, Work, etc.
    • Regular schedule: a set of <time, location> such as <0600,Home>, <0700,Work>, <1600,Pub>, etc.
    • Special schedules: a set of <conditions,location> such as <(Christmas),Party>
    • Dialogues: a set of <conditions, which dialogue to play>
    As time ticks along, the NPC can follow its regular schedule, which takes it to various locations. You could set up triggers in each location. For example, when the blacksmith NPC steps in front of the Anvil trigger at 0700, it can switch her to her blacksmithing behavior (which as a simple first pass implementation could just start playing a hammering animation).

    If you put the schedule into a priority queue, you can insert special events as they happen, too, and they would take priority over the regular schedule.
     
  3. Sendatsu_Yoshimitsu

    Sendatsu_Yoshimitsu

    Joined:
    May 19, 2014
    Posts:
    691
    That's a really good suggestion, and it's already something I've kinda-sorta implemented for more important NPCs; basically the way my game is set up, there are two categories of NPCs: Key characters, who are story/quest-important NPCs who you get to know throughout the course of the game, and Filler characters, who are basically particularly animated furniture. Key characters follow consistent schedules that have a bit of variation for spice, and are managed entirely through scripting commands contained in my quests and cutscenes, which move them around in response to story triggered by player progress.

    What I was suggesting with the gigantic spreadsheets is to handle Filler characters, which are simultaneously way less complex, and seemingly a lot more annoying to curate. Most filler characters have bog-simple dialogue along the lines of "Oh geez, I couldn't sleep at all last night; a motorcycle kept racing up and down my street," and their purpose is to add life to the world; all of the filler NPCs get dialogue that either illuminates something about the current story, sets up an incoming plot beat, or just makes the world feel more lived-in. Militating this behavior is as simple as setting their location and dialogue keys, but the sheer volume of people with short dialogue makes doing anything manually a losing proposition.

    It doesn't give nearly as much fine-tuned control, but I suppose one thing I could do is compromise between your idea and my current setup by setting each filler NPC's dialogue from data, but making their placement pseudo-procedural by defining a list of possible locations they can appear, then choosing one randomly when the level loads in. I'd have to get fancy to handle some of the edge cases that are easy to do in data, like positioning multiple characters whose dialogue indicates they're talking to each other in adjacent locations, but that's a lot less overall work than curating the huge lists of CSVs like I was discussing.
     
  4. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,670
    Sounds good. How much work would it really be to add time ranges to the possible locations that your filler NPCs can appear? Seems like this way you could guarantee that at 4:00 PM on Thursday the blacksmith would be either at her forge or slacking off in the pub, and not at the church which is only open on Sunday mornings.
     
  5. Sendatsu_Yoshimitsu

    Sendatsu_Yoshimitsu

    Joined:
    May 19, 2014
    Posts:
    691
    It would actually be super-easy, since time works more like a turn-based game than something like Skyrim: the day is divided into discrete time periods, and certain player actions advance the time period by one. Key character schedules are currently organized by <day of the week,time>, with an override list to consult if certain recurring conditions are met, like foul weather making everyone who should be outside take cover indoors.

    For the filler characters, I was thinking of making it simple to the point of being almost dumb- everybody gets a list of <day, time> and a level ID, and when a level streams in it retrieves a list of everyone who return its ID for the current day and time.


    What I'm thinking through now is a bit of an elaboration on that- there are lots of conceivable cases where I'd like to place multiple characters in proximity, to visually indicate that they're socializing in a way that backs up dialogue which would likely contain multiple people speaking to each other or reacting. Placement is easy, I can just make certain Group spawn points that are actually 3-5 individual transforms that've been hand-placed in positions that suggest their occupants are talking/socializing. Actually indicating that multiple people should spawn together seems a bit harder- right now I'm thinking the same spreadsheet that keeps track of when someone's dialogue changes should also contain an optional field for a group key, so if somebody spawns in with a non-null key like, say, "MotorcycleConversationGroup," the system puts them aside until all the individuals have been spawned, then does a second pass across the spawn points looking for an unused group position with enough slots to seat everyone with an identical tag. It's slightly fiddly to actually maintain, but it's simple enough that I can't see anything going wrong on the code side.
     
  6. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,670
    Good plan. It's a little more work to code, bu it should be much less work to manage the data.