Untitled

mail@pastecode.io avatar
unknown
csharp
a year ago
12 kB
2
Indexable
using Sirenix.OdinInspector;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;


public class ClosetGenerator : SerializedMonoBehaviour
{
    [Title("tube properties")]
    public float radius = 10;
    public int boxesPerLevel = 36;
    public int numberOfLevels = 20;
    public float boxHeight = 2f;
    public Material tubeMaterial;
    public ParticleSystem _poofParticle;

    [Title("drawer properties")]
    public float drawerDepth = 1f;
    public float drawerBackThickness = 0.3f;
    public float drawerSidesThickness = 0.3f;
    public float drawerUpDownThickness = 0.3f;
    public float colliderSideScale = 1.3f;
    [Title("drawer spacing")]
    public float drawerSideSpacing = 0.1f;
    public float drawerVerticalSpacing = 0.1f;

    [Title("assets")]
    public float spawnProbability = 0.6f;
    public float assetsScale = 1f;
    public float assetsSpacing = 1f;
    public List<AssetsParams> _assetsToSpawn;
    public List<GameObject> _spawnedAssets;
    public struct AssetsParams
    {
        public GameObject asset;
        public Vector3 rotation;
        public float offset;
    }
    [Title("fall animation")]
    [SerializeField]
    public float animTime = 1f;
    public AnimationCurve _animCurve;
    public float blinktime = 1;
    public float destroyTime = 1;

    [Title("objects list")]
    public List<List<ClosetCell>> drawerList = new List<List<ClosetCell>>();
    private void Update()
    {

    }
    [Button]
    private void GenerateTube()
    {
        ClearTube();
        GameObject tubeParent = new GameObject();
        tubeParent.transform.parent = this.transform;
        float anglePerBox = 360f / boxesPerLevel;


        //generating tube
        for (int y = 0; y < numberOfLevels; y++)
        {
            float height = (boxHeight * (y + 1)) - (boxHeight * 0.5f);

            List<ClosetCell> horizontalDrawers = new List<ClosetCell>();
            for (int x = 0; x < boxesPerLevel; x++)
            {
                GameObject myBox = new GameObject();
                myBox.transform.position = new Vector3(0f, height, 0f);
                myBox.transform.parent = tubeParent.transform;
                myBox.transform.eulerAngles = new Vector3(0, anglePerBox * x, 0);
                myBox.transform.Translate(Vector3.forward * radius);
                myBox.transform.localScale = new Vector3(1, 1 - (drawerVerticalSpacing / 2), 1);
                DestroyImmediate(myBox.GetComponent<MeshRenderer>());
                myBox.layer = LayerMask.NameToLayer("Tube");
                myBox.name = x.ToString() + "," + y.ToString();

                var closetCell = myBox.AddComponent<ClosetCell>();                
                closetCell.index = new Vector2Int(x, y);

                horizontalDrawers.Add(closetCell);
                GenerateChildDrawer(myBox);
            }
            drawerList.Add(horizontalDrawers);
        }

        //spawning assets in tube
        

    }

