using System.Collections; using System.Collections.Generic; using UnityEngine; using DG.Tweening; using TMPro; public class PlayerController : MonoBehaviour { [SerializeField] private Joystick joystick; [SerializeField] private CharacterController controller; [SerializeField] private Animator anim; [SerializeField] private Camera mainCam; [SerializeField] private GameObject targetIndicator; [SerializeField] private ParticleSystem movementEffect; [SerializeField] private ParticleSystem dissolveFX; [SerializeField] private AudioSource collectAudioSrc; [SerializeField] private AudioSource chaseAudioSrc; [SerializeField] private float speed; [SerializeField] private float gravity; private Vector3 _moveDirection; // private List _bulletStorage; [SerializeField] private Vector3 emojiSpacing = new (0, 3.3f, 0); [SerializeField] private GameObject box, player, bag; [SerializeField] private TMP_Text scoreEffect; // TODO: Script needs better clearance & organization!! [SerializeField] private Transform hudParent; [SerializeField] private Transform animationParent; [SerializeField] private CashIcon cashEffect; public List Emojis_list_1; // Inside box public List Emojis_list_2; // Running public List Emojis_list_3; // Busted private GameObject _activeEmoji; public bool IsSafe { get; private set; } private Coroutine _emojiCoroutineBox; private Coroutine _emojiCoroutinePlayer; private Coroutine _emojiCoroutineRun; private int _currentEmojiIndex; private Vector3 _emojiPosition; private bool _isEmojiCoroutineRunning; private bool _startState; private bool _angryState; private bool _isChased; private static readonly int Moving = Animator.StringToHash("Moving"); private GameManager _manager; private GameManager Manager { get { if (_manager == null) _manager = GameManager.Instance; return _manager; } } private void Start() { _isChased = false; player.SetActive(true); box.SetActive(false); } private void Update() { if (Manager.IsGameOver) return; var direction = joystick.Direction; if (controller.isGrounded) { _moveDirection = new Vector3(-direction.x, 0, -direction.y); var targetRotation = _moveDirection != Vector3.zero ? Quaternion.LookRotation(_moveDirection) : transform.rotation; transform.rotation = targetRotation; _moveDirection *= speed; } var deltaTime = Time.deltaTime; _moveDirection.y -= gravity * deltaTime; controller.Move(_moveDirection * deltaTime); var isMoving = direction != Vector2.zero; if (anim.GetBool(Moving) != isMoving) { anim.SetBool(Moving, isMoving); _startState = true; } _emojiPosition = transform.position + emojiSpacing; UpdateEmojiPosition(deltaTime); if (_startState) Emoji_Popup(isMoving); } private void UpdateEmojiPosition(float inDeltaTime) { if (_activeEmoji == null) return; if (!_isEmojiCoroutineRunning) return; _activeEmoji.transform.position = Vector3.Lerp(_activeEmoji.transform.position, _emojiPosition, inDeltaTime * 100f); } private void Emoji_Popup(bool isMoving) { var cameraRotation = mainCam.transform.rotation; if (!isMoving) { if (_emojiCoroutinePlayer != null) { StopCoroutine(_emojiCoroutinePlayer); _emojiCoroutinePlayer = null; HideActiveEmoji(); } if (!_isEmojiCoroutineRunning) { _emojiCoroutineBox = StartCoroutine(DelayedEmojiAppearance(Emojis_list_1, _emojiPosition, cameraRotation, 0.5f, 4f, 0.5f, 5f)); } movementEffect.Stop(); player.SetActive(false); bag.SetActive(false); box.SetActive(true); } else { if (_emojiCoroutineBox != null) { StopCoroutine(_emojiCoroutineBox); _emojiCoroutineBox = null; HideActiveEmoji(); } if (_isChased) { if (!_angryState) { if (_emojiCoroutinePlayer != null) { StopCoroutine(_emojiCoroutinePlayer); _emojiCoroutinePlayer = null; HideActiveEmoji(); } _angryState = true; } if (!_isEmojiCoroutineRunning) { _emojiCoroutineRun = StartCoroutine(DelayedEmojiAppearance(Emojis_list_3, _emojiPosition, cameraRotation, 0.1f, 2f, 0.5f, 2f)); } } else { if (!_isEmojiCoroutineRunning) { _emojiCoroutinePlayer = StartCoroutine(DelayedEmojiAppearance(Emojis_list_2, _emojiPosition, cameraRotation, 0.1f, 3f, 0.5f, 5f)); } } movementEffect.Play(); player.SetActive(true); bag.SetActive(true); box.SetActive(false); } } private IEnumerator DelayedEmojiAppearance(List emojiList, Vector3 position, Quaternion cameraRotation, float delayIn, float delayOut, float duration, float exitDelay) { _isEmojiCoroutineRunning = true; _currentEmojiIndex = (_currentEmojiIndex + 1) % emojiList.Count; _activeEmoji = emojiList[_currentEmojiIndex]; _activeEmoji.transform.position = position; yield return new WaitForSeconds(delayIn); _activeEmoji.SetActive(true); _activeEmoji.transform.localScale = Vector3.zero; _activeEmoji.transform.DOScale(Vector3.one, duration).SetEase(Ease.InOutQuad); _activeEmoji.transform.DOMoveY(position.y, duration).SetEase(Ease.InOutQuad); _activeEmoji.transform.rotation = Quaternion.LookRotation(cameraRotation * Vector3.forward, cameraRotation * Vector3.up); yield return new WaitForSeconds(delayOut); HideActiveEmoji(); } private void HideActiveEmoji() { if (_activeEmoji == null) return; _activeEmoji.transform.DOScale(Vector3.zero, .1f) .OnComplete(() => { _activeEmoji.SetActive(false); _activeEmoji = null; _isEmojiCoroutineRunning = false; }) .SetEase(Ease.InOutQuad); } public void SwitchSafeState(bool isSafe) { IsSafe = isSafe; targetIndicator.SetActive(!isSafe); } public void ActivateChaseState() { if (_isChased) return; _isChased = true; chaseAudioSrc.Play(); } /*public void DisableBullet(GameObject targetBullet) { targetBullet.SetActive(false); _bulletStorage.Add(targetBullet); }*/ public void OnTriggerEnter(Collider other) { if (other.CompareTag("Obstacle")) { var obstaclePosition = other.transform.position; var scoreTextEffect = Instantiate(scoreEffect, obstaclePosition, Quaternion.identity); // Cash Icon animation. var viewPosition = mainCam.WorldToViewportPoint(obstaclePosition); var icon = Instantiate(cashEffect, hudParent); icon.BindData(viewPosition, animationParent.position); icon.ShowUpAnimation(); icon.MoveUpAnimation(); other.enabled = false; collectAudioSrc.Play(); Manager.UpdateScore(); dissolveFX.gameObject.transform.position = obstaclePosition; var cameraRotation = mainCam.transform.rotation; scoreTextEffect.transform.rotation = Quaternion.LookRotation(cameraRotation * Vector3.forward, cameraRotation * Vector3.up); scoreTextEffect.transform.localScale = Vector3.zero; scoreTextEffect.DOFade(1f, 0.2f); scoreTextEffect.transform .DOScale(Vector3.one, 0.2f) .SetEase(Ease.InOutQuad); scoreTextEffect.transform.DOMoveY(obstaclePosition.y + 2.5f, 0.2f) .SetEase(Ease.InOutQuad) .OnComplete(() => { scoreTextEffect.DOFade(0f, 0.8f) .OnComplete(() => Destroy(scoreTextEffect.gameObject)); }); dissolveFX.Play(); other.gameObject.transform.DOMove(transform.position, 0.2f); other.gameObject.transform.DOScale(Vector3.zero, 0.2f) .SetEase(Ease.OutCubic) .OnComplete(() => Destroy(other.gameObject)); return; } if (other.gameObject.CompareTag("car")) { Manager.EscapeLevel(); HideActiveEmoji(); gameObject.SetActive(false); // Destroy(gameObject); return; } } }