For example, I have a Door class which inherits from the Box class
By the way, it's generally best to structure game logic such that your game objects
have physical representations (an Entity or some other types like StaticMesh) rather than have game objects that
are physical objects. This helps avoids awkward coupling between rendering, game logic, and physics architecture.
That said, to use the hit object in a ray cast or collision event, it helps to understand the flow of ownership around Collidables and Entities.
-The Entity supports motion and can collide. If dynamic, it's 'normally physical' and will respond to collisions in the expected way. Kinematic entities effectively have infinite mass and inertia, so they do not respond to collisions, but their velocity can be changed manually. Dynamic entities that a kinematic entity runs into will be pushed out of the way or crushed; the kinematic will not slow down or change direction due to the collision. Two kinematics will simply go through each other.
-The Entity.CollisionInformation property returns an EntityCollidable that acts as the entity's collision proxy in the space. This object inherits from Collidable, which in turn inherits from BroadPhaseEntry. BroadPhaseEntry objects live in the collision detection pipeline starting in the BroadPhase, detecting collision pairs for further analysis. Collidable is the subclass of BroadPhaseEntry that is capable of generating contacts with other Collidables. Those contacts are the primary output of the narrow phase collision detection.
-There exist Collidables which are not EntityCollidables and so are not used by any Entity but can exist alone in the Space. These are the StaticMesh, InstancedMesh, and Terrain (and other custom types; it's extensible). These are completely incapable of continuous motion; they cannot have velocity. These are typically used for static level geometry. StaticMesh and its peers don't have a CollisionInformation property because they are the collision information themselves and have no other abilities.
So how is this relevant?
The space ray cast is tested against the BroadPhase's acceleration structure. That acceleration structure holds only references to BroadPhaseEntry objects. You can access the acceleration structure queries directly through the Space.BroadPhase.QueryAccelerator to see how it works. The Space.RayCast takes the list of BroadPhaseEntry objects found by the acceleration structure and performs a detailed ray cast against the individual objects. The logic for the detailed ray cast is defined by the BroadPhaseEntry object itself. That detailed ray cast provides the hit location, time, and normal. So, the result of a Space ray cast is a broad phase entry, the location, T, and normal (or a list of them).
There's a few ways you can get from the BroadPhaseEntry to the data you want.
In your case, where you have extended the Entity type, you'll need to try to cast the entry to EntityCollidable, since that's what Entities have. If the cast succeeds, you can use the EntityCollidable's Entity property to get the entity. You can then attempt to cast that Entity to a Door. If that succeeds, you can call its Open method.
Rather than doing casting around the physics object hierarchy, it's usually more convenient to make use of tags. The BroadPhaseEntry class has its own Tag property. The Entity class has its own separate Tag property. Setting an Entity.Tag does not set the Entity.CollisionInformation.Tag. Because the BroadPhaseEntry.Tag is visible directly from the ray cast result (or collision event), it can be convenient to store a game object in the tag to help manage logic.
For example, if you split up the architecture such that there was a clear separation between physics, rendering, and game logic with some game object that is aware of all the pieces that go into itself and handles the 'glue' between them, you could put that game object into the Tag property. Then, when a ray cast hits a BroadPhaseEntry, you could attempt to cast the Tag to your game object and then fire your RayHit event or directly call some logic or whatever else.
Also, as a sidenote: I'd like to store a string about the collision entity in its tag. I was able to get this to work for a static mesh, but in my Door class (which inherits from a class I wrote for drawing a box which subsequently inherits from the Box class itself) the data doesn't seem to be getting through. Does anyone have any thoughts as to why this doesn't work?
This is probably just the separation between BroadPhaseEntry.Tag and Entity.Tag mentioned above. They are separate properties, so setting one does not set the other automatically.