eye-therapy-2 / Assets / Scripts / Builder / BuildingBehaviour.cs
BuildingBehaviour.cs
Raw
using System.Collections;
using UnityEngine;

public class BuildingBehaviour : MonoBehaviour, IListener
{
    public Transform building;
    [SerializeField] Transform destination = null;
    [SerializeField] private Color wrongColor = new Color(1, 0, 0, 0.1f);
    [SerializeField] private AnimationCurve colorChangeCurve = null;
    [SerializeField][Min(0.1f)] private float wrongPosAnimTime = 0.5f;

    private bool buildDone = false;
    private Color destBottomColor, destTopColor;
    private Material destinationMaterial;
    private Material[] buildingMaterials;
    private bool wrongCoroutineRunning = false;
    private Vector3 finalPosition;
    private ParticleSystemRenderer destPsRenderer;
    private Vector3 currentEulerAngles;
    
    void Start()
    {
        building.GetComponent<Renderer>().enabled = false;
        destination.GetComponent<Renderer>().enabled = false;

        Bounds b = building.GetComponent<Renderer>().bounds;
        destination.position = new Vector3(destination.position.x, b.center.y + 0.01f, b.center.z);
        destination.localScale = b.size + Vector3.one * 0.01f;
        finalPosition = new Vector3(destination.position.x, building.position.y, b.center.z);
        var destPsShape = destination.GetComponent<ParticleSystem>().shape;
        destPsShape.position = new Vector3(destPsShape.position.x, b.min.y, destPsShape.position.z);

        buildingMaterials = building.GetComponent<Renderer>().materials;
        for (int i = 0; i < buildingMaterials.Length; i++)
        {
            buildingMaterials[i].SetInt("_HighlightOn", 0);
        }
        destinationMaterial = destination.GetComponent<Renderer>().material;
        destBottomColor = destinationMaterial.GetColor("_BottomColor");
        destTopColor = destinationMaterial.GetColor("_TopColor");
        destPsRenderer = destination.GetComponent<ParticleSystemRenderer>();
        currentEulerAngles = building.eulerAngles;

        EventManager.Instance.AddListener(EVENT_TYPE.ON_BUILDING_EYE_CHANGED, this);
        EventManager.Instance.AddListener(EVENT_TYPE.ON_BUILDING_DEST_EYE_CHANGED, this);
    }

    public void Init(float? startX = null)
    {
        if(startX != null)
        {
            building.position = new Vector3(startX.Value, building.position.y, building.position.z);
        }
        for (int i = 0; i < buildingMaterials.Length; i++)
        {
            buildingMaterials[i].SetInt("_HighlightOn", 1);
        }
        building.GetComponent<Renderer>().enabled = true;
        building.GetComponent<Renderer>().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
        destination.GetComponent<Renderer>().enabled = true;
        destination.GetComponent<ParticleSystem>().Play();
    }

    public void CheckDistance(float distance)
    {
        if (Mathf.Abs(building.position.x - destination.position.x) <= distance)
        {
            EventManager.Instance.PostNotification<Object>(EVENT_TYPE.ON_BUILDING_BUILT, this);
            StopAllCoroutines();
            StartCoroutine(FinalizeBuild());
        }
        else
        {
            StartCoroutine(WrongPosColorAnim());
        }
    }

    public void Rotate()
    {
        currentEulerAngles += new Vector3(0, 90, 0);
        building.eulerAngles = currentEulerAngles;
    }

    IEnumerator WrongPosColorAnim()
    {
        if (wrongCoroutineRunning) yield break;
        wrongCoroutineRunning = true;
        float t = 0f;
        while (t <= wrongPosAnimTime)
        {
            t += Time.deltaTime;
            float percent = Mathf.Clamp01(t / wrongPosAnimTime);
            float curvePercent = colorChangeCurve.Evaluate(percent);
            destinationMaterial.SetColor("_BottomColor", Color.LerpUnclamped(destBottomColor, wrongColor, curvePercent));
            yield return null;
        }
        destinationMaterial.SetColor("_BottomColor", destBottomColor);
        wrongCoroutineRunning = false;
    }

    IEnumerator FinalizeBuild()
    {
        buildDone = true;
        destination.GetComponent<ParticleSystem>().Stop();
        for (int i = 0; i < buildingMaterials.Length; i++)
        {
            buildingMaterials[i].SetInt("_HighlightOn", 0);
        }
        float t = 0f;
        Vector3 startPosition = building.position;
        float buildingAlphaLeft = buildingMaterials[0].GetFloat("_AlphaLeftEye");
        float buildingAlphaRight = buildingMaterials[0].GetFloat("_AlphaRightEye");
        float destinationAlphaLeft = destinationMaterial.GetFloat("_AlphaLeftEye");
        float destinationAlphaRight = destinationMaterial.GetFloat("_AlphaRightEye");
        while (t <= 1f)
        {
            t += Time.deltaTime;
            destinationMaterial.SetColor("_BottomColor", Color.Lerp(destBottomColor, destTopColor, t));
            building.position = Vector3.Lerp(startPosition, finalPosition, t);
            destinationMaterial.SetFloat("_AlphaLeftEye", Mathf.Lerp(destinationAlphaLeft, 1f, t));
            destinationMaterial.SetFloat("_AlphaRightEye", Mathf.Lerp(destinationAlphaRight, 1f, t));
            for(int i = 0; i < buildingMaterials.Length; i++)
            {
                buildingMaterials[i].SetFloat("_AlphaLeftEye", Mathf.Lerp(buildingAlphaLeft, 1f, t));
                buildingMaterials[i].SetFloat("_AlphaRightEye", Mathf.Lerp(buildingAlphaRight, 1f, t));
            }
            yield return null;
        }
        destination.GetComponent<Renderer>().enabled = false;
        building.GetComponent<Renderer>().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.On;
    }

    public void OnEvent<T>(EVENT_TYPE eventType, Component Sender, T param = default)
    {
        switch (eventType)
        {
            case EVENT_TYPE.ON_BUILDING_EYE_CHANGED:
                if (!buildDone)
                {
                    for (int i = 0; i < buildingMaterials.Length; i++)
                    {
                        buildingMaterials[i].SetFloat("_AlphaLeftEye", ((dynamic)param)[0]);
                        buildingMaterials[i].SetFloat("_AlphaRightEye", ((dynamic)param)[1]);
                    }
                }
                break;
            case EVENT_TYPE.ON_BUILDING_DEST_EYE_CHANGED:
                if (!buildDone)
                {
                    destinationMaterial.SetFloat("_AlphaLeftEye", ((dynamic)param)[0]);
                    destinationMaterial.SetFloat("_AlphaRightEye", ((dynamic)param)[1]);
                    destPsRenderer.material.SetFloat("_AlphaLeftEye", ((dynamic)param)[0]);
                    destPsRenderer.material.SetFloat("_AlphaRightEye", ((dynamic)param)[1]);
                }
                break;
        }
    }
}