There's a few different high level approaches to consider:
1) Rough query volumes. For simpler queries where you only care about overlapping bounding boxes or centerpoint distance, simply querying the broad phase using Simulation.BroadPhase.GetOverlaps is a good choice. By avoiding contact generation, it's quite a bit faster than more precise tests. You can apply your own filtering after the fact- once you have the set of collidables with overlapping bounding boxes, you could check their centerpoints for distance to the center, for example. Bounding box level intersection of rays can also be done using Simulation.BroadPhase.RayCast.
2) You can perform your own contact-level queries by using the CollisionBatcher on the results of a GetOverlaps call. It's a little complex to use- you have to collect all the relevant information, and the batcher is built to operate across many tests at once. It'll give you the same raw contact information that the narrow phase callbacks would give you, though.
3) Having a collidable in the simulation which generates pairs and reports pairs/contacts through the narrow phase callbacks. If a query is intended to be long lasting (many contiguous frames, like a trigger region), this can be a little faster than a query that does the same thing since it's batched alongside the rest of the simulation. If you only need overlaps, you can use the AllowContactGeneration callback and return false to stop contact generation. If you need contacts and don't want constraints, the ConfigureContactManifold callback would do the trick (again returning false to stop constraints).
The ContactEventsDemo shows one example of #3. Individual collidables are registered as eventful in a dictionary. Determining whether a given collision should emit an event requires a dictionary lookup. The rest of the demo is just showing basic infrastructure about how to record the event and avoid re-emitting events every frame. This isn't the fastest or simplest approach, but it shows how an 'initial contact' event system could be made.
The TankDemo is another example of #3, but it uses a different approach that's a little more direct. Rather than having a dictionary of eventful collidables, TankCallbacks stores metadata about every single dynamic body by handle (the Properties field). In the callback, the collidable handle is used to look up that metadata. It uses a direct O(1) lookup. Based on that metadata it adds the event to the ProjectileImpacts list. Given the relative rarity of projectile impacts, a lock is used to append new events to the list. If your events are rare, this is fine. For extremely frequent events (hundreds of times per frame), you might have to adopt a strategy like per-thread event lists (like the ContactEventsDemo) instead to avoid synchronization overhead.
My superior(my brother) think create list like contactEventDemo is just touch and not in it can't use like skilll like firewall(ragnarok online)(this skill damage enemy that in it and if not unleaded it will push it back);
While the 'initial contact' event wouldn't be a great choice for something like a persistent firewall, contacts are still reported during deep collision, so a different version that reports every frame of collision would work. It's worth noting that meshes don't have volume, so you'd want to use primitives like Boxes or ConvexHulls instead to define a trigger volume. (Or track entry and exit events, but that would be complicated.)
Thank you. You are really dedicate to bepuphysics. I appreciate you help.