ProjectDDD/Assets/_Datas/SLShared/SLUnity/UnitSytem/View/SLCamera.cs
2025-06-17 20:47:57 +09:00

471 lines
14 KiB (Stored with Git LFS)
C#

using System;
using System.Collections.Generic;
using Superlazy;
using UnityEngine;
public abstract class CameraOperation
{
public virtual Vector3 CenterDelta { get; } = Vector3.zero;
public virtual Vector3 OffsetDelta { get; } = Vector3.zero;
public virtual float DistDelta { get; } = 0;
public virtual float LatitudeDelta { get; } = 0;
public virtual float OffsetRotationDelta { get; } = 0;
public abstract bool IsEnd { get; }
public abstract void Play();
}
public class CameraZoom : CameraOperation
{
private readonly float fadeTime;
private readonly float fadeDelay;
private readonly float targetDist;
private float currentTime;
private float currentZoom;
private float zoomDelta;
public CameraZoom(float targetDist, float fadeTime, float fadeDelay)
{
this.fadeTime = fadeTime;
this.fadeDelay = fadeDelay;
currentTime = 0.0f;
targetDist = targetDist + SLGame.Session["CameraView"]["DestDistance"] - SLGame.Session["CameraView"]["DestDistance"];
this.targetDist = targetDist;
SLGame.Session["CameraView"]["DestDistance"] += targetDist;
}
public override float DistDelta => zoomDelta;
public override bool IsEnd => currentTime > fadeTime + fadeDelay;
public override void Play()
{
currentTime += Time.smoothDeltaTime;
if (currentTime - fadeDelay > 0 && currentTime - fadeDelay < fadeTime)
{
var t = Mathf.SmoothStep(0, 1, (currentTime - fadeDelay) / fadeTime);
zoomDelta = t * targetDist - currentZoom;
currentZoom = t * targetDist;
}
else if (currentTime - fadeDelay >= fadeTime)
{
zoomDelta = targetDist - currentZoom;
currentZoom = targetDist;
}
}
}
public class CameraMove : CameraOperation
{
private readonly Vector3 direction;
private readonly float fadeTime;
private readonly float fadeDelay;
private float currentTime;
private Vector3 currentCenter;
private Vector3 centerDelta;
public CameraMove(Vector3 direction, float fadeTime, float fadeDelay)
{
this.fadeTime = fadeTime;
this.fadeDelay = fadeDelay;
currentTime = 0.0f;
currentCenter = Vector3.zero;
this.direction = direction;
var cameraView = SLGame.Session["CameraView"];
var dest = cameraView["Dest"].ToVector3() + direction;
dest.x = Mathf.Clamp(dest.x, cameraView["MinX"], cameraView["MaxX"]);
dest.z = Mathf.Clamp(dest.z, cameraView["MinZ"], cameraView["MaxZ"]);
SLGame.Session["CameraView"]["Dest"] = dest.ToEntity();
}
public override Vector3 CenterDelta => centerDelta;
public override bool IsEnd => currentTime > fadeTime + fadeDelay;
public override void Play()
{
currentTime += Time.deltaTime;
if (currentTime - fadeDelay > 0 && currentTime - fadeDelay < fadeTime)
{
var t = (currentTime - fadeDelay) / fadeTime;
var newCenter = Vector3.Lerp(Vector3.zero, direction, t);
centerDelta = newCenter - currentCenter;
currentCenter = newCenter;
}
else if (currentTime - fadeDelay >= fadeTime)
{
centerDelta = direction - currentCenter;
currentCenter = direction;
}
}
}
public class CameraOffset : CameraOperation
{
private readonly Vector3 direction;
private readonly float fadeTime;
private readonly float fadeDelay;
private float currentTime;
private Vector3 currentCenter;
private Vector3 centerDelta;
public CameraOffset(Vector3 direction, float fadeTime, float fadeDelay)
{
this.fadeTime = fadeTime;
this.fadeDelay = fadeDelay;
currentTime = 0.0f;
currentCenter = Vector3.zero;
this.direction = direction;
var dest = SLGame.Session["CameraView"]["DestOffset"].ToVector3() + direction;
SLGame.Session["CameraView"]["DestOffset"] = dest.ToEntity();
}
public override Vector3 OffsetDelta => centerDelta;
public override bool IsEnd => currentTime > fadeTime + fadeDelay;
public override void Play()
{
currentTime += Time.smoothDeltaTime;
if (currentTime - fadeDelay > 0 && currentTime - fadeDelay < fadeTime)
{
var t = (currentTime - fadeDelay) / fadeTime;
var newCenter = Vector3.Slerp(Vector3.zero, direction, t);
centerDelta = newCenter - currentCenter;
currentCenter = newCenter;
}
else if (currentTime - fadeDelay >= fadeTime)
{
centerDelta = direction - currentCenter;
currentCenter = direction;
}
}
}
public class CameraShake : CameraOperation
{
private readonly Vector3 direction;
private readonly float fadeTime;
private readonly float fadeDelay;
private float currentTime;
private Vector3 currentCenter;
private Vector3 centerDelta;
private readonly int count;
public CameraShake(Vector3 direction, int count, float fadeTime, float fadeDelay)
{
this.fadeTime = fadeTime;
this.fadeDelay = fadeDelay;
this.count = count;
currentTime = 0.0f;
currentCenter = Vector3.zero;
this.direction = direction;
}
public override Vector3 CenterDelta => centerDelta;
public override bool IsEnd => currentTime > fadeTime + fadeDelay;
public override void Play()
{
currentTime += Time.smoothDeltaTime;
if (currentTime - fadeDelay > 0 && currentTime - fadeDelay < fadeTime)
{
var t = (currentTime - fadeDelay) / fadeTime * count;
var shakeAmount = direction.magnitude * (count - t);
var shakeDir = direction.normalized;
var shakeValue = Mathf.Cos((1 - t) * 360 * 2) * shakeAmount * shakeDir;
centerDelta = shakeValue - currentCenter;
currentCenter = shakeValue;
}
else if (currentTime - fadeDelay >= fadeTime)
{
centerDelta = direction - currentCenter;
currentCenter = direction;
}
}
}
public class CameraRotation : CameraOperation
{
private readonly float fadeTime;
private readonly float fadeDelay;
private float currentTime;
private float current;
private float currentDelta;
private readonly float delta;
public CameraRotation(float delta, float fadeTime, float fadeDelay)
{
this.fadeTime = fadeTime;
this.fadeDelay = fadeDelay;
currentTime = 0.0f;
this.delta = delta;
SLGame.Session["CameraView"]["DestOffsetRotation"] += delta;
}
public override float OffsetRotationDelta => current;
public override bool IsEnd => currentTime > fadeTime + fadeDelay;
public override void Play()
{
currentTime += Time.smoothDeltaTime;
if (currentTime - fadeDelay > 0 && currentTime - fadeDelay < fadeTime)
{
var t = (currentTime - fadeDelay) / fadeTime;
var tv = Mathf.Sin(t * Mathf.PI - Mathf.PI / 2) * 0.5f + 0.5f;
if (t < 0.5f)
{
t = Mathf.Pow(tv, 3);
}
else
{
t = 1 - Mathf.Pow(1 - tv, 3);
}
current = t * delta - currentDelta;
currentDelta = t * delta;
}
else if (currentTime - fadeDelay >= fadeTime)
{
current = delta - currentDelta;
currentDelta = current;
}
}
}
public class CameraLatitude : CameraOperation
{
private readonly float latitude;
private readonly float fadeTime;
private readonly float fadeDelay;
private readonly float targetLatitude;
private float currentTime;
private float currentLatitude;
private float latitudeDelta;
public CameraLatitude(float latitude, float fadeTime, float fadeDelay)
{
this.fadeTime = fadeTime;
this.fadeDelay = fadeDelay;
currentTime = 0.0f;
targetLatitude = latitude;
SLGame.Session["CameraView"]["DestLatitude"] += targetLatitude;
}
public override float LatitudeDelta => latitudeDelta;
public override bool IsEnd => currentTime > fadeTime + fadeDelay;
public override void Play()
{
currentTime += Time.smoothDeltaTime;
if (currentTime - fadeDelay > 0 && currentTime - fadeDelay < fadeTime)
{
var t = Mathf.SmoothStep(0, 1, (currentTime - fadeDelay) / fadeTime);
latitudeDelta = t * targetLatitude - currentLatitude;
currentLatitude = t * targetLatitude;
}
else if (currentTime - fadeDelay >= fadeTime)
{
latitudeDelta = targetLatitude - currentLatitude;
currentLatitude = targetLatitude;
}
}
}
public class SLCamera : MonoBehaviour
{
public static float minCameraDist = 0;
public static float maxCameraDist = 900;
public float latitude = 40;
public int longtitude = 40;
public float distance = 900;
public Vector3 center = Vector3.zero;
public Vector3 offset = Vector3.zero;
public float offsetRotation = 0;
private readonly List<CameraOperation> operations = new List<CameraOperation>();
private float cameraDist;
private Camera[] cams;
private readonly Transform background;
private string positionBind = string.Empty;
private int stopDist;
private int moveDist;
private Camera[] Cams
{
get
{
if (cams == null)
{
cams = GetComponentsInChildren<Camera>();
cameraDist = cams[0].farClipPlane;
}
return cams;
}
}
private void LateUpdate()
{
foreach (var op in operations)
{
op.Play();
center += op.CenterDelta;
distance += op.DistDelta;
latitude += op.LatitudeDelta;
offset += op.OffsetDelta;
offsetRotation += op.OffsetRotationDelta;
}
operations.RemoveAll(op => op.IsEnd);
if (operations.Count == 0)
{
center = SLGame.Session["CameraView"]["Dest"].ToVector3();
distance = SLGame.Session["CameraView"]["DestDistance"];
latitude = SLGame.Session["CameraView"]["DestLatitude"];
offset = SLGame.Session["CameraView"]["DestOffset"].ToVector3();
offsetRotation = SLGame.Session["CameraView"]["DestOffsetRotation"];
}
if (string.IsNullOrEmpty(positionBind) == false)
{
var destCenter = SLGame.SessionGet(positionBind).ToVector3();
var targetDist = moveDist;
if (destCenter == center) targetDist = stopDist;
center = destCenter;
SLGame.Session["CameraView"]["Dest"] = destCenter.ToEntity();
}
{
var mainCam = Cams[0];
var dist = distance;
if (mainCam.aspect < 1.77f/*16.0f/9.0f*/)
{
foreach (var cam in Cams)
{
cam.farClipPlane = 1.7777f / mainCam.aspect * cameraDist;
}
dist = dist * 1.7777f / mainCam.aspect;
}
else
{
foreach (var cam in Cams)
{
cam.farClipPlane = cameraDist;
}
}
{
var safeWidthtRate = Screen.width / Screen.safeArea.width;
var safeHeightRate = Screen.height / Screen.safeArea.height;
dist *= Mathf.Max(safeWidthtRate, safeHeightRate);
}
transform.SetPositionAndRotation(Quaternion.Euler(latitude, longtitude, 0) * Vector3.back * dist - transform.rotation * offset + center, Quaternion.Euler(latitude, longtitude + offsetRotation, 0));
SLGame.Session["CameraView"]["Center"] = center.ToEntity();
SLGame.Session["CameraView"]["Distance"] = distance;
SLGame.Session["CameraView"]["Offset"] = offset.ToEntity();
SLGame.Session["CameraView"]["Latitude"] = latitude;
SLGame.Session["CameraView"]["OffsetRotation"] = offsetRotation;
}
}
public void Play(CameraOperation op)
{
operations.Add(op);
}
private void Clear()
{
operations.Clear();
}
public void InitCamera(int latitude, int distance, Vector3 center, Vector3 offset)
{
Clear();
this.latitude = latitude;
this.distance = distance;
this.center = center;
this.offset = offset;
SLGame.Session["CameraView"]["Dest"] = this.center.ToEntity();
SLGame.Session["CameraView"]["Center"] = this.center.ToEntity();
SLGame.Session["CameraView"]["DestDistance"] = this.distance;
SLGame.Session["CameraView"]["Distance"] = this.distance;
SLGame.Session["CameraView"]["DestOffset"] = this.offset.ToEntity();
SLGame.Session["CameraView"]["Offset"] = this.offset.ToEntity();
SLGame.Session["CameraView"]["DestLatitude"] = this.latitude;
SLGame.Session["CameraView"]["Latitude"] = this.latitude;
SLGame.Session["CameraView"]["DestOffsetRotation"] = 0;
SLGame.Session["CameraView"]["OffsetRotation"] = 0;
SLGame.Session["CameraView"]["MinX"] = float.MinValue;
SLGame.Session["CameraView"]["MinZ"] = float.MinValue;
SLGame.Session["CameraView"]["MaxX"] = float.MaxValue;
SLGame.Session["CameraView"]["MaxZ"] = float.MaxValue;
}
public void AnchorBind(string anchorPosition, int stopDist, int moveDist, float zoomSpeed)
{
if (string.IsNullOrEmpty(anchorPosition))
{
positionBind = null;
}
else
{
positionBind = anchorPosition;
this.stopDist = stopDist;
this.moveDist = moveDist;
}
}
public void SetBound(float minX, float minZ, float maxX, float maxZ)
{
SLGame.Session["CameraView"]["MinX"] = minX;
SLGame.Session["CameraView"]["MinZ"] = minZ;
SLGame.Session["CameraView"]["MaxX"] = maxX;
SLGame.Session["CameraView"]["MaxZ"] = maxZ;
}
}