Jump to content
  • Advertisement
Sign in to follow this  
Stefan Fischlschweiger

Moving child objects with parent

This topic is 928 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm now trying to move away from the Almirante engine ECS I've been using so far and implement my own.

 

I've now got a GameObject class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MetastormDX.Engine.Objects
{
    internal class GameObject
    {
        internal uint Id;
        internal string Tag;

        internal Dictionary<Type, Component> Components; 

        internal GameObject()
        {
            Components = new Dictionary<Type, Component>();

            Create();
        }

        internal GameObject(IEnumerable<Component> components)
        {
            foreach (var component in components)
            {
                AddComponent(component);
            }

            Create();
        }

        internal void AddComponent(Component component)
        {
            component.Create();
            Components.Add(component.GetType(), component);
        }

        internal void RemoveComponent(Type componentType)
        {
            Components.Remove(componentType);
        }

        internal T GetComponent<T>() where T : Component
        {
            Component component;
            Components.TryGetValue(typeof(T), out component);

            return component as T;
        }

        private void Create()
        {
            
        }

        private void Kill()
        {
            foreach (var component in Components)
            {
                component.Value.Destroy();
            }

            Components = null;
        }
    }
}

Everything shall be an instance of this class, instead of having many derived classes for all kinds of objects (like ships, stations, planets, guns, lights, etc..) with the object being defined by the Components attached to it. 

For example, a planet would have at least a TransformComponent and a RenderComponent, but no VelocityComponent as it doesn't move.

 

The TransformComponent class currently looks like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SharpDX;

namespace MetastormDX.Engine.Objects.Components
{
    internal class TransformComponent : Component
    {
        internal bool HasParent;
        internal TransformComponent ParentTransformComponent;

        internal Vector3 WorldPosition;
        internal Vector3 LocalPosition;

        internal Quaternion WorldOrientation;
        internal Quaternion LocalOrientation;

        internal TransformComponent()
        {
            HasParent = false;
            WorldPosition = Vector3.Zero;
            WorldOrientation = Quaternion.Zero;
        }

        internal override void Create()
        {
            if (!HasParent)
            {
                LocalPosition = Vector3.Zero;
                LocalOrientation = Quaternion.Zero;
                ParentTransformComponent = null;
            }
        }
    }
}

Now as you can see objects can be in a parent-child relation, like guns attached to ship or station.

 

I've started writing a MovementSystem class which is (obviously) resposible for moving all the objects around that can move:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MetastormDX.Engine.Core;
using MetastormDX.Engine.Objects.Components;

namespace MetastormDX.Engine.Objects.Systems
{
    internal class MovementSystem : GameSystem
    {
        internal List<GameObject> RegisteredGameObjects;

        internal override void Initialize()
        {
            
        }

        internal override void Execute(GameTime gameTime)
        {
            Parallel.ForEach(RegisteredGameObjects, (currentObject) =>
            {
                var transform = currentObject.GetComponent<TransformComponent>();
                var velocity = currentObject.GetComponent<VelocityComponent>();
            });
        }
    }
}

Now, my question here is: How would I go about making child objects move with their parents and, more importantly, how I can make sure that they are moved in the correct order. That is, first the objects which are only parents, then their childs and so on down the heirarchy, in case there are 3 or more layers in a parent-child chain?

Share this post


Link to post
Share on other sites
Advertisement

When would this matter? That is when would you actually need them to move with their parents? You'd need it during rendering I guess, will you need it during physics too? I would approach this by making is such that each object would have it's own transform relative to a parent and an absolute transform relative to the world. In the case of a parentless object then the transforms are the same.

 

A gun on a ship would have a relative transform compared to the ship(parent), maybe translated (2, 3, 4). The ship might be at (1, 1, 1). Thus the world transform for the ship would still be (1, 1, 1) but the gun would now be (3, 4, 5). Since you are keeping both you can now work out the actual world transform from the local transform and the parent transform. The local transform will effectively be a transformation that goes local space->parent space. All you need to do to create those world transforms is to multiply the local transform by the parent's local transform by that parent's local transform and so on all the way up the hierarchy until you run out of parents.

 

You'd move things relative to their parents (or the world if they don't have a parent) then for each object you'd go though and multiply all the local transforms by their parent's transforms to create a 'to world' transform for each individual part. For deeper hierarchies you could optimize that a bit by making use of matrix multiplication being associative, you also only need to work it out if you are actually going to use the values and if the original values change only. Also if your deep hierarchies never change relative to their parent you can make further optimizations there too.

 

As far as moving things that are moving relative to their parent (such as a moon around a moving planet) then you just decide what the movement is relative to. If a moon is moving then you would be updating it's local transformation but if the moon isn't moving but the planet is (thus moving the moon too) then you don't need to change anything as this will be taken care of during the part where you update to 'to world' transforms.

Edited by Nanoha

Share this post


Link to post
Share on other sites

My solution to this is as follows:

 

All game objects that are placed in the world have a Placement component (essentially a position and an orientation; can be requested for the world transform of the object). All game objects exists in a flat list. If an object has to be geometrically related to another one, it need to have a suitable component attached to it. The component for forward kinematics is the Parenting component (it is one of round about a dozen mechanisms, like Grabbing and Aiming and so on). With the parenting being explicit and just one of a couple of possibilities, the belonging sub-system (called SpatialServices here) manages them by building an internal dependency graph. Hence this graph defines the order of execution.

 

The algorithm of Parenting is as usual: It has a reference to the parental Placement component and a local placement variable. The also references Placement component of the own game object is computed as product of the parental placement and the local one.

 

An animation (the MovementSystem in the OP is in fact a mechanism that applies an animation to a placement) alters independent variables only. It may alter the placement variable of the parental game object directly, it may alter the local placement of the child object directly, but it may not alter the placement component variable of the child object. This is because the mechanisms like Parenting are run after the animations are applied. Hence they would overwrite what an animation would have applied. However, this is okay w.r.t. the way things are handled, isn't it? Because there would be 2 competing controllers for the same variable.

Share this post


Link to post
Share on other sites

A quick and dirty solution that's relatively painless is to hold a depth counter for all nodes. A parent will have a depth of zero, a child will have a depth of N many levels.

So... when you create an object. We create a parent with a depth of zero. This parent has six direct children, so the  children get one. One of these children has a child. So that lower child gets a two. And so on.

 

When you are ready to compute transforms, you sort your list.

Share this post


Link to post
Share on other sites

a "parent" variable for each object can be used to store the nesting info (IE what object is this object's parent). when drawing an object, you simply go through all the parents adding their transforms, until you come to the root object with no parent. this is used in the rigid body modeling system in caveman, which supports nesting up to twenty levels deep.

 

you can also add info like the location of the attachment point with respect to the parents local origin, the default rotation of the child with respect to the parent, etc.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!