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; } } }