Most NPCs are scripted with a lot of personality. They have character arcs and opinions and a backstory and a romance arc and all sorts of stuff to try and make them interesting.
The problem with these NPCs is that they are pretty oblivious to when they should actively express themselves, and relative to which people and things. If they are active, they tend to run roughshod over other dialog, current missions, and the player's current intentions. Even if they are just commenting in a small way (such as '-5: Lilliana doesn't like you helping magicians') it distracts from the player's intention and simply makes things muddy and awkward.
So most of the time, the NPCs are put into extremely passive roles. They are only allowed to express themselves when the player returns to base and actively seeks them out. This gives them explicit permission to activate and express themselves.
Unfortunately, it also limits how they can interact. They can't interact much with other NPCs, the world at large, or the ongoing central quest. All they can do is sit in a safe little spot and wait for the player to strike up a conversation. This is very awkward and forced at the best of times.
There have been a lot of NPCs I've wanted to spend time with, but these games don't allow you to do so. Sure, you can put them in your party, but they leave their personality back at base. Sometimes they will judge something you do, but rather than being interesting and fun, it blindsides you and leaves you feeling cheated or caged-in.
For example, almost all of the characters in all the Mass Effect games were interesting enough that I wanted to hang out with them. Mass Effect didn't let me. While I could go through their personal character arcs and learn their backstories, it was impossible to simply shoot the breeze. Mass Effect 3 was especially notable for this because many of the shipside conversations ended up being hanging out. You'd talk to Garrus and he'd take you on a drinking-and-skeet-shooting hangout. It was fun.
But it was only once.
I couldn't get Garrus to go drinking with me again. I couldn't get Solus to sing any more songs. I couldn't get Tali to geek out over random pieces of tech lying around in the various places I went. I couldn't get Liara to do psychic hang-outs. I couldn't go bar-fighting with Wrex. I could only march along the scripted course and reach the scripted destination. The only thing I had control over is which person I wanted to see half-naked for 3 seconds.
Even that was, of course, a one-off event.
The only times NPCs are active is when you are in one of their personal sidequests.
Sure, they are scripted to respond to events in their personal sidequest, but that's actually only a minor issue. It's easy to script general responses to general events in every kind of scenario. No, the reason they are active in their sidequests is because you have given them implicit permission to be active. By going on their personal mission, you have implicitly stated that you care about what they have to say, at least for the next hour or so.
There's nothing difficult about programming Tali to run up to every significant piece of tech randomly found in the game world, scan it, geek out over it, say random clips of dialog about it. That would have been very easy to program. But it also would have trampled my gameplay, and walking around would have become more like herding children than being on a mission.
The core issue is that Tali has no way to tell whether it is contextually appropriate for her to geek out over something. At any given moment, her running off to geek out could screw up my pre-combat arrangements, or talk over an important meeting, or just be incredibly socially inappropriate.
There are a lot of heuristics you could use to try and keep Tali's commentary reasonable, but the core problem isn't the exact timing or number of her outbursts. The problem is that the game devs can't read the player's mind. Even if you know exactly where all the enemies are and exactly where all the socially constrained areas are, you don't know what the player is thinking. If you were really there, you would: the player's body language and facial expression would give it away pretty quick. But you obviously can't read that through an XBox controller.
The solution is to create a way to give implicit consent.
Basically, you trigger the same kind of "consent to act" that is usually associated with loyalty sidequests.
You need to do this in a way that isn't annoying to the player, and the easiest way to do that is to use it to enhance immersion rather than detract from it. By spending time with Tali on your ship, a counter begins. For the next 30 minutes or so, Tali will be active, happily running around. Afterwards, the context fades and Tali reverts. You can prolong the context - or change it to an even more permissive context - by interacting with her out in the field. The interactions you have available to you depend on the context you've established.
If you've talked to Tali about her pilgrimage, most of your options will be related to that facet of her character - talking about whether something is suitable to send home, or can be learned from, or how it contrasts with home. If you've invited Tali out on a date, then most of your options will be related to that - and she'll spend less time geeking out over tech and more time considering whether you're having fun. And the context can be changed, if you can find the right opportunity.
You can revert faster by changing the context. You don't have to call an excitable Tali over and say "stop it! You're annoying!" Instead, you simply ask her whether she's ready for the mission. This painlessly changes the context from "Tali is important to me" to "Mission time!"
I propose we increase the number of times the player interacts with the NPC while decreasing the amount of time each interaction takes.
The intention is that the player will often "nudge" the NPC gently into a mode which suits the player's current mood and play intentions. As the situation changes, the nudges wear off or the player nudges in new ways. This constant low-level interaction allows the player to enjoy an NPC without getting sideswiped by annoyingly overactive NPCs.
A few things are required to make this work well, though.
One is that there needs to be a reward for active NPCs. For example, if Tali geeks out over a piece of tech, Tali should gain 5 XP or something. A small reward that makes you feel like they are either evolving or useful to you when let off their leash.
Another thing is that you still have tiered relationships.
When you first meet Tali or Garrus or Mordin, you can't simply go "OK let's date and get kissyface". I mean, it's a viable route, but you'll have to establish that kind of relationship by letting them be active while in less romantic contexts. But what kinds of relationships are viable with what ease will vary: Tali's romance route is tough because she will literally get sick if you even touch her. Liara, on the other hand, would probably be very easy to woo - not only does she start right off with a crush on you, but her species is not exactly puritanical.
Whatever relationship you aim for isn't a "final goal", and is instead a "fun place to be". Sometimes that's closer or further from where you start.
The last thing is "passive evolution" and "simple judging". Even when not active, the NPCs need to exist. The easiest way to do this is to have them gently react to the player's actions.
However, this is a trap you need to be careful of. In most games "react to the player's actions" translates to "judge her dialog tree choices". This is an obnoxious thing to try to do, because you can't read the player's mind and have no way of knowing why she chose that option. It's also obnoxious because the player often doesn't know it's coming, can't predict it, and can't easily fix the damage it causes. It's just not a great approach.
"Simple judging" is probably a better answer. With this, the characters feel differently about the player inch by inch as the player performs various basic gameplay feats. Most of these should be positive, very few should be negative: hanging out for a long time should make you more friendly and accepting rather than less, even if that person is kind of annoying.
So Liara might respect you more each time you use a powerful psychic attack or kill a psychic in combat. Mordin would like you more each time you used a medpack. Garrus would like you more each time you sniped or used a grenade. Etc.
In a less restricted world, these could be applied to a wider variety of interactions, but I think that's enough talking about it.
That's my basic idea! Small, frequent context shifts under the player's control give the NPCs all the information they need to know about whether they can express themselves, and how.
To be honest, I have this whole big algorithm thing involving nodes and context pipes and crap, but I really don't think discussing a specific implementation will help this essay much.
So I'm done!