I'm writing a game for a video game course (which unfortunately taught nothing), and I'm having trouble designing the interactions between the game entities and the class that actually runs the game.
My problem reduces pretty much to this: assuming an entity has a position, it shouldn't be able to modify it directly (instead having to wait for the game manager to run a game step), but it should be able to access it, to run AI checks and so on.
My solution would be to create a Position class that is friend with GameManager, and to create an entity class like this
class Entity {
public:
Position & getPosition() { return pos_; }
private:
Position pos_;
};
So the manager would be able to modify the entities' positions but other classes would only be able to observe. However this reasoning would hold for lots and lots of other properties, and since the entity class is actually derived into a series of subclasses, which have more and more properties, I would have to put the friend attribute almost everywhere.
What would be a better approach to solve this problem?
The idea of identifying certain classes as friend and certain others as non-friend is not a good idea, for many reasons. What this means is that,
How this class is being used is also a concern of this class.
But this is not its concern at all. This class, whatever class is under consideration, should be designed to do its own responsibility.
Now, with your case, first of all you should decide on where the action/behaviour of changing position belongs to; does it belong to Entity, Entity Manager, or something else. For example, which of these two cases make more sense:
Entity changes its position from x1 to x2.
Entity Manager changes to position of Entity from x1 to x2.
Suppose you decided that this behaviour really belongs to Entity, rather than Entity manager (case 1). In that case, as is pointed out in the comments by #bengoesboom, it should provide a setter that users of the class can use to change its position.
Now, if you think that this class might be used in ways that is not desired, then you should enforce constraints and business rules within this class. For example (just a simple example), if you want to allow only certain range of values in an operation. You check the input, if it is not in the range, then you throw an exception.
Once, you have properly taken care of rules and constraints, then you don't care about who will use this class.
Related
I'm a computational physicist trying to learn how to code properly. I've written several program by now, but the following canonical example keeps coming back, and I'm unsure as to how to handle it. Let's say that I have a composition of two objects such as
class node
{
int position;
};
class lattice
{
vector <node*> nodes;
double distance (node*,node*);
};
Now, this will not work, because position is a private member of node. I know of two ways to solve this: either you create an accessor such as getpos(){return position}, or make lattice a friend of node.
The second of these solutions seems a lot easier to me. However, I am under the impression that it is considered slightly bad practice, and that one generally ought to stick to accessors and avoid friend. My question is this: When should I use accessors, and when should I use friendship for compositions such as these?
Also, a bonus question that has been bugging me for some time: Why are compositions preferred to subclasses in the first place? To my understanding the HAS-A mnemonic argues this, but, it seems more intuitive to me to imagine a lattice as an object that has an object called node. That would then be an object inside of an object, e.i. a subclass?
Friend is better suited if you give access rights to only specific classes, rather than to all. If you define getpos(){return position}, position information will be publicly accessible via that getter method. If you use friend keyword, on the other hand, only the lattice class will be able to access position info. Therefore, it is purely dependent on your design decisions, whether you wanna make the information publicly accessible or not.
You made a "quasi class", this a textbook example of how not to do OOP because changing position doesn't change anything else in node. Even if changing position would change something in node, I would rethink the structure to avoid complexity and improve the compiler's ability to optimize your code.
I’ve witnessed C++ and Java programmers routinely churning out such
classes according to a sort of mental template. When I ask them to
explain their design, they often insist that this is some sort of
“canonical form” that all elementary and composite item (i.e.
non-container) classes are supposed to take, but they’re at a loss to
explain what it accomplishes. They sometimes claim that we need the
get and set functions because the member data are private, and, of
course, the member data have to be private so that they can be changed
without affecting other programs!
Should read:
struct node
{
int position;
};
Not all classes have to have private data members at all. If your intention is to create a new data type, then it may be perfectly reasonable for position to just be a public member. For instance, if you were creating a type of "3D Vectors", that is essentially nothing but a 3-tuple of numeric data types. It doesn't benefit from hiding its data members since its constructor and accessor methods have no fewer degrees of freedom than its internal state does, and there is no internal state that can be considered invalid.
template<class T>
struct Vector3 {
T x;
T y;
T z;
};
Writing that would be perfectly acceptable - plus overloads for various operators and other functions for normalizing, taking the magnitude, and so on.
If a node has no illegal position value, but no two nodes in a lattice cannot have the same position or some other constraint, then it might make sense for node to have public member position, while lattice has private member nodes.
Generally, when you are constructing "algebraic data types" like the Vector3<T> example, you use struct (or class with public) when you are creating product types, i.e. logical ANDs between other existent types, and you use std::variant when you are creating sum types, i.e. logical ORs between existent types. (And for completeness' sake, function types then take the place of logical implications.)
Compositions are preferred over inheritance when, like you say, the relationship is a "has-a" relationship. Inheritance is best used when you are trying to extend or link with some legacy code, I believe. It was previously also used as a poor approximation of sum types, before std::variant existed, because the union keyword really doesn't work very well. However, you are almost always better off using composition.
Concerning your example code, I am not sure that this poses a composition. In a composition, the child object does not exist as an independent entity. As a rule of thumb, it's life time is coupled with the container. Since you are using a vector<node*> nodes, I assume that the nodes are created somewhere else and lattice only has a pointer to these objects. An example for a composition would be
class lattice {
node n1; // a single object
std::vector<node> manyNodes;
};
Now, addressing the questions:
"When should I use accessors, and when should I use friendship for compositions such as these?"
If you use plenty of accessors in your code, your are creating structs and not classes in an OO sense. In general, I would argue that besides certain prominent exceptions such as container classes one rarely needs setters at all. The same can be argued for simple getters for plain members, except when the returning the property is a real part of the class interface, e.g. the number of elements in a container. Your interface should provide meaningful services that manipulate the internal data of your object. If you frequently get some internal data with a getter, then compute something and set it with an accessor you should put this computation in a method.
One of the main reasons why to avoid ´friend´ is because it introduces a very strong coupling between two components. The guideline here is "low coupling, high cohesion". Strong coupling is considered a problem because it makes code hard to change, and most time on software projects is spent in maintenance or evoluation. Friend is especially problematic because it allows unrelated code to be based on internal properties of your class, which can break encapsulation. There are valid use-cases for ´friend´ when the classes form a strongly related cluster (aka high cohesion).
"Why are compositions preferred to subclasses in the first place?"
In general, you should prefer plain composition over inheritance and friend classes since it reduces coupling. In a composition, the container class can only access the public interface of the contained class and has no knowledge about the internal data.
From a pure OOP point of view, your design has some weaknesses and is probably not very OO. One of the basic principles of OOP is encapsulation which means to couple related data and behavior into objects. The node class e.g. does not have any meaning other than storing a position, so it does not have any behavior. It seems that you modeled the data of your code but not the behavior. This can be a very appropriate design and lead to good code, but it not really object-oriented.
"To my understanding the HAS-A mnemonic argues this, but, it seems more intuitive to me to imagine a lattice as an object that has an object called node. That would then be an object inside of an object, e.i. a subclass?"
I think you got this wrong. Public inheritance models an is-a-relationship.
class A: public B {};
It basically says that objects of class A are a special kind of B, fulfilling all the assumptions that you can make about objects of type B. This is known as the Liskov substitution principle. It basically says that everywhere in your code where you use a B you should be able to also use an A. Considering this, class lattice: public node would mean that every lattice is a node. On the other hand,
class lattice {
int x;
node n;
int y;
};
means that an object of type lattice contains another object of type node, in C++ physically placed together with x and y. This is a has-a-relationship.
(Refer Update #1 for a concise version of the question.)
We have an (abstract) class named Games that has subclasses, say BasketBall and Hockey (and probably many more to come later).
Another class GameSchedule, must contain a collection GamesCollection of various Games objects. The issue is that we would, at times, like to iterate only through the BasketBall objects of GamesCollection and call functions that are specific to it (and not mentioned in the Games class).
That is, GameSchedule deals with a number of objects that broadly belong to Games class, in the sense that they do have common functions that are being accessed; at the same time, there is more granularity at which they are to be handled.
We would like to come up with a design that avoids unsafe downcasting, and is extensible in the sense that creating many subclasses under Games or any of its existing subclasses must not necessitate the addition of too much code to handle this requirement.
Examples:
A clumsy solution that I came up with, that doesn't do any downcasting at all, is to have dummy functions in the Game class for every subclass specific function that has to be called from GameSchedule. These dummy functions will have an overriding implementation in the appropriate subclasses which actually require its implementation.
We could explicitly maintain different containers for various subclasses of Games instead of a single container. But this would require a lot of extra code in GameSchedule, when the number of subclasses grow. Especially if we need to iterate through all the Games objects.
Is there a neat way of doing this?
Note: the code is written in C++
Update# 1: I realized that the question can be put in a much simpler way. Is it possible to have a container class for any object belonging to a hierarchy of classes? Moreover, this container class must have the ability to pick elements belonging to (or derive from) a particular class from the hierarchy and return an appropriate list.
In the context of the above problem, the container class must have functions like GetCricketGames, GetTestCricketGames, GetBaseballGame etc.,
This is exactly one of the problems that The "Tell, Don't Ask" principle was created for.
You're describing an object that holds onto references to other objects, and wants to ask them what type of object they are before telling them what they need to do. From the article linked above:
The problem is that, as the caller, you should not be making decisions based on the state of the called object that result in you then changing the state of the object. The logic you are implementing is probably the called object’s responsibility, not yours. For you to make decisions outside the object violates its encapsulation.
If you break the rules of encapsulation, you not only introduce the runtime risks incurred by rampant downcasts, but also make your system significantly less maintainable by making it easier for components to become tightly coupled.
Now that that's out there, let's look at how the "Tell, Don't Ask" could be applied to your design problem.
Let's go through your stated constraints (in no particular order):
GameSchedule needs to iterate over all games, performing general operations
GameSchedule needs to iterate over a subset of all games (e.g., Basketball), to perform type-specific operations
No downcasts
Must easily accommodate new Game subclasses
The first step to following the "Tell, Don't Ask" principle is identifying the actions that will take place in the system. This lets us take a step back and evaluate what the system should be doing, without getting bogged down into the details of how it should be doing it.
You made the following comment in #MarkB's answer:
If there's a TestCricket class inheriting from Cricket, and it has many specific attributes concerning the timings of the various innings of the match, and we would like to initialize the values of all TestCricket objects' timing attributes to some preset value, I need a loop that picks all TestCricket objects and calls some function like setInningTimings(int inning_index, Time_Object t)
In this case, the action is: "Initialize the inning timings of all TestCricket games to a preset value."
This is problematic, because the code that wants to perform this initialization is unable to differentiate between TestCricket games, and other games (e.g., Basketball). But maybe it doesn't need to...
Most games have some element of time: Basketball games have time-limited periods, while Baseball games have (basically) innings with basically unlimited time. Each type of game could have its own completely unique configuration. This is not something we want to offload onto a single class.
Instead of asking each game what type of Game it is, and then telling it how to initialize, consider how things would work if the GameSchedule simply told each Game object to initialize. This delegates the responsibility of the initialization to the subclass of Game - the class with literally the most knowledge of what type of game it is.
This can feel really weird at first, because the GameSchedule object is relinquishing control to another object. This is an example of the Hollywood Principle. It's a completely different way of solving problems than the approach most developers initially learn.
This approach deals with the constraints in the following ways:
GameSchedule can iterate over a list of Games without any problem
GameSchedule no longer needs to know the subtypes of its Games
No downcasting is necessary, because the subclasses themselves are handling the subclass-specific logic
When a new subclass is added, no logic needs to be changed anywhere - the subclass itself implements the necessary details (e.g., an InitializeTiming() method).
Edit: Here's an example, as a proof-of-concept.
struct Game
{
std::string m_name;
Game(std::string name)
: m_name(name)
{
}
virtual void Start() = 0;
virtual void InitializeTiming() = 0;
};
// A class to demonstrate a collaborating object
struct PeriodLengthProvider
{
int GetPeriodLength();
}
struct Basketball : Game
{
int m_period_length;
PeriodLengthProvider* m_period_length_provider;
Basketball(PeriodLengthProvider* period_length_provider)
: Game("Basketball")
, m_period_length_provider(period_length_provider)
{
}
void Start() override;
void InitializeTiming() override
{
m_period_length = m_time_provider->GetPeriodLength();
}
};
struct Baseball : Game
{
int m_number_of_innings;
Baseball() : Game("Baseball") { }
void Start() override;
void InitializeTiming() override
{
m_number_of_innings = 9;
}
}
struct GameSchedule
{
std::vector<Game*> m_games;
GameSchedule(std::vector<Game*> games)
: m_games(games)
{
}
void StartGames()
{
for(auto& game : m_games)
{
game->InitializeTiming();
game->Start();
}
}
};
You've already identified the first two options that came to my mind: Make the base class have the methods in question, or maintain separate containers for each game type.
The fact that you don't feel these are appropriate leads me to believe that the "abstract" interface you provide in the Game base class may be far too concrete. I suspect that what you need to do is step back and look at the base interface.
You haven't given any concrete example to help, so I'm going to make one up. Let's say your basketball class has a NextQuarter method and hockey has NextPeriod. Instead, add to the base class a NextGameSegment method, or something that abstracts away the game-specific details. All the game-specific implementation details should be hidden in the child class with only a game-general interface needed by the schedule class.
C# supports reflections and by using the "is" keyword or GetType() member function you could do these easily. If you are writing your code in unmanaged C++, I think the best way to do this is add a GetType() method in your base class (Games?). Which in its turn would return an enum, containing all the classes that derive from it (so you would have to create an enum too) for that. That way you can safely determine the type you are dealing with only through the base type. Below is an example:
enum class GameTypes { Game, Basketball, Football, Hockey };
class Game
{
public:
virtual GameTypes GetType() { return GameTypes::Game; }
}
class BasketBall : public Game
{
public:
GameTypes GetType() { return GameTypes::Basketball; }
}
and you do this for the remaining games (e.g. Football, Hockey). Then you keep a container of Game objects only. As you get the Game object, you call its GetType() method and effectively determine its type.
You're trying to have it all, and you can't do that. :) Either you need to do a downcast, or you'll need to utilize something like the visitor pattern that would then require you to do work every time you create a new implementation of Game. Or you can fundamentally redesign things to eliminate the need to pick the individual Basketballs out of a collection of Games.
And FWIW: downcasting may be ugly, but it's not unsafe as long as you use pointers and check for null:
for(Game* game : allGames)
{
Basketball* bball = dynamic_cast<Basketball*>(game);
if(bball != nullptr)
bball->SetupCourt();
}
I'd use the strategy pattern here.
Each game type has its own scheduling strategy which derives from the common strategy used by your game schedule class and decouples the dependency between the specific game and game schedule.
So I'm working on a 2D space simulator and I have the resource manager 'calc' that handles all calculations for everything. For example, from calc.hpp:
var calc::eccentricity (object A, object B);
var calc::distance (object A, object B);
var calc::orbitV (object A, object B);
etc. However, the way I have my program structured is in my calc class I have
private:
object *ship //the currently controlled ship
object *targ //target
object *ref //reference (from which speeds, position, etc. are calculated)
and to use the calculations given in the first example with these, I write three functions for each calculation function, like so:
var calc::ship_ecc (object A){
if(!ship) //catches null pointers
return NAN;
return eccentricity(*ship, A);
}
var calc::ship_ref_ecc (){
if(!ref) //catches null pointers
return NAN;
return ship_ecc(*ref);
}
var calc::ship_targ_ecc (){
if(!targ) //catches null pointers
return NAN;
return ship_ecc(*targ);
}
for eccentricity, and then the same for distance and orbitV. So I end up having four functions for every calculation. As you can see from calc.hpp this makes for plenty of duplicated code. And duplicated code is a Bad Thing.
What my question is
Is there some way to call
calc.ship.targ.eccentricity();
calc.ship.ref.eccentricity(); //or variation thereof
or
calc.ship.targ(eccentricity);
calc.ship.ref(eccentricity); //or variation thereof
instead of
calc.ship_targ_ecc();
calc.ship_ref_ecc();
? I'm wondering if you could do some fancy operator() overloading, or pass a function, or make a friend class in calc. Ideally I should only be able to access lines 31 - 53, which are all public.
Thanks!
EDIT: got an example for yall: https://ideone.com/jypJQS this is what it should output and how it is working now
Maybe this changes too much your current code. But I think that the functions in calc should be members of object. So you could things like :
ship.eccentricity(target);
What confuses me (and what is probably the big problem here) is that you seem to define some hard relations in your calc object (the private members). What are those for ? From the code, I guess there is a calc object for every "ship". If yes, it would be an other reason to add the code to object instead of maintaining 1-1 relations between object and calc.
This might require a little bit of refactoring, but I think it's worth it. For a simple game, you can use OOP and Polymorphism to fix the issue.
First of all, create an object class.
class Object {
public:
Object();
~Object();
};
This object class would be a basis for all your objects in the game (ship, character, etc...). You, then, would create a sub class for your ship.
class Ship : public Object {
};
This would allow an easy expansion to future objects that require the same principle.
In the object class, you would have some basic properties:
physical (optional)
dimensions
speed (last calculated speed)
controlled (bool - current controlling ship or not)
This would eliminate the need to have hard relationships with the calc and ship class.
Next, you would change your calc class to become general. You don't want to depend on a single ship object, this is cumbersome.
Option 1
You could create an instance of the calc class for each object. This calc instance would have access to the already available properties of the object and ship class.
Option 2
Create a general calc class that would require you to pass a reference to the ship/object instance. calc->eccentricity(&ship, target);
Option 3
Within a possible manager class, or a simple "global" variable. You could hold a reference to the currently controlled ship (if that's how your system works, I'm not sure). Or you could store the index of the ship and all instances are held inside a vector<&Ship>.
In a simplistic game, straight forward OOP will suffice, but if you want more decoupling, component based game design would be a better bet (in combination with OOP, of course).
So I took this over to /r/learnprogramming, and I got a good answer from zzyzzyxx (as always). His answer:
What's wrong with simply having functions that take the required two or three parameters? They don't have to be in any special calc class. Maybe a calc namespace. I'm not sure it makes sense with the rest of your design, but what about making it a member function so that anything can calculate what it needs given a target and potentially a reference point if there's no sensible default?
So basically, don't worry about all this calc.eccentricity(A, B), calc.ship_ecc(A), calc.ship_ref_ecc() business, just say
calc.eccentricity(*calc.targ(), B)
Also, don't make calc a singleton, make it a namespace.
I'll go do that now.
In my game engine, that is written in C++, I've moved away from the classical hierarchical entity system and build up a component-based one. It works roughly in this way:
An entity is merely a container for components. Some example components are: Point, Sprite, Physics, Emitter.
Each entity can hold at most one component of each type. Some component depend on another, like Physics and Sprite depend on Point, because they need a position and angle delivered by it.
So everything works fine with the component system, but now I have trouble implementing more specialized entities, like:
A camera, which needs additional functions to handle movement and zoom
A player, which needs support to receive input from the user and move
Now, I could easily solve this with inheritance. Just derive the camera from the entity and add the additional zoom functions and members. But this simply feels wrong.
My question:
How can I solve the problem of specialized entities with a component system in C++?
You seem to be doubting the IS-A relationship here. So why not make it a HAS-A relationship? Instead of being an entity, the camera and the player could be objects that have an entity (or a reference to the entity), but exist outside of your component-system. That way, you can easily keep the uniformity and orthogonality of your component system.
This also fits nicely with the meaning of those two examples (camera/player) as 'glue' objects. The player glues the entity system to the input system and acts as a controller. The camera glues the entity system to the renderer and acts as a kind of observer.
What about just creating components that enable that behavior? For example, an InputComponent could handle input from the player. Then your design remains the same, and a player is just an entity which allows input from a keyboard, rather than input from an AI controller.
Components based system usually have a general method allowing to send "messages" to entities, like a function send(string message_type, void* data). The entity then pass it to all its components and only some of them will react to it. For example, your component Point could react to send("move", &direction). Or you could introduce a moveable component to have more control. Same thing for your camera, add a component view and make it handle "zoom" message.
This modular design already allow to define different types of cameras (like a fixed one not having the moveable component), reuse some component for other stuff (another type of entity may use a "view") and you can also gain flexibility by having various components handling each message differently.
Of course, some optimization tricks could be needed, especially for frequently used messages.
How about giving each entity some restrictions to what kind of components it may hold (and maybe also what it should hold), and loosening those restrictictions when you derive from that entity. For example by adding a virtual function that verifies whether a certain component can be added to the entity.
A common solution is to use the visitor pattern. Basically, you'll have your entity being "visited" by a Visitor class. Inside your entity, you'd have :
void onVisitTime(Visitor* v)
{
// for each myComponent...
v->visit(myComponent);
// end for each
}
And then, you'd have, in the Visitor class :
void visit(PointComponent* p);
void visit(CameraComponent* c);
Be aware that it's a bit of violation of OOP (data-manipulation being handled outside the object, since the visitor will handle it). And visitors tend to become over-complicated, so it's a not-so-great solution.
I've got a game engine where I'm splitting off the physics simulation from the game object functionality. So I've got a pure virtual class for a physical body
class Body
from which I'll be deriving various implementations of a physics simulation. My game object class then looks like
class GameObject {
public:
// ...
private:
Body *m_pBody;
};
and I can plug in whatever implementation I need for that particular game. But I may need access to all of the Body functions when I've only got a GameObject. So I've found myself writing tons of things like
Vector GameObject::GetPosition() const { return m_pBody->GetPosition(); }
I'm tempted to scratch all of them and just do stuff like
pObject->GetBody()->GetPosition();
but this seems wrong (i.e. violates the Law of Demeter). Plus, it simply pushes the verbosity from the implementation to the usage. So I'm looking for a different way of doing this.
The idea of the law of Demeter is that your GameObject isn't supposed to have functions like GetPosition(). Instead it's supposed to have MoveForward(int) or TurnLeft() functions that may call GetPosition() (along with other functions) internally. Essentially they translate one interface into another.
If your logic requires a GetPosition() function, then it makes sense turn that into an interface a la Ates Goral. Otherwise you'll need to rethink why you're grabbing so deeply into an object to call methods on its subobjects.
One approach you could take is to split the Body interface into multiple interfaces, each with a different purpose and give GameObject ownership of only the interfaces that it would have to expose.
class Positionable;
class Movable;
class Collidable;
//etc.
The concrete Body implementations would probably implement all interfaces but a GameObject that only needs to expose its position would only reference (through dependency injection) a Positionable interface:
class BodyA : public Positionable, Movable, Collidable {
// ...
};
class GameObjectA {
private:
Positionable *m_p;
public:
GameObjectA(Positionable *p) { m_p = p; }
Positionable *getPosition() { return m_p; }
};
BodyA bodyA;
GameObjectA objA(&bodyA);
objA->getPosition()->getX();
Game hierarchies should not involve a lot of inheritance. I can't point you to any web pages, but that is the feeling I've gather from the several sources, most notably the game gem series.
You can have hierarchies like ship->tie_fighter, ship->x_wing. But not PlaysSound->tie_fighter. Your tie_fighter class should be composed of the objects it needs to represent itself. A physics part, a graphics part, etc. You should provide a minimal interface for interacting with your game objects. Implement as much physics logic in the engine or in the physic piece.
With this approach your game objects become collections of more basic game components.
All that said, you will want to be able to set a game objects physical state during game events. So you'll end up with problem you described for setting the various pieces of state. It's just icky but that is best solution I've found so far.
I've recently tried to make higher level state functions, using ideas from Box2D. Have a function SetXForm for setting positions etc. Another for SetDXForm for velocities and angular velocity. These functions take proxy objects as parameters that represent the various parts of the physical state. Using methods like these you could reduce the number of methods you'd need to set state but in the end you'd probably still end up implementing the finer grained ones, and the proxy objects would be more work than you would save by skipping out on a few methods.
So, I didn't help that much. This was more a rebuttal of the previous answer.
In summary, I would recommend you stick with the many method approach. There may not always be a simple one to 1 relationship between game objects and physic objects. We ran into that where it was much simpler to have one game object represent all of the particles from an explosion. If we had given in and just exposed a body pointer, we would not have been able to simplify the problem.
Do I understand correctly that you're separating the physics of something from it's game representation?
i.e, would you see something like this:
class CompanionCube
{
private:
Body* m_pPhysicsBody;
};
?
If so, that smells wrong to me. Technically your 'GameObject' is a physics object, so it should derive from Body.
It sounds like you're planning on swapping physics models around and that's why you're attempting to do it via aggregation, and if that's the case, I'd ask: "Do you plan on swapping physics types at runtime, or compile time?".
If compile time is your answer, I'd derive your game objects from Body, and make Body a typedef to whichever physics body you want to have be the default.
If it's runtime, you'd have to write a 'Body' class that does that switching internally, which might not be a bad idea if your goal is to play around with different physics.
Alternatively, you'll probably find you'll have different 'parent' classes for Body depending on the type of game object (water, rigid body, etc), so you could just make that explicit in your derivation.
Anyhow, I'll stop rambling since this answer is based on a lot of guesswork. ;) Let me know if I'm off base, and I'll delete my answer.