1
This commit is contained in:
@@ -4280,7 +4280,7 @@ MonoBehaviour:
|
||||
spawnList: []
|
||||
isCreateFish: 0
|
||||
isFrozen: 0
|
||||
debugSpawnFishNumber: 11023
|
||||
debugSpawnFishNumber: 12034
|
||||
isleft: 0
|
||||
debugSpawnAllLines: 0
|
||||
fishList_All: []
|
||||
@@ -4290,6 +4290,7 @@ MonoBehaviour:
|
||||
fishList_TS: []
|
||||
fishList_TS_Boss: []
|
||||
isResources: 0
|
||||
lineConflictCooldown: 1
|
||||
--- !u!114 &2075409202
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
@@ -1239,10 +1239,17 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
|
||||
if (MonsterMoveLine.dic_BezierCurveDatas.TryGetValue("鱼阵" + pathId, out var bd700))
|
||||
baseAngle = bd700.start.y > 0f ? 90f : -90f;
|
||||
|
||||
for (int i = 1; i <= 17; i++)
|
||||
// ⭐ 扇形:17 条(单数)以基准角为中心左右对称展开,总张角 150°;
|
||||
// 顺序从中间往两边:第1条在正中间(0°),之后依次 +step、-step 交替(保证左右对称)
|
||||
const int fanFishCount = 17;
|
||||
const float fanTotalAngle = 150f;
|
||||
float fanStep = fanTotalAngle / (fanFishCount - 1); // 150 / 16 = 9.375°
|
||||
|
||||
for (int i = 1; i <= fanFishCount; i++)
|
||||
{
|
||||
// 交替正负角度,形成扇形分布(从基准角向两侧±5°~±85°展开)
|
||||
float angle = i * 5f * (i % 2 == 0 ? -1f : 1f);
|
||||
// i=1→0°, 2→+9.375°, 3→-9.375°, 4→+18.75°, 5→-18.75° … 16→+75°, 17→-75°
|
||||
float mag = (i / 2) * fanStep;
|
||||
float angle = i <= 1 ? 0f : (i % 2 == 0 ? mag : -mag);
|
||||
// ⭐ 方向判断与原始flipY700一致:路线起点start.y<0的阵绕鱼头轴翻面180°
|
||||
// (鱼头方向不变,肚背朝向翻转);原始写法为 transform.Rotate(Z,180,Space.Self)
|
||||
float flipZ = (bd700 != null && bd700.start.y < 0f) ? 180f : 0f;
|
||||
@@ -1272,7 +1279,7 @@ public class CreateFishManager : MonoSingleton<CreateFishManager>
|
||||
mc.Init(pathId.ToString(), cfg.times, true, yz.arrayNumber);
|
||||
|
||||
// ⭐ 鱼阵调试日志:输出每条子鱼生成后的旋转与缩放(排查"有的正有的反")
|
||||
Debug.Log($"[鱼阵调试] 阵={yz.arrayNumber}(扇形700) pathId={pathId} 第{i}/{16}条 guid={mc.guid} " +
|
||||
Debug.Log($"[鱼阵调试] 阵={yz.arrayNumber}(扇形700) pathId={pathId} 第{i}/{fanFishCount}条 guid={mc.guid} " +
|
||||
$"rotation={fish.transform.eulerAngles.ToString("F1")} localScale={fish.transform.localScale.ToString("F3")}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,53 +1,125 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Unity.VisualScripting;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 纵向循环滚动背景(所有直接子物体按顺序当作背景图,第一个在最上面)。
|
||||
///
|
||||
/// 适配不同机型的做法:背景大小仍由子物体上的 BgFit 按屏幕铺满,这里不自己算缩放,
|
||||
/// 而是在“第一帧”(BgFit 缩放完成后)读出背景的真实世界高度,用它来定间距:
|
||||
/// 间距 = 真实图高 - 2像素
|
||||
/// 间距和图高永远同一个来源,所以不管什么分辨率/宽高比,接缝都不会张开露黑。
|
||||
/// 另外位置按整像素对齐、底部留余量并跟随相机,运行中不会出现黑线。
|
||||
/// </summary>
|
||||
public class BGManager : MonoBehaviour
|
||||
{
|
||||
//private float height;
|
||||
public Vector3 upV3;
|
||||
public Vector3 centerV3;
|
||||
public Vector3 downV3;
|
||||
private float currHeight;
|
||||
public float speed;
|
||||
public float height;
|
||||
// Start is called before the first frame update
|
||||
[Header("滚动")]
|
||||
[Tooltip("背景向下滚动的速度(世界单位/秒)")]
|
||||
public float speed = 3f;
|
||||
|
||||
[Header("拼接(消除黑线)")]
|
||||
[Tooltip("相邻两张背景的重叠像素:留一点重叠,接缝就不会因取整/采样露黑")]
|
||||
public float overlapPixels = 2f;
|
||||
[Tooltip("背景底部相对屏幕下边缘多留的比例,避免镜头抖动时露黑")]
|
||||
public float bottomMargin = 0.05f;
|
||||
[Tooltip("位置按整像素对齐:接缝只会落在像素边界上,画面更稳(参考工程的背景也是这样)")]
|
||||
public bool snapToPixel = true;
|
||||
|
||||
// —— 运行时数据 ——
|
||||
public float height; // 单张背景缩放后的真实世界高度
|
||||
private float spacing; // 相邻背景间距(整像素对齐)= 图高 - 重叠
|
||||
private float unitsPerPixel; // 1 个屏幕像素等于多少世界单位
|
||||
private float marginWorld; // 底部余量(世界单位,整像素对齐)
|
||||
private float offset; // 累计滚动距离
|
||||
private bool layoutReady;
|
||||
private readonly List<Transform> tiles = new List<Transform>();
|
||||
private readonly List<float> pivotToBottom = new List<float>(); // pivot 到底边的世界距离
|
||||
private readonly List<float> pivotToLeft = new List<float>(); // pivot 到左边的世界距离
|
||||
|
||||
void Start()
|
||||
{
|
||||
//设置背景布局
|
||||
//height = Screen.height*3;
|
||||
upV3 = Vector3.up * Screen.height*2;
|
||||
centerV3 = Vector3.up * Screen.height;
|
||||
downV3 = Vector3.zero;
|
||||
upV3 = CoordinateTransformation.ScreenToCamera(upV3);
|
||||
centerV3 = CoordinateTransformation.ScreenToCamera(centerV3);
|
||||
downV3 = CoordinateTransformation.ScreenToCamera(downV3);
|
||||
transform.GetChild(0).position = upV3;
|
||||
transform.GetChild(1).position = centerV3;
|
||||
transform.GetChild(2).position = downV3;
|
||||
height = upV3.y - centerV3.y;
|
||||
tiles.Clear();
|
||||
foreach (Transform child in transform) tiles.Add(child);
|
||||
}
|
||||
// Update is called once per frame
|
||||
|
||||
/// 第一帧执行:此时 BgFit 已把每张背景缩放到铺满屏幕,读出来的高度才是最终值。
|
||||
/// 记录每张背景 pivot 到底边/左边的距离,摆放时按底边、左边对齐,
|
||||
/// 这样以后换图(pivot 不是左下角)也不会错位。
|
||||
void CacheLayout()
|
||||
{
|
||||
Camera cam = Camera.main;
|
||||
if (cam == null) return;
|
||||
|
||||
float visibleH = cam.orthographicSize * 2f; // 相机可见高度(随屏幕自适应)
|
||||
unitsPerPixel = visibleH / Mathf.Max(Screen.height, 1);
|
||||
|
||||
float minTileH = float.MaxValue;
|
||||
pivotToBottom.Clear();
|
||||
pivotToLeft.Clear();
|
||||
foreach (Transform t in tiles)
|
||||
{
|
||||
float minY = 0f;
|
||||
float minX = 0f;
|
||||
SpriteRenderer sr = t.GetComponent<SpriteRenderer>();
|
||||
if (sr != null && sr.sprite != null)
|
||||
{
|
||||
Vector3 scale = t.lossyScale;
|
||||
minTileH = Mathf.Min(minTileH, sr.bounds.size.y); // 真实图高:间距以它为准
|
||||
minY = sr.sprite.bounds.min.y * scale.y;
|
||||
minX = sr.sprite.bounds.min.x * scale.x;
|
||||
}
|
||||
pivotToBottom.Add(minY);
|
||||
pivotToLeft.Add(minX);
|
||||
}
|
||||
|
||||
height = minTileH == float.MaxValue ? visibleH : minTileH;
|
||||
|
||||
// 间距 = 图高 - 重叠,并按整像素取整(保证每张背景的边都在像素线上)
|
||||
float overlapWorld = overlapPixels * unitsPerPixel;
|
||||
float spacingPixels = Mathf.Round((height - overlapWorld) / unitsPerPixel);
|
||||
spacing = Mathf.Max(spacingPixels, 1f) * unitsPerPixel;
|
||||
marginWorld = Mathf.Round(bottomMargin * Screen.height) * unitsPerPixel;
|
||||
|
||||
layoutReady = true;
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
float step = Time.deltaTime * speed;
|
||||
currHeight += step;
|
||||
foreach (Transform t in transform)
|
||||
if (tiles.Count == 0) return;
|
||||
if (!layoutReady) CacheLayout();
|
||||
if (!layoutReady || spacing <= 0f) return;
|
||||
|
||||
Camera cam = Camera.main;
|
||||
if (cam == null) return;
|
||||
|
||||
offset += speed * Time.deltaTime;
|
||||
|
||||
// 当前格子内的位移(0 ~ spacing)与已经滚过的格子数。
|
||||
// 位移取整像素后所有背景共用同一个值,间距不会被各自取整破坏。
|
||||
float phase = Snap(offset - Mathf.Floor(offset / spacing) * spacing);
|
||||
int step = Mathf.FloorToInt(offset / spacing);
|
||||
|
||||
// 基准点:屏幕左下角,再往下留 bottomMargin,跟随相机(镜头震动也不会露边)
|
||||
float leftX = Snap(cam.transform.position.x - cam.orthographicSize * cam.aspect);
|
||||
float bottomY = Snap(cam.transform.position.y - cam.orthographicSize) - marginWorld;
|
||||
|
||||
int n = tiles.Count;
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
t.Translate(Vector3.down * step);
|
||||
// 第 1 个子物体在最上面,初始占第 (n-1-i) 格;滚出屏幕后回到最上面
|
||||
int slot = (n - 1 - i) - step;
|
||||
slot = ((slot % n) + n) % n;
|
||||
|
||||
Vector3 p = tiles[i].position;
|
||||
p.x = leftX + pivotToLeft[i];
|
||||
p.y = bottomY + pivotToBottom[i] + slot * spacing - phase;
|
||||
tiles[i].position = p;
|
||||
}
|
||||
|
||||
if (currHeight > height*1.3f)
|
||||
{
|
||||
|
||||
currHeight -= height;
|
||||
Vector3 v3 = transform.GetChild(2).position;
|
||||
v3.y += height*3;
|
||||
transform.GetChild(2).position= v3;
|
||||
transform.GetChild(2).SetAsFirstSibling();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// 世界坐标吸附到屏幕像素
|
||||
float Snap(float world)
|
||||
{
|
||||
if (!snapToPixel || unitsPerPixel <= 0f) return world;
|
||||
return Mathf.Round(world / unitsPerPixel) * unitsPerPixel;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user