    [Button]
    private void spawnAssets()
    {
        for (int y = 0; y < numberOfLevels; y++)
        {
            for (int x = 0; x < boxesPerLevel; x++)
            {
                for (int i = 0; i < 3; i++)
                {
                    if (Random.Range(0f, 1f)<spawnProbability)
                    {
                        int random = Random.Range(0, _assetsToSpawn.Count);
                        var go = _assetsToSpawn[random].asset;
                        var rotation = _assetsToSpawn[random].rotation;
                        var offset = _assetsToSpawn[random].offset;

                        Vector3 position = new Vector3((i - 1) * assetsSpacing, 0, -drawerDepth / 2);

                        drawerList[y][x].AddObject(go, position, rotation, assetsScale, offset, boxHeight * 0.85f, i, colliderSideScale);
                    }
                    else
                    {
                        Vector3 position = new Vector3((i - 1) * assetsSpacing, 0, -drawerDepth / 2);

                        drawerList[y][x].AddObject(null, position, Vector3.zero, 1, 0, boxHeight * 0.85f, i, colliderSideScale);
                    }
                }
            }
        }
    }
    [Button]
    public void DestroyCell(Vector2Int cell)
    {
        List<GameObject> objectsToAnimate = new List<GameObject>();
        List<float> startPositions = new List<float>();
        List<float> endpositions = new List<float>();

        for (int y = 0; y < numberOfLevels; y++)
        {


            for (int x = 0; x < boxesPerLevel; x++)
            {
                if (x == cell.x && y > cell.y)
                {
                    if (drawerList[y][x] != null)
                    {
                        objectsToAnimate.Add(drawerList[y][x].gameObject);
                        Debug.Log(drawerList[y][x].gameObject.name);
                        startPositions.Add(drawerList[y][x].transform.position.y);
                        endpositions.Add(drawerList[y][x].transform.position.y - boxHeight);
                    }
                }
            }
        }
        Destroy(drawerList[cell.y][cell.x].gameObject);
        drawerList[cell.y][cell.x] = null;


        StartCoroutine(Animate(objectsToAnimate.ToArray(), startPositions.ToArray(), endpositions.ToArray()));
    }
    public void CheckCell(Vector2Int cell)
    {
        if(drawerList[cell.y][cell.x]._slots[0].item.name == drawerList[cell.y][cell.x]._slots[1].item.name && drawerList[cell.y][cell.x]._slots[2].item.name == drawerList[cell.y][cell.x]._slots[1].item.name)
        {
            StartCoroutine(DestroyCoroutine(cell));
        }
    }

    private IEnumerator DestroyCoroutine(Vector2Int cell)
    {
        drawerList[cell.y][cell.x]._slots[0].item.GetComponent<Item>().Blink(blinktime);
        drawerList[cell.y][cell.x]._slots[1].item.GetComponent<Item>().Blink(blinktime);
        drawerList[cell.y][cell.x]._slots[2].item.GetComponent<Item>().Blink(blinktime);

        
        yield return new WaitForSeconds(destroyTime);
        _poofParticle.transform.position = drawerList[cell.y][cell.x].transform.position;
        _poofParticle.transform.eulerAngles = drawerList[cell.y][cell.x].transform.eulerAngles;
        _poofParticle.Play();
        DestroyCell(cell);
    }

    private IEnumerator Animate(GameObject[] objectsToAnimate, float[] startPositions, float[] endpositions)
    {
        if (objectsToAnimate == null || objectsToAnimate.Length == 0)
        {
            Debug.LogWarning("No objects to animate.");
            yield break;
        }

        float elapsedTime = 0f;


        while (elapsedTime < animTime)
        {
            Debug.Log("animating");
            float t = elapsedTime / animTime;

            float curveValue = _animCurve.Evaluate(t);

            for (int i = 0; i < objectsToAnimate.Length; i++)
            {
                Vector3 newPosition = Vector3.Lerp(
                   new Vector3(objectsToAnimate[i].transform.position.x, startPositions[i], objectsToAnimate[i].transform.position.z),
                   new Vector3(objectsToAnimate[i].transform.position.x, endpositions[i], objectsToAnimate[i].transform.position.z),
                   1 - curveValue);
                objectsToAnimate[i].transform.position = newPosition;
            }

            elapsedTime += Time.deltaTime;
            yield return null;
        }



        for (int i = 0; i < objectsToAnimate.Length; i++)
        {
            objectsToAnimate[i].transform.position = new Vector3(objectsToAnimate[i].transform.position.x, endpositions[i], objectsToAnimate[i].transform.position.z);
        }

    }


