Files
SXDMystery/Assets/_SXDMystery/Scripts/Task/FlyFollowToPlayer.cs
2025-12-09 18:15:19 +08:00

123 lines
3.0 KiB
C#

using UnityEngine;
using DG.Tweening;
/// <summary>
/// 物体飞到玩家面前 + 可选始终面向玩家 + 飞回原位
/// </summary>
public class FlyFollowToPlayer : MonoBehaviour
{
[Header("玩家摄像机")]
public Transform playerCamera;
[Header("停留距离")]
public float distance = 0.8f;
[Header("高度偏移")]
public float heightOffset = -0.1f;
[Header("平滑跟随速度")]
public float followSmooth = 6f;
[Header("视线锁定阈值(角度)")]
public float viewLockAngle = 5f;
[Header("是否始终面向玩家")]
public bool alwaysFacePlayer = true;
private bool isFlying = false;
private bool isFollow = false;
private Vector3 targetPos;
/// <summary>原始位置与旋转(回展台)</summary>
private Vector3 originPos;
private Quaternion originRot;
void Start()
{
originPos = transform.position;
originRot = transform.rotation;
}
void Update()
{
if (!isFollow) return;
// 计算目标位置(始终在视线前方)
targetPos = playerCamera.position
+ playerCamera.forward * distance
+ Vector3.up * heightOffset;
// 判断是否在视线正前
Vector3 dir = (transform.position - playerCamera.position).normalized;
float angle = Vector3.Angle(playerCamera.forward, dir);
// 已在视线范围内则停止位置修正,但如果需要朝向玩家,则继续朝向
if (angle >= viewLockAngle)
{
// 平滑移动
transform.position = Vector3.Lerp(
transform.position,
targetPos,
Time.deltaTime * followSmooth
);
}
// 是否面向玩家
if (alwaysFacePlayer)
{
transform.LookAt(playerCamera);
}
}
/// <summary>
/// 物体飞到玩家面前
/// </summary>
public void FlyToPlayer()
{
if (isFlying) return;
isFlying = true;
targetPos = playerCamera.position
+ playerCamera.forward * distance
+ Vector3.up * heightOffset;
transform.DOMove(targetPos, 1f)
.SetEase(Ease.OutBack)
.OnComplete(() =>
{
isFollow = true;
isFlying = false;
});
}
/// <summary>
/// 停止跟随玩家(不再更新位置)
/// </summary>
public void StopFollow()
{
isFollow = false;
}
/// <summary>
/// 物体飞回展台原位
/// </summary>
public void FlyBackToOrigin()
{
isFollow = false; // 停止跟随玩家
isFlying = true;
transform.DOKill(); // 停止其他动画,避免冲突
transform.DOMove(originPos, 1f)
.SetEase(Ease.InOutQuad);
transform.DORotateQuaternion(originRot, 1f)
.SetEase(Ease.InOutQuad)
.OnComplete(() =>
{
isFlying = false;
});
}
}