0
\$\begingroup\$

Small Context.

Moon - Projectile.

Eye - Magnet that rotates on z axis and causes projectile to rotate too.

On the first screen you can see a projectile and it is positioned as -1 on y axis. Parent position is 0,0,0.

enter image description here

The flow is next. Pressing mouse button launches projectile in direction that it is facing and if it hits target it is launched back. On the second screen you can see a code for Magnet that checks for a colliders in radius, if it found it than it means that it found the Projectile

Magnet.Script

private void Update() {
    StickProjectileToMagnetOnReturn();
}

private void StickProjectileToMagnetOnReturn() {
    if (ProjectileState.RETURNING == projectile.GetProjectileState()) {
        Collider2D collider = Physics2D.OverlapCircle(new Vector2(transform.position.x, transform.position.y), 1);
        if (collider != null) {
            projectile.StopProjectile();
            projectile.SetProjectileState(ProjectileState.ROTATING);

            rotationRoutine = StartCoroutine(Rotate());

            GameManager.Instance.SetGameState(GameState.GENERATE_TARGETS);
        }
    }
}

Problem: In unity editor I positioned my projectile on 0,-1,0 coordinates relative to parent. In code when I perform OverlapCircle in 1F radius it finds my Projectile when it is positioned on (0, -1.2,0) which is larger than (0, -1, 0) and results in Projectile being position further from Magnet than on start of the game. I thought that new position og the Projectile should be (0, -1, 0) too or something like (0.5, 0.5, 0)

enter image description here

Projectile.Script

public void LaunchProjectile() {
    Vector3 position = transform.position;

    float v = Vector3.Angle(rotator.transform.position, position);

    float sin = Mathf.Sin(v);
    float cos = Mathf.Cos(v);

    coroutine = StartCoroutine(LaunchInDirection(new Vector3(sin, cos, transform.position.z)));
}

private IEnumerator LaunchInDirection(Vector3 direction) {
    particleSystem.Play();

    while(true) {
        yield return waitForFixedUpdate;
        Vector3 translation = direction * speed * Time.deltaTime;
        transform.Translate(translation);
    }
}

public void StopProjectile() {
    rigidbody.velocity = Vector2.zero;
    rigidbody.angularVelocity = 0;

    transform.localEulerAngles = Vector3.zero;

    StopCoroutine(coroutine);

    particleSystem.Stop();
}

Target.Script

private void OnCollisionEnter2D(Collision2D collision) {
    if (isActive) {
        particleSystem.Play();
        LaunchProjectileBack(collision);
        SetNotActive();

        targetGroup.OnTargetHit();
    } else {
        targetGroup.OnWrongTargetHit();
    }
}

private static void LaunchProjectileBack(Collision2D collision) {
    // here i just redirect my projectile back
    collision.transform.localEulerAngles = new Vector3(0, 0, 180);

    Projectile projectile = collision.transform.GetComponent<Projectile>();
    projectile.SetProjectileState(ProjectileState.RETURNING);
}
\$\endgroup\$
7
  • 1
    \$\begingroup\$ Your circle collider has some radius, no? So it will overlap a circle up to a distance of overlapCircleRadius + colliderRadius away. I might be misreading your screenshots - try not to crop them so tight - ensure the reader can always see what object you're selecting in the hierarchy, scene view, and the full inspector. Share code as text, not images. \$\endgroup\$
    – DMGregory
    Apr 28, 2023 at 13:49
  • \$\begingroup\$ I have no idea how you implemented the returning-mechanic, because there are about a hundred ways to do that. But I would recommend to implement it in a way that makes it return explicitly to 0:-1:0 and not determine whether or not it has arrived using a collision check with the destination. \$\endgroup\$
    – Philipp
    Apr 28, 2023 at 13:53
  • \$\begingroup\$ I did returning by collision.transform.localEulerAngles = new Vector3(0, 0, 180); \$\endgroup\$ Apr 28, 2023 at 13:54
  • \$\begingroup\$ Collider is exactly the size of the Projectile @DMGregory \$\endgroup\$ Apr 28, 2023 at 13:55
  • \$\begingroup\$ It doesn't appear like you posted the code I actually asked for, but I still got an idea what your problem might be. \$\endgroup\$
    – Philipp
    Apr 28, 2023 at 14:14

1 Answer 1

2
\$\begingroup\$

The method Physics2D.OverlapCircle(new Vector2(transform.position.x, transform.position.y), 1); will return true if there is a collider that overlaps a circle of radius 1. That means the distance you will end up with is the radius of the circle plus the radius of the detected collider. I suspect that the reason why you end up at -1.2 instead of -1.0 is because the collider of the magnet has a radius of 0.2 units.

And there is another problem here: You are detecting any collider, not just the one of the magnet. Which could become a source of lots of bugs when your game gets more complex.

But there is a much more reliable and efficient way to check the distance between the positions of two game objects if you have references to both of them in the script. So if you add a variable GameObject magnet to the projectile and make it reference the magnet, then you can do this:

Vector2 myPosition = transform.position;
Vector2 otherPosition = magnet.transform.position;
if(Vector2.Distance(myPosition, otherPosition) <= 1.0f) {
    // destination reached
}

However, keep in mind that you don't know how far the object moved between the previous and the last frame. So in most cases it will end up slightly closer to 1.0f. So it's a good idea to set its position explicitly to where you want it to be:

Vector2 myPosition = transform.position;
Vector2 otherPosition = magnet.transform.position;
if(Vector2.Distance(myPosition, otherPosition) <= 1.0f) {
    transform.localPosition = new Vector3(0, -1, 0);
    // destination reached
}
\$\endgroup\$
2
  • \$\begingroup\$ Thank you for you comment Philipp. Your approach with Vector2 Distance helped me to fix this issue but still I want to clarify about Colliders. My magnet has no collider and also radius of projectile collider is 0.4 so still something strange happens because it should have detected projectile collider faster so resulting transform would be something like 0, -1.38,0 because when using Distance appoach it detects projectile when it's almost at 0, -1, 0. \$\endgroup\$ Apr 28, 2023 at 20:38
  • \$\begingroup\$ Also I guess using Colliders to find distance between two objects is not the best way and ideally Vector.Distance should be used? \$\endgroup\$ Apr 28, 2023 at 20:40

You must log in to answer this question.

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