You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity LaserControl脚本激光粒子系统不生效仅LineRenderer显示问题

Unity LaserControl脚本粒子系统失效问题排查

核心故障点

  • 播放状态标记逻辑错误:现有代码用startParticlePlaying/endParticlePlaying两个自定义布尔值控制粒子播放触发,但该标记仅在松开射击键时重置。粒子系统按自身配置播放完一轮自动停止后,标记仍为true,后续帧不会再触发Play()调用,粒子直接停播。
  • 射线命中长度计算错误:当前计算LineRenderer终点的公式逻辑混乱,本地坐标系下向上发射的射线命中距离可直接通过RaycastHit2D.distance获取,原有公式算出的长度偏差极大,可能导致终点粒子被卡在碰撞体内部、或移出相机视域范围无法看见。
  • 坐标同步逻辑缺陷:直接修改粒子物体的世界坐标时,若粒子为当前激光物体的子物体、且粒子Simulation Space设为Local,坐标会叠加父物体偏移,最终粒子位置和预期的射击起点/命中点完全错位。
  • 缺失空引用校验:代码未在初始化阶段校验两个粒子系统的引用是否在Inspector面板正确赋值,一旦漏拖引用,调用Play()/Stop()时会抛出空引用异常,粒子逻辑直接中断,异常仅在控制台打印日志,极易被忽略。

修复后完整代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class LaserControl : MonoBehaviour
{
    public ParticleSystem LaserStartParticle;
    public ParticleSystem LaserEndParticle;
    public float lineLength = 36f;
    public int damage;
    public LayerMask layerMask;

    private LineRenderer Laser;
    private RaycastHit2D hit;

    void Start()
    {
        Laser = GetComponent<LineRenderer>();
        // 初始化校验引用,避免空引用
        if (LaserStartParticle == null || LaserEndParticle == null)
        {
            Debug.LogError("请在Inspector面板赋值激光粒子引用!");
            enabled = false;
            return;
        }
        // 强制粒子使用世界空间模拟,避免坐标偏移
        var startMain = LaserStartParticle.main;
        startMain.simulationSpace = ParticleSystemSimulationSpace.World;
        var endMain = LaserEndParticle.main;
        endMain.simulationSpace = ParticleSystemSimulationSpace.World;
    }

    void Update()
    {
        if (Input.GetButton("Fire1")) {
            ShootLaser();
        }
        else
        {
            Laser.enabled = false;
            Laser.SetPosition(1, new Vector3(0, lineLength, 0));
            // 直接调用停止,不需要额外标记
            LaserEndParticle.Stop(true);
            LaserStartParticle.Stop(true);
        }
    }

    void ShootLaser()
    {
        Laser.enabled = true;
        // 直接通过粒子系统自带的isPlaying判断状态,避免自定义标记不同步
        if (!LaserStartParticle.isPlaying)
        {
            LaserStartParticle.Play(true);
        }
        LaserStartParticle.transform.position = transform.position;

        hit = Physics2D.Raycast(transform.position, Vector2.up, lineLength, layerMask);
        if (hit)
        {
            Enemy enemy = hit.transform.GetComponent<Enemy>();
            if (enemy != null)
            {
                enemy.GetDamage(damage);
            }

            if (!LaserEndParticle.isPlaying)
            {
                LaserEndParticle.Play(true);
            }
            LaserEndParticle.transform.position = hit.point;
            // 直接用hit.distance设置LineRenderer本地终点坐标
            Laser.SetPosition(1, new Vector3(0, hit.distance, 0));
        }
        else
        {
            Laser.SetPosition(1, new Vector3(0, lineLength, 0));
            LaserEndParticle.Stop(true);
        }
    }
}

部署前额外检查项

  • 确认两个粒子系统的Play On Awake选项为关闭状态,避免场景加载时自动播放
  • 确认粒子材质挂载在相机可渲染的层级,未被其他碰撞体遮挡
  • 若需要持续射击时粒子持续显示,将两个粒子的Looping选项勾选,Duration设为大于等于0.5s即可
  • 确认LayerMask参数在Inspector中正确勾选了需要检测的碰撞层,避免射线检测失效导致终点粒子无法触发

内容的提问来源于stack exchange,提问作者Rogan Charlie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 00:48:24