243 lines
7.4 KiB
C#
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);
|
|
}
|
|
}
|