1
\$\begingroup\$

I'm developing a 2D top down shooter game. I'm building the grenade functionality. The idea is that while you're holding the grenade button, it remains in your hand, and then when you release the button it throws the grenade. When the grenade is in your hand, I'm using a line renderer to show the trajectory of where the grenade will be thrown and bounce off walls.

I have a recursive function that uses linecasts to detect where the grenade will bounce and reflect the line as if it was bouncing off the wall. It's working as expected but it's somehow still giving a Stack Overflow Error. If I point the LineRenderer at a wall and put a breakpoint on the first line of the recursive function ThrowLineRaycast() it's only being called twice, and _lineRendererPoints.Count = 3.

void Update() {
    if (_isHeld && _throwable.ReleaseType == "Throw") {
        DrawThrowLine();
    }
}

private void DrawThrowLine() {
    _lineRendererPoints = new() { _rigidbody.position };
    ThrowLineRaycast(_rigidbody.position, transform.up, 0, _throwDistance);
    _lineRenderer.positionCount = _lineRendererPoints.Count;
    _lineRenderer.SetPositions(_lineRendererPoints.ToArray());
}

private void ThrowLineRaycast(Vector3 startPos, Vector3 direction, float distanceTraveled, float distanceRemaining, int hitNum = 0) {
    Vector3 endPos = startPos + (direction * distanceRemaining);
    LayerMask mask = LayerMask.GetMask("Walls", "WindowsAndCover");
    RaycastHit2D[] allHits = Physics2D.LinecastAll(startPos, endPos, mask);
    if (hitNum > allHits.Length - 1) {
        _lineRendererPoints.Add(endPos);
    } else {

        RaycastHit2D hit = allHits[hitNum];
        Vector3 hitPos = hit.point;
        Vector3 newDirection = Vector3.Reflect(direction, hit.normal);
        float totalDistanceToHit = distanceTraveled + hit.distance;
        float distanceRemainingAfterHit = distanceRemaining - hit.distance;

        if (hit.transform.gameObject.layer == LayerMask.NameToLayer("Walls")) {
            _lineRendererPoints.Add(hitPos);
            ThrowLineRaycast(hitPos, newDirection, totalDistanceToHit, distanceRemainingAfterHit, 0);
        } else if (hit.transform.gameObject.layer == LayerMask.NameToLayer("WindowsAndCover")) {
            if (GetThrowHeightFromLength(distanceTraveled, distanceTraveled + distanceRemaining) < _coverHeight) {
                _lineRendererPoints.Add(hitPos);
                ThrowLineRaycast(hitPos, newDirection, totalDistanceToHit, distanceRemainingAfterHit, 0);
            } else {
                ThrowLineRaycast(startPos, direction, distanceTraveled, distanceRemaining, hitNum + 1);
            }
        }
    }
}

private float GetThrowHeightFromLength(float distanceTraveled, float throwDistance) {
    return 3f;
}

Note: Ignore the WallsAndCover and throw height part. That hasn't been fully implemented yet, but the idea is that if the grenade is in the air and has a height greater than the height of the cover (something you can shoot over) it will ignore that hit. this is why I need the LinecastAll and hitNum, but that part of the code isn't even being hit yet.

\$\endgroup\$

1 Answer 1

0
\$\begingroup\$

Watched a bunch of tutorials on bouncing lasers and found one that suggested adding Physics2D.queriesStartInColliders = false; to the start function. I'm using awake in this case so I added it and that solved the problem. So I guess the second iteration was colliding with the same collision that the first iteration hit.

It's strange that my debugging didn't reflect that issue. If that was the case I would expect the breakpoint to be hit way more and have way more Vector3's in _lineRendererPoints

\$\endgroup\$

You must log in to answer this question.

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