116 lines
3.9 KiB
C#

using System.Collections;
using UnityEngine;
namespace RR.Game2D.Core
{
public class CameraFollow2D : MonoBehaviour
{
[Header("Follow")]
[SerializeField, Min(0)] private float damping = 1.5f;
[SerializeField] private Vector2 offset = new(2f, 1f);
[SerializeField] private bool faceLeft;
[Header("Behaviour")]
[SerializeField] private bool snapOnFound = true;
private Transform player;
private float lastX;
private Coroutine bindRoutine;
void OnEnable()
{
offset = new Vector2(Mathf.Abs(offset.x), offset.y);
bindRoutine = StartCoroutine(BindLoop());
}
void OnDisable()
{
if (bindRoutine != null) { StopCoroutine(bindRoutine); bindRoutine = null; }
}
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>
private 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 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;
}
}
}