/// --------------------------------------------- /// Behavior Designer /// Copyright (c) Opsive. All Rights Reserved. /// https://www.opsive.com /// --------------------------------------------- namespace Opsive.BehaviorDesigner.Samples { using Opsive.BehaviorDesigner.Samples.SceneManagers; using UnityEngine; /// /// Character controller for the turn based scene. /// public class TurnBaseCharacterController : MonoBehaviour { [Tooltip("The amount of time it takes for the projectile to spawn after attacking")] [SerializeField] protected float m_ProjectileSpawnDelay = 0.1f; [Tooltip("A prefab of the projectile that should be spawned when the character attacks.")] [SerializeField] protected GameObject m_Projectile; [Tooltip("The location that the projectile should spawn.")] [SerializeField] protected GameObject m_ProjectileSpawnLocation; [Tooltip("The amount of time it takes before the attack state should be reset.")] [SerializeField] protected float m_AttackResetDelay = 0.5f; [Tooltip("The color to flash the material. Set to clear to disable.")] [SerializeField] protected Color m_MaterialFlashColor = Color.clear; [Tooltip("The amount of time the material color should stay the flash color.")] [SerializeField] protected float m_MaterialFlashCooldownDelay = 0.01f; [Tooltip("The amount of time that the material color should be interpolated back to the original value.")] [SerializeField] protected float m_MaterialFlashDuration = 0.25f; private Animator m_Animator; private Health m_Health; private TurnBasedSceneManager m_TurnBasedSceneManager; private GameObject m_Target; private Material m_FlashMaterial; private Color m_OriginalColor; private Coroutine m_MaterialFlashCoroutine; /// /// Initializes the default values. /// private void Awake() { m_Animator = GetComponent(); m_Health = GetComponentInChildren(); m_Health.OnUpdateValue += OnUpdateHealthValue; #if UNITY_2022 m_TurnBasedSceneManager = Object.FindObjectOfType(); #else m_TurnBasedSceneManager = Object.FindFirstObjectByType(); #endif if (m_MaterialFlashColor != Color.clear) { m_FlashMaterial = GetComponent().material; } } /// /// The health value has been updated. /// /// The health value. private void OnUpdateHealthValue(float value) { if (value == 0) { // Death state. m_Animator.SetInteger("State", 2); // Game over. if (gameObject == m_TurnBasedSceneManager.Player) { Time.timeScale = 0; } } // Play a quick damage flash. if (m_FlashMaterial != null) { if (m_MaterialFlashCoroutine != null) { m_FlashMaterial.color = m_OriginalColor; StopCoroutine(FlashMaterial()); m_MaterialFlashCoroutine = null; } m_MaterialFlashCoroutine = StartCoroutine(FlashMaterial()); } } /// /// Flashes the material. /// private System.Collections.IEnumerator FlashMaterial() { m_OriginalColor = m_FlashMaterial.color; m_FlashMaterial.color = m_MaterialFlashColor; yield return new WaitForSeconds(m_MaterialFlashCooldownDelay); // Cooldown. var endTime = Time.time + m_MaterialFlashDuration; while (Time.time < endTime) { var color = Color.Lerp(m_OriginalColor, m_MaterialFlashColor, (endTime - Time.time) / m_MaterialFlashDuration); m_FlashMaterial.color = color; yield return new WaitForEndOfFrame(); } m_FlashMaterial.color = m_OriginalColor; m_MaterialFlashCoroutine = null; } /// /// Attacks the specified target. /// /// The target that should be attacked. public void Attack(GameObject target) { m_Target = target; m_Animator.SetInteger("State", 1); Invoke("SpawnProjectile", m_ProjectileSpawnDelay); Invoke("ResetState", m_AttackResetDelay); } /// /// Spawns the projectile. /// private void SpawnProjectile() { var projectileObj = Object.Instantiate(m_Projectile); projectileObj.transform.SetPositionAndRotation(m_ProjectileSpawnLocation.transform.position, m_ProjectileSpawnLocation.transform.rotation); if (transform.localScale.x < 0) { var scale = projectileObj.transform.localScale; scale.x *= -1; projectileObj.transform.localScale = scale; } Physics2D.IgnoreCollision(projectileObj.GetComponent(), GetComponent()); projectileObj.GetComponent().Initialize(m_Target); } /// /// Resets the animator state. /// private void ResetState() { m_Animator.SetInteger("State", 0); } /// /// The sprite has been selected. /// public void OnMouseDown() { if (m_Health.Value <= 0) { return; } m_TurnBasedSceneManager.SelectedCharacter(gameObject); } } }