That depends on what kind of unused variables you're looking for. If we're talking about variables whose scope (visibility) is limited to known locations, then it's fairly easy.
https://github.com/dart-lang/sdk/blob/main/pkg/analyzer/doc/tutorial/analysis.md should explain how to use an `AnalysisContextCollection` to get an `AnalysisSession`. Given an `AnalysisSession` you can use `getResolvedLibrary` to get the fully resolved ASTs for each of the libraries where the variable could be visible and for the library that declares the variable. First traverse the AST of the declaring library to find the declaration in question so that you can access the `declaredElement`, then traverse all of the ASTs (including the declaring library) to find `SimpleIdentifier`s whose static element is equal to the declared element. If you don't find any, then the variable is unreferenced.
(Depending on what you need, it might also be useful to check the `errors` associated with the individual `units` in the result. For local variables there should be a diagnostic indicating that they're unused. That won't cover all possible variables, though, so it isn't a replacement for the more general technique above.)
Let me know if you have additional questions.