> If you imagine a game that has characters, relationships, items, spells, and so on, it's often not that easy to model as encapsulated objects.
I...disagree. ECS definitely has efficiency advantages for games in terms of support performant implementations, which for games is often overwhelmingly critical, but there’s well understand OO ways to address the modelling issue tou raise.
> Does each character have a list of other characters that they have a relationship with?
It probably acts like it does, but it probably doesn’t maintain it, instead deferring to a separate object that acts as a repository of relationships, which are themselves objects, which allows you to modify relationships without touching the characters at each side (which may be more than two for multilateral relationships).
> What happens when you want to change the relationship, or a character casts a spell that temporarily changes the relationship?
You retrieve and act on the relationship object, which knows how to handle modifications.
You always have "global data" in your program - i.e. the sum of all it models. The issue is with controlling who can see and modify it. Encapsulation is a way to establish that control, and it's purpose is to minimize cognitive load on the programmer.
The problem with relationship example is that modelling this is tricky, and you have to be careful - and that's regardless of the programming paradigm used. For instance, if you're talking about "a relationship between two characters" as an objective, categorical thing (e.g. "A and B are friends", "C and D are enemies"), you're thinking about a concept that's separate from the characters themselves. So you don't want your characters to have a list of other characters, because it splits a single concept into two pieces and risks creating inconsistencies (A has a "friend" pointer to B, but B doesn't have a "friend" pointer to A). On the other hand, character A may want to query the list of characters to whom they're related, so you'll want to be able to generate that list on the fly.
Thus the OOP design would be: some object that manages all the relationships, that object being reachable from every character, and able to answer a query "what are all relationships for character $X?". An action modifying a relationship (say a spell temporarily making A and B enemies) would therefore act on that relationship manager too - which makes sense, because the action is modifying a relationship, a concept that's separate from characters themselves.
On the other hand, if you wanted to model relationships from the point of view of your characters, i.e. what they think of another character, then such relationships stop being an independent concept. You're now modelling the subjective perspective - and thus these would belong to characters, and in OOP, you'd likely model them as a list on the character object.
Whether you're doing classic OOP, plain functional programming, data-oriented programming - you still have to think about the questions described above in order to pick a correct representation for your paradigm. These questions are independent from the programming paradigm.
(And to add a further example to the mix, if you're storing character data in a relational database, these questions boil down to "is 'relationship' many:many, or 1:many?", and the answer determines the kind of bridge table you'll use.)
I...disagree. ECS definitely has efficiency advantages for games in terms of support performant implementations, which for games is often overwhelmingly critical, but there’s well understand OO ways to address the modelling issue tou raise.
> Does each character have a list of other characters that they have a relationship with?
It probably acts like it does, but it probably doesn’t maintain it, instead deferring to a separate object that acts as a repository of relationships, which are themselves objects, which allows you to modify relationships without touching the characters at each side (which may be more than two for multilateral relationships).
> What happens when you want to change the relationship, or a character casts a spell that temporarily changes the relationship?
You retrieve and act on the relationship object, which knows how to handle modifications.