    private void GenerateChildDrawer(GameObject cell)
    {

        GameObject drawerBack = GameObject.CreatePrimitive(PrimitiveType.Cube);
        drawerBack.name = "drawerBack";
        drawerBack.transform.parent = cell.transform;
        drawerBack.transform.localPosition = Vector3.zero - new Vector3(0, 0, drawerDepth);
        drawerBack.transform.localEulerAngles = Vector3.zero;
        drawerBack.transform.localScale = new Vector3(((2 * Mathf.PI * (radius - drawerDepth)) / boxesPerLevel), boxHeight, drawerBackThickness);
        drawerBack.layer = LayerMask.NameToLayer("Tube");
        if (tubeMaterial != null) drawerBack.GetComponent<Renderer>().material = tubeMaterial;


        float sidePosition = (((2 * Mathf.PI * (radius - (drawerDepth * 0.5f))) / boxesPerLevel) / 2) * 1 - drawerSideSpacing;

        GameObject drawerLeft = GameObject.CreatePrimitive(PrimitiveType.Cube);
        drawerLeft.name = "drawerLeft";
        drawerLeft.transform.parent = cell.transform;
        drawerLeft.transform.localPosition = new Vector3(sidePosition, 0, -drawerDepth / 2);
        drawerLeft.transform.LookAt(new Vector3(0, drawerLeft.transform.position.y, 0));
        drawerLeft.transform.localScale = new Vector3(drawerSidesThickness, boxHeight, drawerDepth);
        drawerLeft.layer = LayerMask.NameToLayer("Tube");
        if (tubeMaterial != null) drawerLeft.GetComponent<Renderer>().material = tubeMaterial;

        GameObject drawerRight = GameObject.CreatePrimitive(PrimitiveType.Cube);
        drawerRight.name = "drawerRight";
        drawerRight.transform.parent = cell.transform;
        drawerRight.transform.localPosition = new Vector3(-sidePosition, 0, -drawerDepth / 2);
        drawerRight.transform.LookAt(new Vector3(0, drawerRight.transform.position.y, 0));
        drawerRight.transform.localScale = new Vector3(drawerSidesThickness, boxHeight, drawerDepth);
        drawerRight.layer = LayerMask.NameToLayer("Tube");
        if (tubeMaterial != null) drawerRight.GetComponent<Renderer>().material = tubeMaterial;

        int subparts = 5;
        for (int i = 0; i < subparts; i++)
        {
            GameObject drawerUp = GameObject.CreatePrimitive(PrimitiveType.Cube);
            drawerUp.name = "drawerUp";
            drawerUp.transform.parent = cell.transform;
            drawerUp.transform.localPosition = new Vector3(0, (boxHeight / 2) - (drawerUpDownThickness / 2), (-drawerDepth * (i + 0.5f)) / subparts);
            drawerUp.transform.LookAt(new Vector3(0, drawerUp.transform.position.y, 0));
            float myRadius = (2 * Mathf.PI * (Vector3.Distance(drawerUp.transform.position, new Vector3(0, drawerUp.transform.position.y, 0))) / boxesPerLevel);
            drawerUp.transform.localScale = new Vector3(myRadius - drawerSidesThickness, drawerUpDownThickness, drawerDepth / subparts);
            if (tubeMaterial != null) drawerUp.GetComponent<Renderer>().material = tubeMaterial;
            drawerUp.layer = LayerMask.NameToLayer("Tube");

            GameObject drawerDown = Instantiate(drawerUp, drawerUp.transform.parent, false);
            drawerDown.name = "drawerDown";
            //drawerDown.transform.parent = drawerUp.transform.parent;
            drawerDown.transform.localPosition = new Vector3(drawerDown.transform.localPosition.x, -drawerDown.transform.localPosition.y, drawerDown.transform.localPosition.z);
        }
    }

    [Button]
    private void ClearTube()
    {
        drawerList.Clear();
        _spawnedAssets.Clear();
        Transform[] meshRenderers = this.transform.GetComponentsInChildren<Transform>();
        for (int i = 0; i < meshRenderers.Length; i++)
        {
            if (meshRenderers[i] != this.transform)
            {
                DestroyImmediate(meshRenderers[i].gameObject);
            }
        }
    }
}