I can list three candidate approaches. I'm not sure how to choose among them -- you might need to experiment among them to see which will work best in your situation.
Approach #1: sweepline algorithm
This can be solved with a straightforward application of a sweepline algorithm.
Sweep a vertical line from left to right, with increasing $x$-values. At any value of $x$, you'll have a binary search tree that, given $y$, lets you look up which polygon the point $(x,y)$ is contained in. There are two key ideas in sweepline algorithms: you only need one tree for each interval of $x$-values between two adjacent "events" (here each event is an intersection of two line segments from the exteriors of the polygons), so you only need only $O(n)$ binary search trees; and, each binary search tree differs from the previous one by a single insertion or deletion, so you don't need to store all of them separately, but you can store them jointly using a persistent data structure.
Now this makes it easy to solve your problem. At any moment in time, we know the $(x,y)$ position of the point and can look up which polygon it is contained in and a trapezoid inside that polygon it is contained in. As the point moves, once it leaves that trapezoid, we can query the data structure again. Each lookup into the data structure takes $O(\log n)$ time, so will be efficient.
Approach #2: Graph of polygons
As a precomputation, build an undirected graph of polygons, where each polygon is a vertex, and two polygons are joined by an edge if they are adjacent (overlap in a point or line segment). Store this graph in an adjacency list representation. Also, find the polygon that contains the initial position of the point by any algorithm (e.g., linear scan over all polygons).
Note that you can answer point-in-polygon queries (given a point and a polygon, is the point inside that polygon?) in time linear in the number of vertices of the polygon.
Now, the algorithm is simple. Watch the movement of the current point, and as soon as it leaves the current polygon, check which polygon it has moved into by doing a point-in-polygon query on each adjacent polygon. Thus, when it leaves the current polygon, the work is proportional to the number of neighboring polygons, not to the total number of polygons.
There are various optimizations and improvements available:
Optimization 1: We can speed up the process of finding when the point leaves the polygon it is currently inside. If we are guaranteed that once the point leaves a polygon, it will never come back to it, then we can use binary search over time to find the first instant when it has left the polygon. Each iteration of binary search requires one point-in-polygon query and we do logarithmically many iterations. If we don't have that guarantee, but we have an upper bound on the speed and/or acceleration and/or turning radius for the movement of the point, we can compute a lower bound on the time to leave the current polygon and return to it (based on the current position of the point and the polygon it is contained within), and use a modified binary search where we avoid jumping further into the future in any one step than given by that bound.
Optimization 2: We can sort each adjacency list. Consider the adjacency list for polygon $P$. Suppose the perimeter of $P$ has length $\ell$. If you walk along the perimeter of $P$ starting at some point on the perimeter and returning to it, this maps each point on the perimeter to a number in the range $[0,\ell)$, which gives a total order on points on the perimeter. This yields a total order on the polygons adjacent to $P$: map each neighboring polygon to the points of intersection on the perimeter of $P$, map those to numbers/intervals in $[0,\ell)$, then sort by that. (We can resolve ties as follows: if two neighboring polygons both overlap with $P$ at the same point $p$, where $p$ is on some face of $P$, then imagine extending outward by a tiny bit $\epsilon$ from that face and look at the intersection with those two polygons.) So, sort each adjacency list in this way, as part of the precomputation/setup phase.
This now speeds up the process of determining which new polygon the point has entered, when it leaves the current one: instead of using a number of point-in-polygon tests that is linear in the number of neighboring polygons, it goes by the log of the number of neighboring polygons.
Optimization 3: Compute the bounding box for each polygon. Now, before doing a point-in-polygon test, you can first check whether the point is in the bounding box, which will enable quickly rejecting some polygons.
You could also use this to speed up finding the polygon the initial position is within. Store all bounding boxes in some appropriate data structure (e.g., a quadtree). Now, given a point, use that data structure to enumerate all bounding boxes it is contained in, then test each with a point-in-polygon test.
Approach #3: Graph of triangles
During a precomputation, triangulate each polygon, i.e., decompose it into a union of triangles. Now combine all these triangles, build a graph of triangles, and proceed as in approach #2, but using triangles instead of objects.
This replaces each point-in-polygon test with a point-in-triangle test, which is much faster; but because the point will traverse many more triangles than polygons, the number of iterations might be much larger. I'm not sure which approach will be faster in the end.
Also, the type of triangulation used might affect performance. I'm not sure whether it is better to choose a triangulation that minimizes the variance of the degrees in the graph or one that maximizes the variance (e.g., a fan decomposition).