I’m sort of at my wits end with this one. My end goal is a sequence of events that allows the detection of a complete and contiguous ring of blocks around a center point. The blocks will stack in layers and each layer needs to be able to detect a complete ring independent of the others. My original idea was to use Raycasts to pass a parameter around the ring until it found itself signaling a complete circuit and therefor a complete ring. As the detection has to happen frequently I used IEnumerators to fire off the Raycasts from each block. This led to a big strain on the memory so I reworked it so that only one column of blocks will act as the “Detectors” and begin the chain of raycasts to check for complete rings. this involves running a coroutine on each block in this column as they come into play (ScorePassing() in the code below). This part appears to work just fine. The issue arises when the next block in the chain becomes involved starting another coroutine (PassiveScoreCheck() in the code below). As far as I can tell whenever this coroutine starts it’s execution Unity freezes. I determined this by commenting out the call to it and running the code with no problems. I have the coroutine set up so that it should be calling itself on each block as it moves it’s way around the ring but I’m wondering if it is for some reason just running the ring infinitely instead of shutting off after passing itself to the next block or passing the confirmation that a complete ring has been made (which is done in the form of a method {ScoreCall()} not an IEnumerator). In my mind, with the way I have written the code I feel that each the coroutines should be running in sequence but after a bit of research it does appear they may be running concurrently though I’m not sure and would appreciate any input on this as well.
Here is the code. It’s a work in progress so there are pieces that still need to be cleaned out.
public class DetectorScript : MonoBehaviour {
[SerializeField]
private Transform _block;
private GameObject _UIManager;
private Vector3 _detectionDirection;
[SerializeField]
private bool _detectorIsStationary;
[SerializeField]
private bool _detectorIsActive;
[SerializeField]
private bool _detectorIsChecked;
[SerializeField]
private bool _isADetector = false;
private bool _isChainDetector;
private bool _scoreDetected;
private bool _notADetector;
[SerializeField]
private float _detectionDistance = .25f;
private Vector3[] ScoreCheckPositions = new[] { new Vector3(4, -4, 0),
new Vector3(5, -4, 0),
new Vector3(6, -4, 0),
new Vector3(7, -4, 0),
new Vector3(8, -4, 0),
new Vector3(9, -4, 0),
new Vector3(10, -4, 0),
new Vector3(11, -4, 0),
new Vector3(12, -4, 0),
new Vector3(13, -4, 0),
new Vector3(14, -4, 0),
new Vector3(15, -4, 0),
new Vector3(16, -4, 0),
new Vector3(17, -4, 0),
new Vector3(18, -4, 0),
new Vector3(19, -4, 0) };
private float _scoreCheckSec = .25f;
void Awake ()
{
_UIManager = GameObject.Find("UIManager");
StartCoroutine(GroundDetectionSequence());
if(transform.name == "ChainDetector")
{
_isChainDetector = true;
}
//Debug.Log(_isChainDetector + " " + transform.name);
//Debug.Log(_isADetector + " " + transform.name);
}
void Update ()
{
if (_isChainDetector == false)
{
_detectionDirection = _block.GetComponent<SingleBlockScript>().blockDirection;
}
else
{
_detectionDirection = Vector3.right;
}
_detectorIsStationary = _block.GetComponent<SingleBlockScript>().isStationary;
_detectorIsActive = _block.GetComponent<SingleBlockScript>().isActive;
_detectorIsChecked = _block.GetComponent<SingleBlockScript>().isChecked;
}
IEnumerator GroundDetectionSequence()
{
while (true)
{
if (_detectorIsStationary == false)
{
GroundDetection();
yield return new WaitForSeconds(_scoreCheckSec);
}
else if (_detectorIsStationary == true && _isADetector == false && _scoreDetected == false)
{
//Debug.Log("Is this the hole?");
ScoreDetection();
yield return new WaitForSeconds(_scoreCheckSec);
yield return new WaitUntil(() => _detectorIsStationary == false || _isADetector == true);
}
else if(_isADetector == true && _detectorIsStationary == true && _isChainDetector == true)
{
yield return new WaitUntil(() => _detectorIsActive == false);
Debug.Log("Detector Detected");
yield return ScorePassing();
_block.GetComponent<Renderer>().material = _block.GetComponent<SingleBlockScript>().red;
yield return new WaitForSeconds(_scoreCheckSec);
yield return new WaitUntil(() => _detectorIsStationary == false);
}
else
{
yield return new WaitUntil(() => _detectorIsStationary == false);
}
}
}
private void GroundDetection()
{
if (_isChainDetector == false)
{
RaycastHit2D grounded = Physics2D.Raycast(transform.position, _detectionDirection, _detectionDistance);
if (grounded.collider != null)
{
if (grounded.collider.tag == "Block")
{
_block.GetComponent<SingleBlockScript>().isStationary = true;
_detectorIsStationary = true;
_detectorIsActive = false;
}
else if (grounded.collider.tag == "PlayingField")
{
_block.GetComponent<SingleBlockScript>().isStationary = true;
_detectorIsStationary = true;
_detectorIsActive = false;
}
}
}
}
private void ScoreDetection()
{
_scoreDetected = true;
foreach (Vector3 i in ScoreCheckPositions)
{
if (i == _block.position)
{
_isADetector = true;
_block.GetComponent<SingleBlockScript>().cornerDetectProxy = false;
_notADetector = false;
}
else
{
_notADetector = true;
_scoreDetected = false;
}
}
}
IEnumerator ScorePassing()
{
while (true)
{
if (_isChainDetector == true && _isADetector == true)
{
RaycastHit2D scorecheck = Physics2D.Raycast(transform.position, Vector3.right, _detectionDistance);
if (scorecheck.collider != null)
{
if (scorecheck.collider.tag == "Block" && scorecheck.collider.name != _block.name)
{
_detectorIsChecked = true;
yield return scorecheck.collider.GetComponentInChildren<DetectorScript>().PassiveScoreCheck();
}
}
}
else
{
StopCoroutine(ScorePassing());
}
yield return new WaitForSeconds(_scoreCheckSec);
}
}
public IEnumerator PassiveScoreCheck()
{
while (true)
{
if (_isChainDetector == true && _isADetector == false)
{
RaycastHit2D passiveScoreCheck = Physics2D.Raycast(transform.position, Vector3.right, _detectionDistance);
if (passiveScoreCheck.collider != null)
{
if (passiveScoreCheck.collider.tag == "Block" && _isChainDetector == true)
{
if(_isADetector == true)
{
passiveScoreCheck.collider.GetComponentInChildren<DetectorScript>().ScoreCall();
StopCoroutine(PassiveScoreCheck());
}
else if (_isADetector == false)
{
yield return passiveScoreCheck.collider.GetComponentInChildren<DetectorScript>().PassiveScoreCheck();
StopCoroutine(PassiveScoreCheck());
}
else
{
StopCoroutine(PassiveScoreCheck());
}
}
}
}
StopCoroutine(PassiveScoreCheck());
}
}
public void ScoreCall()
{
RaycastHit2D scoreCall = Physics2D.Raycast(transform.position, _block.position, _detectionDistance);
if (scoreCall.collider != null)
{
if (scoreCall.collider.tag == "Block")
{
scoreCall.collider.GetComponentInChildren<DetectorScript>().ScoreCall();
_UIManager.GetComponent<UIManager>().score++;
_block.GetComponent<SingleBlockScript>().BlockBlastSequence();
}
}
}
}