Danro/Assets/Scripts/Behaviour/Camera/CameraFollow.cs

116 lines
4.0 KiB
C#

using System.Collections;
using UnityEngine;
namespace RR.Game2D.Core
{
public class CameraFollow : MonoBehaviour
{
[Header("Follow")]
[SerializeField, Min(0)] protected float damping = 1.5f;
[SerializeField] protected Vector2 offset = new(2f, 1f);
[SerializeField] protected bool faceLeft;
[Header("Behaviour")]
[SerializeField] protected bool snapOnFound = true;
protected Transform player;
//private float lastX;
protected Coroutine bindRoutine;
private void OnEnable()
{
offset = new Vector2(Mathf.Abs(offset.x), offset.y);
bindRoutine = StartCoroutine(BindLoop());
}
private void OnDisable()
{
if (bindRoutine != null) { StopCoroutine(bindRoutine); bindRoutine = null; }
}
private void FixedUpdate()
{
if (!player) return; // ждём появления
float currentX = player.position.x;
//if (currentX > lastX + 0.01f) faceLeft = false;
//else if (currentX < lastX - 0.01f) faceLeft = true;
faceLeft = Mathf.Abs(player.localEulerAngles.y) >= 180 ? true : false;
//lastX = currentX;
Vector3 target = player.position;
target.x += faceLeft ? -offset.x : +offset.x;
target.y += offset.y;
target.z = transform.position.z;
transform.position = Vector3.Lerp(transform.position, target, damping * Time.deltaTime);
}
/// <summary>
/// Цикл привязки камеры к игроку. Ищет игрока на сцене.
/// </summary>
private IEnumerator BindLoop()
{
while (true)
{
if (!player)
{
var t = ResolvePlayer();
if (t)
{
player = t;
//lastX = player.position.x;
if (snapOnFound) SnapToPlayer(faceLeft);
}
}
yield return null; // подождём кадр
}
}
/// <summary>
/// Метод для поиска объекта игрока.
/// Сначала ищет экземпляр объекта игрока в GameManager,
/// затем, ели не нашел, то ищет по тегу на сцене
/// </summary>
/// <returns>Transform playerPosition - позиция игрокка</returns>
protected virtual Transform ResolvePlayer()
{
if (GameManager.Instance && GameManager.Instance.PlayerObj)
return GameManager.Instance.PlayerObj.transform;
var go = GameObject.FindWithTag("Player");
return go ? go.transform : null;
}
/// <summary>
/// Метод для поиска игрока и привязки к нему камеры.
/// </summary>
/// <param name="playerFaceLeft">Повернут ли игрок налево</param>
public virtual void FindPlayer(bool playerFaceLeft)
{
faceLeft = playerFaceLeft;
player = ResolvePlayer();
if (!player)
{
Debug.Log("CameraFollow2D: player not found yet, will wait.");
return;
}
//lastX = player.position.x;
SnapToPlayer(faceLeft);
}
/// <summary>
/// Метод для привязки камеры к игроку.
/// </summary>
/// <param name="playerFaceLeft">Повернут ли игрок налево</param>
private void SnapToPlayer(bool playerFaceLeft)
{
if (!player) return;
Vector3 p = player.position;
p.x += (playerFaceLeft ? -offset.x : offset.x);
p.y += offset.y;
p.z = transform.position.z;
transform.position = p;
}
}
}