Jump to content

Only one script for each entity?


Go to solution Solved by Josh,

Recommended Posts

  • Solution
Posted

For Lua, this is by design. Since Lua is dynamically typed, it's easiest to attach properties and functions directly to the entity. For parts of the code where two entities interact, this makes things very easy and straightforward:

function MyGameObject:EncounterOtherObject(entity)
  if entity.team ~= self.team then-- other entity is on a different team than me
    if isnumber(entity.health) and entity.health > 0 then-- other entity is still alive
      --Attack the enemy!
    end
  end
end

Now with C++ (and potentially other languages in the future), since it is statically typed, all properties have to be declared in a separate class anyways, so there is no downside to using multiple objects to store those. In C++ the same code above would look something like this:

void MyGameObject::EncounterOtherObject(shared_ptr<Entity> entity)
{
    for (auto component : entity->components)
    {
    	auto baseclass = dynamic_pointer_cast<BaseClass>(component);
    	if (not baseclass) continue;
      	if (baseclass->team ~= this->team)// entity is on a different team than me, probably
        {
            if (baseclass->health > 0)// entity is still alive, probably
            {
              	// Attack code!
              	break;
            }
        }
    }
}

However, if this approach were applied to Lua it would introduce two problems.

First, flipping back and forth between a script object and an entity object is tedious, and it introduces a constant burden to everything you do. Due to technical limitations at the time, Leadwerks 4 had a separate script and entity object, and it was a constant burden to try to remember which functions and properties were entity functions in the engine, and which were script functions attached to the entity script table. When you can just type self.health or entity.magic it makes life much easier, and aligns better with the design of the Lua language. The alternative is to force the user to declare a for loop every time they want to access a value on another entity or call a function. It makes the interactions between objects very tedious to code.

Second, this introduces ambiguity into the system. What is an entity's health value? You can loop through all the components until you find a class that has that value as part of it, and return the first one you encounter. What if two attached objects have two different values? The entity will be treated in unexpected ways by other entities, and if you debug just that class you won't know why, unless you filter through all the possible other entities. Game debugging is complicated, and I think adding more complication to something that is already complicated should be avoided.

We allow multiple attached objects with C++ because the static typing of C++ prevents us from doing things the Lua way anyways, but in my own game I am developing, we have a strict rule of one object per entity, so that we can simplify our code like so:

void MyGameObject::EncounterOtherObject(shared_ptr<Entity> entity)
{
    auto baseclass = dynamic_pointer_cast<BaseClass>(entity->actor);// value is equal to component[0] if it exists, or NULL if it does not
    if (not baseclass) return;
    if (baseclass->team ~= this->team)// entity is definitely on a different team than me
    {
        if (baseclass->health > 0)// entity is definitely still alive
        {
            // Attack code!
        }
    }
}

That way I don't have to guess which attached object is triggering some behavior, I just look at the actor, and I know all my properties and functions are stored there. To make everything accessible without casting to different classes, I just declare all members and functions in a single base class that get accessed across different entities in the base class, and all my game classes are derived from that. C++ programmers can still do things the way the second example here shows, but for my own games I prefer the last example.

  • Thanks 1

Let's build cool stuff and have fun. :)

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...