Hola, estoy programando un juego de Pokémon en Unity y, al facilitarme el trabajo haciendo un sistema de simulación personalizado, al programarlo y probarlo, las animaciones del personaje son muy rápidas. No sé si me faltará algún Time.deltaTime o algo así.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CharacterAnimator : MonoBehaviour
{
[SerializeField] List<Sprite> walkDownSprites;
[SerializeField] List<Sprite> walkUpSprites;
[SerializeField] List<Sprite> walkRightSprites;
[SerializeField] List<Sprite> walkLeftSprites;
//parameters
public float MoveX {get; set; }
public float MoveY {get; set; }
public bool IsMoving {get; set; }
//states
SpriteAnimator walkDownAnim;
SpriteAnimator walkUpAnim;
SpriteAnimator walkRightAnim;
SpriteAnimator walkLeftAnim;
SpriteAnimator currentAnim;
bool wasPreviouslyMoving;
SpriteRenderer spriteRenderer;
private void Start()
{
spriteRenderer = GetComponent<SpriteRenderer>();
walkDownAnim = new SpriteAnimator(walkDownSprites, spriteRenderer);
walkUpAnim = new SpriteAnimator(walkUpSprites, spriteRenderer);
walkRightAnim = new SpriteAnimator(walkRightSprites, spriteRenderer);
walkLeftAnim = new SpriteAnimator(walkLeftSprites, spriteRenderer);
currentAnim = walkDownAnim;
}
private void Update()
{
var prevAnim = currentAnim;
if(MoveX == 1)
currentAnim = walkRightAnim;
else if(MoveX == -1)
currentAnim = walkLeftAnim;
else if (MoveY == 1)
currentAnim = walkUpAnim;
else if (MoveY == -1)
currentAnim = walkDownAnim;
if(currentAnim != prevAnim || wasPreviouslyMoving != IsMoving )
currentAnim.Start();
if(IsMoving)
currentAnim.HandleUpdate();
else
spriteRenderer.sprite = currentAnim.Frames[0];
wasPreviouslyMoving = IsMoving;
}
}
//Distinto script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerScript : MonoBehaviour
{
public LayerMask solidObjectsLayer;
public LayerMask interactableLayer;
public float moveSpeed;
private bool isMoving;
private Vector2 input;
private CharacterAnimator animator;
public VectorValue startingPosition;
private void Awake()
{
animator = GetComponent<CharacterAnimator>();
}
private void Start()
{
transform.position = startingPosition.initialValue;
}
public void HandleUpdate()
{
if (!isMoving)
{
input.x = Input.GetAxisRaw("Horizontal");
input.y = Input.GetAxisRaw("Vertical");
if (input.x != 0) input.y = 0;
if (input != Vector2.zero)
{
animator.MoveX = input.x;
animator.MoveY = input.y;
var targetPos = transform.position;
targetPos.x += input.x;
targetPos.y += input.y;
if(isWalkable(targetPos))
StartCoroutine(Move(targetPos));
}
}
animator.IsMoving = isMoving;
if (Input.GetKeyDown(KeyCode.E))
Interact();
}
IEnumerator Move(Vector3 targetPos)
{
isMoving = true;
while ((targetPos - transform.position).sqrMagnitude > Mathf.Epsilon)
{
transform.position = Vector3.MoveTowards(transform.position, targetPos, moveSpeed * Time.deltaTime);
yield return null;
}
transform.position = targetPos;
isMoving = false;
}
private void Interact()
{
var facingDir = new Vector3(animator.MoveX, animator.MoveY);
var interactPos = transform.position + facingDir;
Debug.DrawLine(transform.position, interactPos, Color.green, 1f);
var collider = Physics2D.OverlapCircle(interactPos, 0.3f, interactableLayer);
if(collider != null)
{
collider.GetComponent<Interactable>()?.Interact();
}
}
private bool isWalkable(Vector3 targetPos)
{
if(Physics2D.OverlapCircle(targetPos, 0.01f, solidObjectsLayer | interactableLayer) != null)
{
return false;
}
return true;
}
}
//distinto script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpriteAnimator : MonoBehaviour
{
SpriteRenderer spriteRenderer;
List<Sprite> frames;
float frameRate;
int currentFrame;
float timer;
public SpriteAnimator(List<Sprite> frames, SpriteRenderer spriteRenderer, float frameRate = 0.16f)
{
this.frames = frames;
this.spriteRenderer = spriteRenderer;
this.frameRate = frameRate;
}
public void Start()
{
currentFrame = 0;
timer = 0f;
spriteRenderer.sprite = frames[0];
}
public void HandleUpdate()
{
timer += Time.deltaTime;
if(timer < frameRate)
{
currentFrame = (currentFrame + 1) % frames.Count;
spriteRenderer.sprite = frames[currentFrame];
timer -= frameRate;
}
}
public List<Sprite> Frames
{
get{ return frames; }
}
}