1
This commit is contained in:
@@ -0,0 +1,260 @@
|
||||
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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user