Untitled

mail@pastecode.io avatar
unknown
plain_text
2 years ago
5.2 kB
3
Indexable
using DG.Tweening;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using UnityEditor;
using UnityEngine;
using static UnityEditor.PlayerSettings;

public class Trail
{
    public Vector3 pos;
    public Quaternion rot;

    public Trail(Vector3 _pos, Quaternion _rot)
    {
        pos = _pos;
        rot = _rot;
    }
}

public class PlayerMovement : MonoBehaviour
{
    [SerializeField]
    [Range(0, 2)]
    private float bodyDistance = 0.5f;
    [SerializeField]
    [Range(0.05f, 0.2f)]
    private float speedFrequency = 0.1f;
    [Range(0.05f, 0.2f)]
    private float rotationSpeed = 0.1f;

    private float interactionTime = 0.1f;
    private float maxAngle = 135f;

    private Transform tr;
    private Vector2 inputDir;
    private List<Transform> bodyPartsList;
    //Se utiliza para ir guardando las posiciones a las que va cada parte del cuerpo
    private Dictionary<int, List<Trail>> bodyPartsDic;
    private float timeElapsed;
    private bool newBodyAdded;
    private bool canRotate;

    private void Awake()
    {
        tr = transform;
        bodyPartsDic = new Dictionary<int, List<Trail>>();
    }

    private void Update()
    {
        timeElapsed += Time.deltaTime;
        if (timeElapsed >= interactionTime)
        {
            canRotate = true;
        }
    }

    public void StartMovement()
    {
        MoveHead();
    }

    public void SetMoveDirection(Vector2 _inputDir)
    {
        inputDir = _inputDir;
    }

    public void UpdateBodyParts(List<Transform> _bodyParts)
    {
        int indexPart = _bodyParts.Count - 1;
        int targetToFollow = _bodyParts.Count - 2;
        bodyPartsDic.Add(indexPart, new List<Trail>());
        bodyPartsList = _bodyParts;
        if (indexPart > 0)
        {
            Trail r = new Trail(bodyPartsList[indexPart].position, bodyPartsList[indexPart].rotation);
            bodyPartsDic[targetToFollow].Add(r);
            newBodyAdded = true;
        }
    }

    private void MoveHead()
    {
        tr.DOMove(tr.position + (tr.forward * bodyDistance), speedFrequency).SetEase(Ease.Linear).OnComplete(() =>
        {
            //si soy el único de la fila, no guardo mi posición
            if (bodyPartsList.Count > 1)
            {
                Trail r = new Trail(tr.position, tr.rotation);
                bodyPartsDic[0].Add(r);
            }
            if (newBodyAdded)
            {
                newBodyAdded = false;
                MoveBody(bodyPartsList[^1]);
            }
            if (canRotate)
            {
                CheckRotation();
            }
            MoveHead();
        });
    }


    private void CheckRotation()
    {
        Vector3 desiredDirection = new Vector3(Mathf.Round(inputDir.x), 0, Mathf.Round(inputDir.y));
        if (desiredDirection != Vector3.zero)
        {
            float angle = Vector3.Angle(tr.forward, desiredDirection);
            Quaternion desiredRot = Quaternion.identity;
            if (angle <= maxAngle && angle != 0)
            {
                if (desiredDirection == Vector3.forward)
                {
                    desiredRot = Quaternion.Euler(0, 0, 0);
                }
                else if (desiredDirection == Vector3.back)
                {
                    desiredRot = Quaternion.Euler(0, 180, 0);
                }
                else if (desiredDirection == Vector3.right)
                {
                    desiredRot = Quaternion.Euler(0, 90, 0);
                }
                else if (desiredDirection == Vector3.left)
                {
                    desiredRot = Quaternion.Euler(0, -90, 0);
                }
                tr.rotation = desiredRot;
                timeElapsed = 0;
                canRotate = false;
            }
        }
    }

    private void MoveBody(Transform bodyPart)
    {
        int bodyIndex = bodyPartsList.IndexOf(bodyPart);
        int targetToFollowIndex = bodyIndex - 1;
        if (bodyPartsDic.ContainsKey(bodyIndex))
        {
            bodyPart.DOMove(bodyPartsDic[targetToFollowIndex][0].pos, speedFrequency).SetEase(Ease.Linear).
                OnComplete(() => OnCompleteMoveBody(bodyPart, targetToFollowIndex));
        }
    }

    private void OnCompleteMoveBody(Transform bodyPart, int targetToFollowIndex)
    {
        bodyPartsDic[targetToFollowIndex].RemoveAt(0);
        //Si no soy el último de la fila, guardo mi posición
        if (bodyPartsList[^1] != bodyPart)
        {
            Trail r = new Trail(bodyPart.position, bodyPart.rotation);
            bodyPartsDic[targetToFollowIndex + 1].Add(r);
        }
        CheckBodyRotation(bodyPart, bodyPartsDic[targetToFollowIndex][0].rot);
        MoveBody(bodyPart);
    }

    private void CheckBodyRotation(Transform bodyPart, Quaternion targetToFollow)
    {
        if (bodyPart.rotation != targetToFollow)
        {
            bodyPart.DORotateQuaternion(targetToFollow, rotationSpeed).SetDelay(speedFrequency * 0.5f);
        }
    }
}