Files
5.24BuYu/Assets/MyGame/Scripts/JiGuangControl.cs
T
2026-10-14 19:39:24 +08:00

261 lines
11 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 激光静态工具类:激光实例的创建/朝向/长度计算,不依赖组件实例。
/// 调用方自行持有激光实例列表(fxList)、基准缩放(fxBaseScale)和长度校正值(lengthCorrect),
/// 创建后每帧调用 JiGuangDirection/JiGuangLength 刷新。
/// 起点支持 Transform / Vector3 两种;Z 轴重载:
/// - 不带 z 参数 → 直接读取起点/目标对象自身的 Z
/// - 带 z 参数 → 强制起点和终点都使用指定 Z(如战神激光统一压到 -50 显示层)
/// </summary>
public static class JiGuangControl
{
// ==================== 创建 ====================
/// <summary>按目标数量创建激光实例(克隆预制体,挂到 parent 下)。生成位置读取起点对象自身的 Z</summary>
public static void JiGuangCreate(GameObject prefab, Transform start, List<Transform> targets, List<Transform> fxList, Transform parent = null)
{
if (start == null) return;
JiGuangCreateCore(prefab, start.position, targets, fxList, parent, null);
}
/// <summary>同上,但生成位置强制使用指定 Z</summary>
public static void JiGuangCreate(GameObject prefab, Transform start, List<Transform> targets, List<Transform> fxList, Transform parent, float z)
{
if (start == null) return;
JiGuangCreateCore(prefab, start.position, targets, fxList, parent, z);
}
/// <summary>起点直接给坐标(如战神激光的动态炮口位置)。生成位置读取 startPos 自身的 Z</summary>
public static void JiGuangCreate(GameObject prefab, Vector3 startPos, List<Transform> targets, List<Transform> fxList, Transform parent = null)
{
JiGuangCreateCore(prefab, startPos, targets, fxList, parent, null);
}
/// <summary>同上,但生成位置强制使用指定 Z</summary>
public static void JiGuangCreate(GameObject prefab, Vector3 startPos, List<Transform> targets, List<Transform> fxList, Transform parent, float z)
{
JiGuangCreateCore(prefab, startPos, targets, fxList, parent, z);
}
/// <summary>
/// 多起点创建:startPositions 与 targets 一一对应(每条激光独立起点),
/// 生成位置强制使用指定 Z。起点数量不足时复用最后一个起点。
/// (如战神激光:第0条=座位点+偏移的主起点,第1/2条=散射左右父对象起点)
/// </summary>
public static void JiGuangCreate(GameObject prefab, List<Vector3> startPositions, List<Transform> targets, List<Transform> fxList, Transform parent, float z)
{
if (prefab == null || startPositions == null || startPositions.Count == 0
|| targets == null || fxList == null)
return;
for (int i = 0; i < fxList.Count; i++)
if (fxList[i] != null)
Object.Destroy(fxList[i].gameObject);
fxList.Clear();
for (int i = 0; i < targets.Count; i++)
{
if (targets[i] == null) continue;
Vector3 spawnPos = startPositions[Mathf.Min(i, startPositions.Count - 1)];
spawnPos.z = z;
GameObject go = Object.Instantiate(prefab, spawnPos, Quaternion.identity, parent);
go.name = prefab.name + "_" + i;
fxList.Add(go.transform);
}
}
private static void JiGuangCreateCore(GameObject prefab, Vector3 startPos, List<Transform> targets, List<Transform> fxList, Transform parent, float? forcedZ)
{
if (prefab == null || targets == null || fxList == null)
return;
for (int i = 0; i < fxList.Count; i++)
if (fxList[i] != null)
Object.Destroy(fxList[i].gameObject);
fxList.Clear();
for (int i = 0; i < targets.Count; i++)
{
if (targets[i] == null) continue;
Vector3 spawnPos = startPos;
if (forcedZ.HasValue)
spawnPos.z = forcedZ.Value;
GameObject go = Object.Instantiate(prefab, spawnPos, Quaternion.identity, parent);
go.name = prefab.name + "_" + i;
fxList.Add(go.transform);
}
}
// ==================== 朝向 ====================
/// <summary>刷新激光朝向:直接读取起点/目标对象自身的 Z</summary>
public static void JiGuangDirection(Transform start, List<Transform> targets, List<Transform> fxList)
{
if (start == null) return;
JiGuangDirectionCore(start.position, targets, fxList, null);
}
/// <summary>刷新激光朝向:起点和终点强制使用指定 Z(同层)</summary>
public static void JiGuangDirection(Transform start, List<Transform> targets, List<Transform> fxList, float z)
{
if (start == null) return;
JiGuangDirectionCore(start.position, targets, fxList, z);
}
/// <summary>刷新激光朝向(起点为坐标):直接使用 startPos 自身的 Z</summary>
public static void JiGuangDirection(Vector3 startPos, List<Transform> targets, List<Transform> fxList)
{
JiGuangDirectionCore(startPos, targets, fxList, null);
}
/// <summary>刷新激光朝向(起点为坐标):起点和终点强制使用指定 Z(同层)</summary>
public static void JiGuangDirection(Vector3 startPos, List<Transform> targets, List<Transform> fxList, float z)
{
JiGuangDirectionCore(startPos, targets, fxList, z);
}
/// <summary>
/// 多起点朝向:startPositions 与 targets/fxList 一一对应(每条激光独立起点),
/// 起点和终点强制使用指定 Z(同层)。起点数量不足时复用最后一个起点。
/// rotateZ:激光预制体自带的 Z 轴旋转(偏移),绕世界 Z 轴叠加在计算朝向上——
/// 预制体上转 Z = 激光在平面内整体旋转(手动修正角度用);X/Y 不参与,保证激光不会甩出平面。
/// </summary>
public static void JiGuangDirection(List<Vector3> startPositions, List<Transform> targets, List<Transform> fxList, float z, float rotateZ)
{
if (startPositions == null || startPositions.Count == 0
|| targets == null || fxList == null || fxList.Count == 0)
return;
int fxIndex = 0;
for (int i = 0; i < targets.Count; i++)
{
if (targets[i] == null) continue;
if (fxIndex >= fxList.Count) break;
Vector3 startPos = startPositions[Mathf.Min(i, startPositions.Count - 1)];
Vector3 endPos = targets[i].position;
startPos.z = z;
endPos.z = z;
Vector3 dir = endPos - startPos;
if (dir.sqrMagnitude > 0.0001f)
fxList[fxIndex].rotation = Quaternion.Euler(0f, 0f, rotateZ) * Quaternion.LookRotation(dir);
fxIndex++;
}
}
private static void JiGuangDirectionCore(Vector3 startPos, List<Transform> targets, List<Transform> fxList, float? forcedZ)
{
if (targets == null || fxList == null || fxList.Count == 0)
return;
int fxIndex = 0;
for (int i = 0; i < targets.Count; i++)
{
if (targets[i] == null) continue;
if (fxIndex >= fxList.Count) break;
Vector3 endPos = targets[i].position;
if (forcedZ.HasValue)
{
startPos.z = forcedZ.Value;
endPos.z = forcedZ.Value;
}
Vector3 dir = endPos - startPos;
if (dir.sqrMagnitude > 0.0001f)
fxList[fxIndex].rotation = Quaternion.LookRotation(dir);
fxIndex++;
}
}
// ==================== 长度 ====================
/// <summary>刷新激光长度(按基准缩放拉伸 Z 轴):直接读取起点/目标对象自身的 Z</summary>
public static void JiGuangLength(Transform start, List<Transform> targets, List<Transform> fxList, Vector3 fxBaseScale, float lengthCorrect = 1f)
{
if (start == null) return;
JiGuangLengthCore(start.position, targets, fxList, fxBaseScale, lengthCorrect, null);
}
/// <summary>刷新激光长度:起点和终点强制使用指定 Z(同层)</summary>
public static void JiGuangLength(Transform start, List<Transform> targets, List<Transform> fxList, Vector3 fxBaseScale, float lengthCorrect, float z)
{
if (start == null) return;
JiGuangLengthCore(start.position, targets, fxList, fxBaseScale, lengthCorrect, z);
}
/// <summary>刷新激光长度(起点为坐标):直接使用 startPos 自身的 Z</summary>
public static void JiGuangLength(Vector3 startPos, List<Transform> targets, List<Transform> fxList, Vector3 fxBaseScale, float lengthCorrect = 1f)
{
JiGuangLengthCore(startPos, targets, fxList, fxBaseScale, lengthCorrect, null);
}
/// <summary>刷新激光长度(起点为坐标):起点和终点强制使用指定 Z(同层)</summary>
public static void JiGuangLength(Vector3 startPos, List<Transform> targets, List<Transform> fxList, Vector3 fxBaseScale, float lengthCorrect, float z)
{
JiGuangLengthCore(startPos, targets, fxList, fxBaseScale, lengthCorrect, z);
}
/// <summary>
/// 多起点长度:startPositions 与 targets/fxList 一一对应(每条激光独立起点),
/// 起点和终点强制使用指定 Z(同层)。起点数量不足时复用最后一个起点。
/// </summary>
public static void JiGuangLength(List<Vector3> startPositions, List<Transform> targets, List<Transform> fxList, Vector3 fxBaseScale, float lengthCorrect, float z)
{
if (startPositions == null || startPositions.Count == 0
|| targets == null || fxList == null || fxList.Count == 0)
return;
int fxIndex = 0;
for (int i = 0; i < targets.Count; i++)
{
if (targets[i] == null) continue;
if (fxIndex >= fxList.Count) break;
Vector3 startPos = startPositions[Mathf.Min(i, startPositions.Count - 1)];
Vector3 endPos = targets[i].position;
startPos.z = z;
endPos.z = z;
float distance = (endPos - startPos).magnitude;
Vector3 scale = fxBaseScale;
scale.z = distance * fxBaseScale.z * lengthCorrect;
fxList[fxIndex].localScale = scale;
fxIndex++;
}
}
private static void JiGuangLengthCore(Vector3 startPos, List<Transform> targets, List<Transform> fxList, Vector3 fxBaseScale, float lengthCorrect, float? forcedZ)
{
if (targets == null || fxList == null || fxList.Count == 0)
return;
int fxIndex = 0;
for (int i = 0; i < targets.Count; i++)
{
if (targets[i] == null) continue;
if (fxIndex >= fxList.Count) break;
Vector3 endPos = targets[i].position;
if (forcedZ.HasValue)
{
startPos.z = forcedZ.Value;
endPos.z = forcedZ.Value;
}
float distance = (endPos - startPos).magnitude;
Vector3 scale = fxBaseScale;
scale.z = distance * fxBaseScale.z * lengthCorrect;
fxList[fxIndex].localScale = scale;
fxIndex++;
}
}
}