0
\$\begingroup\$

Screenshot of stacked balls

I want to make a mechanic like this: on clicking one of the connected balls, all connected balls get destroyed.

So far I have come with the method in the script below. However, it does not work at all.

I tried storing balls as previous balls and next balls when a new ball enters the collider and then using this linked list getting the first ball and start deleting from there but I am not able to implement that.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum BallsType
{
    yellow,
    blue,
    red,
    green
}
public class ConnectedObject
{
    public BallsController connectedBall;
    public GameObject spawnedLine;
}
public class BallsController : MonoBehaviour
{
    public BallsWithColor myColor;
    public GameObject linePrefab;
    public SpriteRenderer myrenderer;
    [SerializeField]private ConnectedObject nextObj;
    public ConnectedObject prevObj=new();
    public string prevObjName;
    void Start()
    {
        BallsWithColor returnedColor = GameManager.instance.GetRandomColor();
        myColor = new BallsWithColor
        {
            ballSprite =returnedColor.ballSprite,
            ballsType = returnedColor.ballsType,
            ballColor = new Color
            {
                r=returnedColor.ballColor.r,
                g=returnedColor.ballColor.g,
                b=returnedColor.ballColor.b,
                a=1,
            }
        };
        myrenderer.color = myColor.ballColor;
    }

