0
\$\begingroup\$

I am trying to get a random world position inside my targets collider, so that I can fire an arrow at it.

I have tried a bunch of different solution but can't seem to get it right, for example (this code is on my target):

//Inside Awake
colliders = GetComponentsInChildren<Collider>(); //I want this to work on a unit with a single capsule collider and a building with 8 different box colliders

public Vector3 GetRandomPoint()
{
    Bounds b = new Bounds();

    for (int i = 0; i < colliders.Length; i++)
    {
        b.Encapsulate(colliders[i].bounds);
    }

    float minX = gameObject.transform.position.x - gameObject.transform.localScale.x * bounds.size.x * 0.5f;
    float minZ = gameObject.transform.position.z - gameObject.transform.localScale.z * bounds.size.z * 0.5f;

    return new Vector3(Random.Range (minX, -minX),
                           gameObject.transform.position.y,
                           Random.Range (minZ, -minZ));
    }

In the scenario I'm having issues with right now, the trageet simply has a single capsule collider.

This return a point quite far away from my target, but I cant find the issue.

EDIT:

Here is another one I tried without success:

public Vector3 GetRandomPoint()
    {
        Bounds b = new Bounds();

        for (int i = 0; i < colliders.Length; i++)
        {
            b.Encapsulate(colliders[i].bounds);
        }

        var target = new Vector3(
            UnityEngine.Random.Range(b.min.x, b.max.x),
            UnityEngine.Random.Range(b.min.y, b.max.y),
            UnityEngine.Random.Range(b.min.z, b.max.z)
        );

        return b.ClosestPoint(target);
    }
\$\endgroup\$
9
  • \$\begingroup\$ What kind of a collide are you using, and where do you assign the bounds data? \$\endgroup\$
    – DMGregory
    Commented Sep 12, 2020 at 12:49
  • \$\begingroup\$ @DMGregory edited. \$\endgroup\$
    – Majs
    Commented Sep 12, 2020 at 12:52
  • \$\begingroup\$ Remember, new Bounds gives you a bounds that contains the world origin. Do you really want to encapsulate the world origin when your colliders are a long distance away from it? \$\endgroup\$
    – DMGregory
    Commented Sep 12, 2020 at 12:55
  • \$\begingroup\$ @DMGregory did not know that. No I dont. But how do I encapsulate colliders without creating new bounds? If a building has 8 different box colliders, I want to generate a random point inside any of these. \$\endgroup\$
    – Majs
    Commented Sep 12, 2020 at 12:56
  • 1
    \$\begingroup\$ Great! Want to write up your solution as an Answer below? \$\endgroup\$
    – DMGregory
    Commented Sep 12, 2020 at 13:00

1 Answer 1

2
\$\begingroup\$

As instructed by @DMGregory, using new Bounds will use world origin, if I instead just use the first collider in the list, it works as intended:

public Vector3 GetRandomPoint()
    {
        Bounds b = colliders[0].bounds;

        for (int i = 1; i < colliders.Length; i++)
        {
            b.Encapsulate(colliders[i].bounds);
        }

        var target = new Vector3(
            UnityEngine.Random.Range(b.min.x, b.max.x),
            UnityEngine.Random.Range(b.min.y, b.max.y),
            UnityEngine.Random.Range(b.min.z, b.max.z)
        );

        return b.ClosestPoint(target);
    }
\$\endgroup\$

You must log in to answer this question.

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