Files
ScienceLab.TypesOfMotion/Assets/Scripts/ChildAnimController.cs
2026-02-18 00:08:49 +02:00

243 lines
7.4 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using UnityEngine.UI;
public class ChildAnimController : MonoBehaviour
{
[Header("Animations")]
[SerializeField] private string idleAnimation1 = "idle_m_2_220f";
[SerializeField] private string idleAnimation2 = "idle_selfcheck_1_300f";
[SerializeField] private string walkAnimation = "locom_m_basicWalk_30f";
[SerializeField] private string talkingAnimation = "idle_phoneTalking_180f";
[Header("Movement Points")]
[SerializeField] private Transform targetPoint1;
[SerializeField] private Transform targetPoint2;
[Header("Light Check")]
[SerializeField] private LightManager lightManager;
[SerializeField] private int requiredLights = 9;
[SerializeField] private string successMessage = "×óäîâî! Ïðåçåíòóé ïåðåä êëàñîì ñâîþ äóìêó!";
[SerializeField] private string failMessage = "Òè ùå íå çàâåðøèâ çàâäàííÿ, ñïðîáóé ùå!";
[Header("Movement Settings")]
[SerializeField] private float walkSpeed = 1f;
[SerializeField] private float waitTime = 3f;
[SerializeField] private float rotationSpeed = 5f;
[SerializeField] private float gravity = 9.81f;
[SerializeField] private float stopDistance = 0.25f;
[Header("Dialogue Settings")]
[SerializeField] private float talkDuration = 7f;
[SerializeField] private float interactionCooldown = 10f;
[SerializeField] private float textHeight = 1f;
[SerializeField] private GameObject existingCanvas;
[SerializeField] private TextMeshProUGUI existingTextMesh;
private Animator _animator;
private CharacterController _characterController;
private bool _isTalking;
private bool _canInteract = true;
private float _verticalVelocity;
private Transform _player;
private Coroutine _walkRoutine;
private void Start()
{
_animator = GetComponent<Animator>();
_characterController = GetComponent<CharacterController>();
if (_characterController == null)
{
_characterController = gameObject.AddComponent<CharacterController>();
_characterController.height = 1f;
_characterController.radius = 0.3f;
_characterController.center = new Vector3(0f, 0.5f, 0f);
}
if (existingCanvas != null)
{
existingCanvas.transform.SetParent(transform);
existingCanvas.transform.localPosition = new Vector3(0f, textHeight, 0f);
existingCanvas.SetActive(false);
}
_walkRoutine = StartCoroutine(WalkRoutine());
}
private void Update()
{
if (existingCanvas != null && existingCanvas.activeSelf)
{
Camera cam = Camera.main;
if (cam != null)
{
Vector3 dir = existingCanvas.transform.position - cam.transform.position;
if (dir != Vector3.zero)
existingCanvas.transform.rotation = Quaternion.LookRotation(dir);
}
}
}
private IEnumerator WalkRoutine()
{
while (true)
{
if (_isTalking)
{
yield return null;
continue;
}
PlayAnimation(idleAnimation1);
yield return new WaitForSeconds(waitTime);
if (targetPoint1 != null)
{
yield return WalkToPoint(targetPoint1.position);
yield return TurnToFaceDirection(targetPoint2 != null ? targetPoint2.position : transform.forward);
}
if (_isTalking) continue;
PlayAnimation(idleAnimation2);
yield return new WaitForSeconds(waitTime);
if (targetPoint2 != null)
{
yield return WalkToPoint(targetPoint2.position);
yield return TurnToFaceDirection(targetPoint1 != null ? targetPoint1.position : transform.forward);
}
}
}
private IEnumerator WalkToPoint(Vector3 targetPosition)
{
PlayAnimation(walkAnimation);
while (true)
{
if (_isTalking) yield break;
Vector3 fromXZ = new Vector3(transform.position.x, 0f, transform.position.z);
Vector3 toXZ = new Vector3(targetPosition.x, 0f, targetPosition.z);
float dist = Vector3.Distance(fromXZ, toXZ);
if (dist <= stopDistance)
{
_verticalVelocity = -0.5f;
yield break;
}
Vector3 dir = (toXZ - fromXZ).normalized;
if (dir != Vector3.zero)
{
Quaternion look = Quaternion.LookRotation(dir);
transform.rotation = Quaternion.Slerp(transform.rotation, look, rotationSpeed * Time.deltaTime);
}
if (_characterController.isGrounded)
_verticalVelocity = -0.5f;
else
_verticalVelocity -= gravity * Time.deltaTime;
Vector3 move = dir * walkSpeed;
move.y = _verticalVelocity;
_characterController.Move(move * Time.deltaTime);
yield return null;
}
}
private IEnumerator TurnToFaceDirection(Vector3 targetPosition)
{
Vector3 dir = targetPosition - transform.position;
dir.y = 0f;
if (dir == Vector3.zero) yield break;
Quaternion targetRot = Quaternion.LookRotation(dir.normalized);
while (Quaternion.Angle(transform.rotation, targetRot) > 1f)
{
if (_isTalking) yield break;
transform.rotation = Quaternion.Slerp(transform.rotation, targetRot, rotationSpeed * Time.deltaTime);
yield return null;
}
}
private void OnTriggerEnter(Collider other)
{
if (!other.CompareTag("Player")) return;
if (!_canInteract) return;
if (_isTalking) return;
_player = other.transform;
StartCoroutine(TalkToPlayer());
}
private IEnumerator TalkToPlayer()
{
_isTalking = true;
_canInteract = false;
if (_walkRoutine != null)
StopCoroutine(_walkRoutine);
if (_player != null)
{
Vector3 dir = _player.position - transform.position;
dir.y = 0f;
if (dir != Vector3.zero)
transform.rotation = Quaternion.LookRotation(dir.normalized);
}
PlayAnimation(talkingAnimation);
if (existingTextMesh != null)
{
if (lightManager != null && lightManager.CurrentLights >= requiredLights)
existingTextMesh.text = successMessage;
else
existingTextMesh.text = failMessage;
}
if (existingCanvas != null)
existingCanvas.SetActive(true);
yield return new WaitForSeconds(talkDuration);
EndTalk();
}
private void EndTalk()
{
if (existingCanvas != null)
existingCanvas.SetActive(false);
_isTalking = false;
StartCoroutine(CooldownRoutine());
_walkRoutine = StartCoroutine(WalkRoutine());
}
private IEnumerator CooldownRoutine()
{
yield return new WaitForSeconds(interactionCooldown);
_canInteract = true;
}
private void PlayAnimation(string animationName)
{
if (_animator == null) return;
if (string.IsNullOrEmpty(animationName)) return;
_animator.CrossFade(animationName, 0.2f);
}
}