    // Update is called once per frame
    void Update()
    {
        
    }
    private bool connectedObjectHasMe(BallsController controller)
    {
        if (controller.nextObj == null)
            return false;
        if (controller.nextObj.connectedBall == null)
            return false;
        if (controller.nextObj.connectedBall == this)
            return true;
        BallsController nextcontoller = controller;
        while(nextcontoller != null)
        {
            if (nextcontoller == this)
                return true;
            if (nextcontoller.nextObj == null)
                return false;
            nextcontoller = nextcontoller.nextObj.connectedBall;
        }

        return false;
    }
    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.CompareTag("Ball"))
        {
            BallsController other = collision.GetComponent<BallsController>();
            if (other == null)
                return;
            if (myColor.ballsType != other.myColor.ballsType)
                return;

            //if (!isObjectInList(collision.GetComponent<BallsController>()) )
            if (nextObj==null && !connectedObjectHasMe(other) )
            {
                Vector2 pos = new((transform.position.x + collision.transform.position.x) / 2,
                (transform.position.y + collision.transform.position.y) / 2);
                Vector3 targ =pos;
                targ.z = 0;
                Vector3 objectPos = transform.position;
                targ.x -= objectPos.x;
                targ.y -= objectPos.y;

                float angle = Mathf.Atan2(targ.y, targ.x) * Mathf.Rad2Deg;
                GameObject spawnedLine = Instantiate(linePrefab, pos, Quaternion.Euler(new Vector3(0, 0, angle)));
                spawnedLine.GetComponent<SpriteRenderer>().color = myColor.ballColor;
                nextObj=new ConnectedObject
                {
                    connectedBall = collision.GetComponent<BallsController>(),
                    spawnedLine = spawnedLine
                };
                other.prevObj.connectedBall=this;
                other.prevObjName = this.GetInstanceID().ToString();
            }
        }
    }
    private void OnTriggerStay2D(Collider2D collision)
    {
        if (collision.CompareTag("Ball"))
        {
            BallsController other = collision.GetComponent<BallsController>();

            if (myColor.ballsType != other.myColor.ballsType)
                return;

            //if (isObjectInList(collision.GetComponent<BallsController>()))
            if (nextObj == null &&!connectedObjectHasMe(other))
            {
                Vector2 pos = new((transform.position.x + collision.transform.position.x) / 2,
                (transform.position.y + collision.transform.position.y) / 2);
                Vector3 targ = pos;
                targ.z = 0;
                Vector3 objectPos = transform.position;
                targ.x -= objectPos.x;
                targ.y -= objectPos.y;

                //Off by 90 degrees for some reasons
                float angle = Mathf.Atan2(targ.y, targ.x) * Mathf.Rad2Deg;
                GameObject spawnedLine = Instantiate(linePrefab, pos, Quaternion.Euler(new Vector3(0, 0, angle)));
                spawnedLine.GetComponent<SpriteRenderer>().color = myColor.ballColor;
                nextObj = new ConnectedObject
                {
                    connectedBall = collision.GetComponent<BallsController>(),
                    spawnedLine = spawnedLine
                };
                other.prevObj.connectedBall = this;
                other.prevObjName = this.GetInstanceID().ToString();

            }
            else if (nextObj != null)
            {
                //SetLinePos(collision.GetComponent<BallsController>());
                Vector2 pos = new((transform.position.x + nextObj.connectedBall.transform.position.x) / 2,
                (transform.position.y + nextObj.connectedBall.transform.position.y) / 2);
                Vector3 targ = pos;
                targ.z = 0;
                Vector3 objectPos = transform.position;
                targ.x -= objectPos.x;
                targ.y -= objectPos.y;
                float angle = Mathf.Atan2(targ.y, targ.x) * Mathf.Rad2Deg;
                nextObj.spawnedLine.transform.SetPositionAndRotation(pos, Quaternion.Euler(new Vector3(0, 0, angle)));

            }
        }
    }
    private void OnTriggerExit2D(Collider2D collision)
    {
        if (collision.CompareTag("Ball"))
        {
            BallsController other = collision.GetComponent<BallsController>();

            if (myColor.ballsType != collision.GetComponent<BallsController>().myColor.ballsType)
                return;
            //if (isObjectInList(collision.GetComponent<BallsController>()))
            if (nextObj != null)
            {
                //DestroyObjectInList(collision.GetComponent<BallsController>());
                Destroy(nextObj.spawnedLine);
                nextObj=null;
                other.prevObjName = "";
                other.prevObj.connectedBall = null;
            }
        }
    }
    private BallsController GetFirstInTheList(BallsController controller)
    {
        BallsController prev = controller;
        while(prev != null)
        {
            Debug.Log(prev.GetInstanceID());
            if (prev.prevObj.connectedBall == null)
            {
                return prev;
            }
            prev = prev.prevObj.connectedBall;
        }
        Debug.Log("A lot is wrong");
        return null;
    }
    public void DestroyMe()
    {
        //BallsController firstInList = GetFirstInTheList(this);
        if(nextObj != null)
        {
            if(nextObj.connectedBall != null)
            {
                nextObj.connectedBall.DestroyMe();
            }
        }
        //GameManager.instance.AddScore(1);
        //Some Effects
        Destroy(gameObject);
    }
    public void DestroyOnlyMe()
    {
        if (nextObj != null)
        {
            if (nextObj.connectedBall != null)
            {
                nextObj.connectedBall.DestroyOnlyMe();
            }
        }
        Destroy(gameObject);
    }
}
\$\endgroup\$
5
  • \$\begingroup\$ As far as I can see, you do not have a stored state of your balls. Is it intended as well that they don't fall evenly? (Left are 9 balls vs right are 8 balls) Your bottom left green balls seems to be as well divided into 2 groups instead of only one. But basically your function that can draw the line between the balls should be able to destroy as well all connected balls \$\endgroup\$
    – Zibelas
    Jul 10 at 20:29
  • \$\begingroup\$ The screen was designed in a way that horizontal area has only space for 4.5 balls so that the balls doesnot seems aligned in grid.It was intentional. And about line drawer how do i implement that. Balls has to destroyed when clicked on balls not on line. And all the connected balls need to destroyed while line only connects two balls. \$\endgroup\$
    – Ravi Thapa
    Jul 11 at 4:43
  • 1
    \$\begingroup\$ As far as I can see, Your data structure can describe a doubly linked list, but a tree structure appears in the post picture. \$\endgroup\$
    – Mangata
    Jul 12 at 2:55
  • \$\begingroup\$ Thanks for your comments. I solved this.I created class for line which contains the list of balls its connecting.And while deleting balls were accessed through line as per the suggestion from @Zibelas. \$\endgroup\$
    – Ravi Thapa
    Jul 13 at 2:58
  • \$\begingroup\$ @RaviThapa If your solution worked for you, you may write it as an answer and accept it. \$\endgroup\$
    – liggiorgio
    Jul 13 at 15:20

0

You must log in to answer this question.

Browse other questions tagged .