using System.Collections; using System.Collections.Generic; using UnityEngine; #if UNITY_EDITOR using UnityEditor; #endif public class CastleAnimator : MonoBehaviour { public float WaitAtStart = 2; public float MoveSpeed = 30; public float MaxWaitTime = 5; [SerializeField] public AnimationCurve SpeedCurve; public float BridgeSpeed = 30; public float maxBridgeWaitTime = 0.5f; [SerializeField] public AnimationCurve ScaleCurve; [System.Serializable] public struct Base { public GameObject gameObject; public Bounds BaseBound; public Tower tower; } [System.Serializable] public struct Tower { public Vector3 originalPos; public GameObject gameObject; public List TowerPieces; public GameObject[] ScalePoints; } [HideInInspector] public List Bases = new List(); public enum ScaleDirection {PositiveX, PositiveZ, NegativeX, NegativeZ } public void Start() { if (MoveSpeed == 0) { Debug.LogWarning("Tower Movement set to 0"); return; } foreach(Base Base in Bases) { StartCoroutine(MoveTower(Base.tower, MoveSpeed, MaxWaitTime)); } } private IEnumerator MoveTower(Tower tower, float moveSpeed, float startRandomizer) { foreach (GameObject scalePoint in tower.ScalePoints) { scalePoint.SetActive(false); scalePoint.transform.localScale = Vector3.zero; } Vector3 endPos = tower.gameObject.transform.position; tower.gameObject.transform.localPosition = Vector3.zero; Vector3 startPos = tower.gameObject.transform.position; float elapsedTime = 0; float randomWait = Random.Range(0, startRandomizer); float animationTime = (Vector3.Distance(endPos, startPos) / moveSpeed); yield return new WaitForSeconds(randomWait + WaitAtStart); while (elapsedTime < animationTime) { float curvePercent = SpeedCurve.Evaluate((elapsedTime / animationTime)); tower.gameObject.transform.position = UnclampedLerp(startPos, endPos, curvePercent); elapsedTime += Time.deltaTime; yield return new WaitForEndOfFrame(); } tower.gameObject.transform.position = endPos; StartCoroutine(scaleBridge(tower.ScalePoints[0], ScaleDirection.PositiveX, BridgeSpeed,maxBridgeWaitTime)); StartCoroutine(scaleBridge(tower.ScalePoints[1], ScaleDirection.PositiveZ, BridgeSpeed,maxBridgeWaitTime)); StartCoroutine(scaleBridge(tower.ScalePoints[2], ScaleDirection.NegativeX, BridgeSpeed,maxBridgeWaitTime)); StartCoroutine(scaleBridge(tower.ScalePoints[3], ScaleDirection.NegativeZ, BridgeSpeed,maxBridgeWaitTime)); } private IEnumerator scaleBridge(GameObject scalePoint, ScaleDirection direction, float scaleSpeed, float startRandomizer) { float randomWait = Random.Range(0, startRandomizer); yield return new WaitForSeconds(randomWait); scalePoint.SetActive(true); Vector3 scaleVector = Vector3.zero; if (direction == ScaleDirection.NegativeX || direction == ScaleDirection.PositiveX) { scaleVector = Vector3.right; scalePoint.transform.localScale = new Vector3(0, 1, 1); } else { scaleVector = Vector3.forward; scalePoint.transform.localScale = new Vector3(1, 1, 0); } Vector3 startScale = scalePoint.transform.localScale; float elapsedTime = 0; float animationTime = 10 / scaleSpeed; while (elapsedTime < animationTime) { float curvePercent = ScaleCurve.Evaluate((elapsedTime / animationTime)); scalePoint.gameObject.transform.localScale = UnclampedLerp(startScale, Vector3.one, curvePercent); elapsedTime += Time.deltaTime; yield return new WaitForEndOfFrame(); } scalePoint.transform.localScale = Vector3.one; } public static Vector3 UnclampedLerp(Vector3 a, Vector3 b, float t) { return t * b + (1 - t) * a; } private Bounds getWorldBounds(GameObject input) { Bounds retVal = new Bounds(input.transform.position, Vector3.zero); foreach (Renderer renderer in input.GetComponentsInChildren()) { retVal.Encapsulate(renderer.bounds); } return retVal; } private void MoveParent(GameObject input, Vector3 moveTo) { Vector3 movement = moveTo - input.transform.position; input.transform.position = moveTo; foreach (Transform child in input.transform) { child.position -= movement; } } #if UNITY_EDITOR public void AddBase(Transform input) { Base newBase = new Base(); GameObject Base = new GameObject(); Undo.RegisterCreatedObjectUndo(Base, "Created Base"); Base.transform.position = getWorldBounds(input.gameObject).center; Base.transform.parent = transform; Base.name = "Base" + Bases.Count; Undo.SetTransformParent(input.transform, Base.transform, "Created Base"); //newBaseObject.parent = Base.transform; newBase.gameObject = Base; Undo.RecordObject(this, "Created Base"); GameObject towerHolder = new GameObject(); towerHolder.transform.parent = Base.transform; towerHolder.transform.localPosition = Vector3.zero; towerHolder.name = "Tower Holder" + Bases.Count; newBase.tower = new Tower(); newBase.tower.gameObject = towerHolder; newBase.tower.TowerPieces = new List(); newBase.tower.ScalePoints = new GameObject[4]; for (int i = 0; i < 4; i++) { newBase.tower.ScalePoints[i] = new GameObject(); newBase.tower.ScalePoints[i].transform.parent = Base.transform; newBase.tower.ScalePoints[i].transform.localPosition = Vector3.zero; newBase.tower.ScalePoints[i].name = "ScalePoint" + Bases.Count + ", " + i; } Bases.Add(newBase); } public void AddTower(Base selectedBase, Transform[] input) { Undo.RecordObject(this, "Added Tower"); foreach (Transform towerObject in input) { if (towerObject == selectedBase.gameObject.transform) continue; if (selectedBase.tower.TowerPieces.Contains(towerObject.gameObject)) continue; selectedBase.tower.TowerPieces.Add(towerObject.gameObject); Undo.SetTransformParent(towerObject.transform, selectedBase.tower.gameObject.transform, "Added Tower"); } Undo.RecordObject(selectedBase.tower.gameObject, "Added Tower"); MoveParent(selectedBase.tower.gameObject, selectedBase.gameObject.transform.position + ((getWorldBounds(selectedBase.tower.gameObject).size.y) * Vector3.up)); selectedBase.tower.originalPos = selectedBase.tower.gameObject.transform.position; } public void AddBridge(Base selectedBase,ScaleDirection direction, Transform[] input) { foreach (Transform bridgeObject in input) { if (bridgeObject == selectedBase.gameObject) continue; if (selectedBase.tower.TowerPieces.Contains(bridgeObject.gameObject)) continue; Undo.SetTransformParent(bridgeObject.transform, selectedBase.tower.ScalePoints[(int)direction].transform, "Added Bridge"); } } public string[] GetBaseNames() { string[] retVal = new string[Bases.Count]; for (int i = 0; i < retVal.Length; i++) { retVal[i] = "Tower" + i; } return retVal; } #endif }