I'm using Linq to select the objects closest to the player that have the usable tag thusly:

GameObject[] usables = GameObject.FindGameObjectsWithTag("Usable")
    .Where(t => Vector3.Distance(t.transform.position, playerT.position) < useDistance)

This works as I intended, but I'd like to further narrow it down to the closest object in that array so the Linq query returns only the single closest GO. Linq is, however, a serious weak spot for me. Any thoughts on how that would look?



I think this post on "How to use linq to find the minimum" will give you some ideas on this. The MinBy extension method in MoreLINQ is likely your best bet, as there isn't a built-in method for what you want to do in System.Linq.

Doing this in pure LINQ is possible with LINQ methods like Aggregate or even OrderBy to sort, but I think it is likely to be a bit clunky or not performant compared to non-pure LINQ code.

This answer shows how to use Aggregate to accomplish finding the minimum item. For example, if you really wanted to use LINQ for this:

var usables = GameObject.FindGameObjectsWithTag("Usable");
var closestUsable = usables.Aggregate((minItem, nextItem) => Vector3.Distance(minItem.transform.position, playerT.position) < Vector3.Distance(nextItem.transform.position, playerT.position) ? minItem : nextItem)
// check if (closestUsable < useDistance), or add another `Where` method to keep it LINQ

However, this involves calling Vector3.Distance more often than necessary and it is also not very readable.

EDIT: This is how this would look like with OrderBy which is more readable, but runs in O(n log n) time due to the sorting:

    GameObject closestUsable = GameObject.FindGameObjectsWithTag("Usable")
        .OrderBy(t => Vector3.Distance(t.transform.position, playerT.position))
        .Where(t => Vector3.Distance(t.transform.position, playerT.position) < useDistance)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .