140 lines
5.2 KiB
C#
140 lines
5.2 KiB
C#
|
|
using System.Collections.Generic;
|
|||
|
|
using Lean.Pool;
|
|||
|
|
using Sirenix.OdinInspector;
|
|||
|
|
using UnityEngine;
|
|||
|
|
|
|||
|
|
namespace SLSUtilities.Effects
|
|||
|
|
{
|
|||
|
|
public class VFXRaycastInteraction : MonoBehaviour, IPoolable
|
|||
|
|
{
|
|||
|
|
[Header("核心设置")]
|
|||
|
|
[Tooltip("在特效生成时是否立刻启用渐变,注意,必须通过对象池生成。\n为true时,渐变效果从targetLight的默认intensity开始,否则需要调用EnableFade方法启用渐变")]
|
|||
|
|
public bool playOnSpawn = true;
|
|||
|
|
public float life = 1f;
|
|||
|
|
public List<float> checkPoints;
|
|||
|
|
public int currentCheckPointIndex = 0;
|
|||
|
|
public bool isEnabling = true;
|
|||
|
|
public Transform startPoint; // 刀尖的位置(用于发射射线)
|
|||
|
|
public LayerMask collisionLayers; // 地面图层
|
|||
|
|
public float rayLength = 0.5f; // 射线长度(稍微比刀刃离地距离长一点)
|
|||
|
|
|
|||
|
|
[Header("特效资源")]
|
|||
|
|
public GameObject sparkPrefab; // 火星特效 Prefab
|
|||
|
|
public GameObject decalPrefab; // 划痕 Decal Prefab
|
|||
|
|
|
|||
|
|
[HideInEditorMode]
|
|||
|
|
[SerializeField]
|
|||
|
|
private bool isFading;
|
|||
|
|
[HideInEditorMode]
|
|||
|
|
[SerializeField]
|
|||
|
|
private float time;
|
|||
|
|
private Vector3 _lastTipPosition;
|
|||
|
|
|
|||
|
|
private void Reset()
|
|||
|
|
{
|
|||
|
|
startPoint = transform;
|
|||
|
|
collisionLayers = LayerMask.GetMask("Wall", "Ground");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void OnSpawn()
|
|||
|
|
{
|
|||
|
|
if (playOnSpawn && !isEnabling)
|
|||
|
|
{
|
|||
|
|
isEnabling = true;
|
|||
|
|
time = 0f;
|
|||
|
|
currentCheckPointIndex = 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_lastTipPosition = startPoint.position;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void OnDespawn()
|
|||
|
|
{
|
|||
|
|
isEnabling = false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void Update()
|
|||
|
|
{
|
|||
|
|
time += Time.deltaTime;
|
|||
|
|
if (time >= life)
|
|||
|
|
{
|
|||
|
|
isEnabling = false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!isEnabling || Time.timeScale == 0 || checkPoints.Count == 0) return;
|
|||
|
|
|
|||
|
|
// 1. 计算刀尖速度方向(用于决定划痕朝向)
|
|||
|
|
Vector3 velocity = (startPoint.position - _lastTipPosition) / Time.deltaTime;
|
|||
|
|
_lastTipPosition = startPoint.position;
|
|||
|
|
|
|||
|
|
//1. 检查是否到达下一个检查点
|
|||
|
|
if (currentCheckPointIndex < checkPoints.Count)
|
|||
|
|
{
|
|||
|
|
if (time >= checkPoints[currentCheckPointIndex])
|
|||
|
|
{
|
|||
|
|
currentCheckPointIndex++;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
return; // 未到达检查点,跳过本次更新
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
return; // 所有检查点已处理完,跳过本次更新
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
// 2. 发射射线检测地面
|
|||
|
|
// 这里我们向下发射射线。如果你的游戏支持墙壁划痕,可以改为 velocity.normalized
|
|||
|
|
|
|||
|
|
RaycastHit hit;
|
|||
|
|
if (Physics.Raycast(startPoint.position, startPoint.forward, out hit, rayLength, collisionLayers))
|
|||
|
|
{
|
|||
|
|
SpawnEffects(hit, velocity);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void SpawnEffects(RaycastHit hit, Vector3 slashVelocity)
|
|||
|
|
{
|
|||
|
|
Vector3 projectedSlashDir = Vector3.ProjectOnPlane(slashVelocity, hit.normal).normalized;
|
|||
|
|
|
|||
|
|
// --- 处理火星 (Spark) ---
|
|||
|
|
if (sparkPrefab != null)
|
|||
|
|
{
|
|||
|
|
// 关键点:使用 Quaternion.LookRotation(hit.normal)
|
|||
|
|
// 这会让火星特效的 Z轴(发射方向)严格对准地面法线(垂直向上),right方向和挥动方向对齐
|
|||
|
|
LeanPool.Spawn(sparkPrefab, hit.point, Quaternion.LookRotation(hit.normal, Vector3.Cross(projectedSlashDir, hit.normal)));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// --- 处理划痕 (Decal) ---
|
|||
|
|
if (decalPrefab != null)
|
|||
|
|
{
|
|||
|
|
// 计算划痕的朝向:
|
|||
|
|
// 我们希望划痕贴在地面上(法线对齐 hit.normal)
|
|||
|
|
// 同时划痕的延伸方向要对齐刀的挥动方向(slashVelocity)
|
|||
|
|
if (projectedSlashDir != Vector3.zero)
|
|||
|
|
{
|
|||
|
|
// 计算 Decal 的旋转,Decal的forward和地面法线对齐,right方向和挥动方向对齐
|
|||
|
|
Quaternion decalRotation = Quaternion.LookRotation(hit.normal, Vector3.Cross(projectedSlashDir, hit.normal));
|
|||
|
|
|
|||
|
|
// 生成 Decal,稍微抬高一点点避免 Z-Fighting
|
|||
|
|
GameObject decal = LeanPool.Spawn(decalPrefab, hit.point + hit.normal * 0.01f, decalRotation);
|
|||
|
|
|
|||
|
|
// 记得在 Prefab 里设置自动销毁,或者在这里写 Destroy
|
|||
|
|
LeanPool.Despawn(decal, 5f);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 用于在 Scene 窗口调试射线,方便你调整 rayLength
|
|||
|
|
void OnDrawGizmos()
|
|||
|
|
{
|
|||
|
|
if (startPoint != null)
|
|||
|
|
{
|
|||
|
|
Gizmos.color = Color.yellow;
|
|||
|
|
Gizmos.DrawLine(startPoint.position, startPoint.position + transform.forward * rayLength);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|