système laser rotatif

Pour les scripts écrits en C#
Règles du forum
Merci de respecter la NOMENCLATURE suivante pour vos TITRES de messages :

Commencez par le niveau de vos scripts
DB = Débutant
MY = Moyen
CF = Confirmé

Puis le domaine d'application
-RS = Réseau
-AL = Algorithmie

Exemple :

[DB-RS] Mouvement perso multijoueur
Avatar de l’utilisateur
Kaloverian
Messages : 369
Inscription : 10 Août 2016 03:03

système laser rotatif

Message par Kaloverian » 12 Juin 2025 18:08

bonjour,

Voici 4 scripts C sharp afin d'établir un système "laser in dotted lines" rotatif:

DirectionPrefab.cs

Code : Tout sélectionner

using UnityEngine;
using System; // Required for [Serializable]

// DirectionPrefab.cs
[Serializable]
public class DirectionPrefab
{
    [Tooltip("The base direction for the tube emitted from the multi-source (relative to spawner's forward).")]
    public Vector3 direction;

    [Tooltip("The specific tube prefab to use for this direction.")]
    public GameObject tubePrefab;
}
TubeInfoRotateConique.cs

Code : Tout sélectionner

using UnityEngine;

// TubeInfoRotateConique.cs
public class TubeInfoRotateConique
{
    public GameObject tubeGameObject;
    public Vector3 baseRelativeDirection; // Direction relative to the spawner's local space
    public Vector3 currentAbsoluteDirection; // World space direction after spawner's rotation
    public float speed;
    public int currentBounces;
    public int maxBouncesLimit;
    public int recursionLevel;
    public Vector3 initialSpawnPosition;
    public bool hasReflected;

    private float _distanceTraveled;

    public TubeInfoRotateConique(GameObject go, Vector3 baseDir, float spd, int bnc, int maxBnc, int recLevel, Vector3 spawnPos)
    {
        tubeGameObject = go;
        baseRelativeDirection = baseDir;
        currentAbsoluteDirection = Vector3.zero;
        speed = spd;
        currentBounces = bnc;
        maxBouncesLimit = maxBnc;
        recursionLevel = recLevel;
        initialSpawnPosition = spawnPos;
        hasReflected = false;
        _distanceTraveled = 0f;
    }

    public void UpdateDistance(float deltaTime)
    {
        _distanceTraveled += speed * deltaTime;
    }

    public Vector3 GetWorldPosition(Transform spawnerTransform)
    {
        // Calculate world position based on spawner's rotation and position
        Vector3 localPoint = baseRelativeDirection.normalized * _distanceTraveled;
        return spawnerTransform.TransformPoint(localPoint);
    }

    public Vector3 GetWorldDirection(Transform spawnerTransform)
    {
        // Calculate world direction based on spawner's rotation
        return spawnerTransform.TransformDirection(baseRelativeDirection.normalized);
    }
}
MultiLaserSpawnerRotateConique.cs:

Code : Tout sélectionner

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

public class MultiLaserSpawnerRotateConique : MonoBehaviour
{
    // --- Configuration générale des tubes (reçue de LaserInfinyRotateConique) ---
    private float _speed;
    private float _spawnInterval;
    private float _laserLength;

    // --- Référence au script principal LaserInfinyRotateConique ---
    private LaserInfinyRotateConique _mainLaserScript;
    private int _currentRecursionLevel;

    // --- Liste des tubes actuellement actifs pour ce spawner ---
    private List<TubeInfoRotateConique> _spawnedTubes = new List<TubeInfoRotateConique>();

    // --- État d'initialisation du spawner ---
    private bool _isInitialized = false;

    // Paramètres pour la rotation longitudinale (Lacet) continue
    private bool _enableContinuousLongitudinalRotation;
    private float _continuousLongitudinalRotationSpeed;
    private float _currentContinuousLongitudeAngle = 0f; // Angle de lacet actuel pour la rotation continue

    // Paramètres pour l'Oscillation Angulaire Calculée
    private bool _enableAngularOscillation;
    private float _oscillationSpeed; // Vitesse angulaire de l'oscillation en degrés par seconde
    private Quaternion _oscillationTargetRotation; // La rotation FromTo (du début à la fin de l'oscillation)
    private float _oscillationAngularMagnitude; // L'amplitude angulaire réelle de l'oscillation en degrés

    private float _oscillationTimer = 0f; // Compteur pour la fonction d'oscillation PingPong

    /// <summary>
    /// Initialise le MultiLaserSpawnerRotateConique avec les paramètres nécessaires.
    /// </summary>
    public void Init(
        LaserInfinyRotateConique mainScript,
        float spd,
        float interval,
        Vector3 initialPos,
        int recLevel,
        bool enableLongRot,
        float longRotSpeed,
        bool enableAngularOsc,      // Indique si l'oscillation angulaire est activée
        float oscSpeedPerSec,       // Vitesse de l'oscillation en deg/sec
        Quaternion oscTargetRot     // La rotation cible pour l'oscillation
    )
    {
        _mainLaserScript = mainScript;
        _speed = spd;
        _spawnInterval = interval;
        _currentRecursionLevel = recLevel;
        _laserLength = mainScript.laserLength;

        transform.position = initialPos;
        _currentContinuousLongitudeAngle = 0f; // Le lacet continu démarre à 0

        _enableContinuousLongitudinalRotation = enableLongRot;
        _continuousLongitudinalRotationSpeed = longRotSpeed;

        _enableAngularOscillation = enableAngularOsc;
        _oscillationSpeed = oscSpeedPerSec; // Stocke la vitesse en deg/sec
        _oscillationTargetRotation = oscTargetRot;

        if (_enableAngularOscillation)
        {
            // Calcule l'amplitude angulaire totale de la rotation d'oscillation
            _oscillationAngularMagnitude = Quaternion.Angle(Quaternion.identity, _oscillationTargetRotation);

            // Si l'amplitude angulaire est très petite, désactiver l'oscillation
            // pour éviter une division par zéro ou un mouvement insignifiant et potentiellement très rapide.
            if (_oscillationAngularMagnitude < 0.01f) // Utilisez un petit seuil (0.01 degrés)
            {
                _enableAngularOscillation = false; // Désactive l'oscillation pour ce spawner
                Debug.LogWarning($"[MultiLaserSpawnerRotateConique] Oscillation désactivée pour ce spawner car le déplacement angulaire cible est trop petit ({_oscillationAngularMagnitude:F4} degrés).");
            }
        }
        else
        {
            _oscillationAngularMagnitude = 0f; // S'assurer que la magnitude est 0 si l'oscillation est désactivée
        }

        // Commence à faire apparaître les tubes de manière répétée
       // InvokeRepeating(nameof(SpawnTube), 0f, _spawnInterval);//avant
        InvokeRepeating(nameof(SpawnTube), 0.001f, _spawnInterval); // Ajout d'un petit délai initial pour la synchronisation
        _isInitialized = true;

        Debug.Log($"[MultiLaserSpawnerRotateConique] Initialisé à {transform.position}. Spawning tubes every {_spawnInterval} seconds. Recursion Level: {_currentRecursionLevel}.");
        Debug.Log($"[MultiLaserSpawnerRotateConique] Rotation: Longitudinale Continue Activée={_enableContinuousLongitudinalRotation} (Vitesse: {_continuousLongitudinalRotationSpeed}). Oscillation Angulaire Activée={_enableAngularOscillation} (Vitesse: {_oscillationSpeed:F2} deg/sec, Magnitude Angulaire: {_oscillationAngularMagnitude:F2} deg).");
    }

    /// <summary>
    /// Crée un nouveau tube à partir de ce spawner.
    /// </summary>
    void SpawnTube()
    {
        if (!_isInitialized)
        {
            Debug.LogWarning("[MultiLaserSpawnerRotateConique] Tentative de 'SpawnTube' avant l'initialisation. Le spawner n'est pas initialisé.");
            return;
        }

        Vector3 initialBaseDirection;
        GameObject currentTubePrefab;

        if (_mainLaserScript.directionPrefabs != null && _mainLaserScript.directionPrefabs.Length > 0)
        {
            // Cycle à travers les préfabriqués de direction en fonction du nombre de tubes apparus par CE spawner
            int index = (_spawnedTubes.Count) % _mainLaserScript.directionPrefabs.Length;
            LaserInfinyRotateConique.DirectionPrefab dp = _mainLaserScript.directionPrefabs[index]; // Notez le 'LaserInfinyRotateConique.' ici

            // --- UTILISATION DE CartesianDirection ICI ---
            initialBaseDirection = dp.CartesianDirection;
            currentTubePrefab = dp.tubePrefab;

            if (currentTubePrefab == null)
            {
                Debug.LogError($"[MultiLaserSpawnerRotateConique] Le préfabriqué de tube est null pour l'index de direction {index} dans LaserInfinyRotateConique. Veuillez l'assigner dans l'Inspector.");
                CancelInvoke(nameof(SpawnTube)); // Arrête l'apparition si le préfabriqué est manquant
                return;
            }
        }
        else
        {
            Debug.LogError("[MultiLaserSpawnerRotateConique] _mainLaserScript.directionPrefabs est null ou vide. Impossible de faire apparaître le tube. Assurez-vous qu'il est configuré dans LaserInfinyRotateConique.");
            CancelInvoke(nameof(SpawnTube)); // Arrête l'apparition s'il n'y a pas de préfabriqués de direction
            return;
        }

        Vector3 spawnPosition = transform.position;
        GameObject tubeGO = Instantiate(currentTubePrefab, spawnPosition, Quaternion.identity);

        // Crée un nouvel objet TubeInfoRotateConique pour gérer le tube apparu
        TubeInfoRotateConique newTube = new TubeInfoRotateConique(tubeGO, initialBaseDirection, _speed, 0, 0, _currentRecursionLevel, spawnPosition);
        _spawnedTubes.Add(newTube);
    }

    /// <summary>
    /// Appelé une fois par frame. Manages spawner rotation and tube movement/destruction.
    /// </summary>
    void Update()
    {
        if (!_isInitialized) return;

        // Commence avec la rotation d'identité pour accumuler les rotations
        Quaternion totalRotation = Quaternion.identity;

        // --- Applique la rotation longitudinale (Lacet) continue si activée ---
        if (_enableContinuousLongitudinalRotation)
        {
            _currentContinuousLongitudeAngle += _continuousLongitudinalRotationSpeed * Time.deltaTime;
            _currentContinuousLongitudeAngle = Mathf.Repeat(_currentContinuousLongitudeAngle, 360f); // Garde l'angle entre 0-360
            totalRotation *= Quaternion.Euler(0, _currentContinuousLongitudeAngle, 0);
        }

        // --- Applique l'oscillation angulaire calculée si activée ---
        if (_enableAngularOscillation)
        {
            // Calcul de la progression du timer pour que l'oscillation ait une vitesse angulaire constante.
            // Le timer PingPong varie de 0 à 1 puis de 1 à 0, pour une durée totale de 2 unités de timer par cycle.
            // La vitesse _oscillationSpeed est en degrés/sec. L'amplitude totale est _oscillationAngularMagnitude (deg).
            // Le temps pour parcourir l'amplitude dans un sens est _oscillationAngularMagnitude / _oscillationSpeed.
            // Le timer doit progresser de 1.0f / (temps pour un sens) par seconde.
            _oscillationTimer += (_oscillationSpeed / _oscillationAngularMagnitude) * Time.deltaTime;

            // normalizedProgress ira de 0.0 (début) à 1.0 (fin de course), puis reviendra à 0.0
            float normalizedProgress = Mathf.PingPong(_oscillationTimer, 1.0f);

            // Slerp interpole entre la rotation d'identité (point de départ)
            // et la rotation cible calculée (_oscillationTargetRotation)
            Quaternion currentOscillationRotation = Quaternion.Slerp(Quaternion.identity, _oscillationTargetRotation, normalizedProgress);

            // Applique la rotation d'oscillation en plus des rotations précédentes
            totalRotation *= currentOscillationRotation;
        }

        // Applique la rotation totale au spawner
        transform.localRotation = totalRotation;

        // --- Débogage Visuel pour l'orientation du spawner ---
        Debug.DrawRay(transform.position, transform.forward * 5f, Color.yellow, 0.1f);
        Debug.DrawRay(transform.position, transform.up * 5f, Color.cyan, 0.1f);

        // --- Gère le Mouvement et la Destruction des Tubes ---
        for (int k = _spawnedTubes.Count - 1; k >= 0; k--)
        {
            TubeInfoRotateConique tube = _spawnedTubes[k];
            // Vérifie si l'objet tube ou les informations sont devenus null inopinément
            if (tube == null || tube.tubeGameObject == null)
            {
                Debug.Log($"[MultiLaserSpawnerRotateConique] TubeInfoRotateConique ou GameObject à l'index {k} était null, suppression de la liste.");
                _spawnedTubes.RemoveAt(k);
                continue;
            }

            tube.UpdateDistance(Time.deltaTime); // Met à jour la distance parcourue
            tube.tubeGameObject.transform.position = tube.GetWorldPosition(transform); // Met à jour la position mondiale du tube
            tube.tubeGameObject.transform.up = tube.GetWorldDirection(transform); // Oriente le tube le long de sa direction
            tube.currentAbsoluteDirection = tube.GetWorldDirection(transform); // Stocke la direction mondiale actuelle

            // Détruit le tube s'il dépasse la limite de longueur du laser
            if (Vector3.Distance(tube.tubeGameObject.transform.position, tube.initialSpawnPosition) > _laserLength * 1.5f)
            {
                Debug.Log($"[MultiLaserSpawnerRotateConique] Le tube '{tube.tubeGameObject.name}' a dépassé la longueur maximale du laser, destruction.");
                Destroy(tube.tubeGameObject);
                _spawnedTubes.RemoveAt(k); // Supprime de la liste
            }
        }

        // Détruit le spawner lui-même s'il n'a plus de tubes et ne fait plus apparaître
        if (_isInitialized && _spawnedTubes.Count == 0 && !IsInvoking(nameof(SpawnTube)))
        {
            Debug.Log($"[MultiLaserSpawnerRotateConique] Tous les tubes de ce spawner ont été détruits et aucune apparition n'est plus programmée. Destruction de l'objet GameObject du spawner : {gameObject.name}.");
            Destroy(gameObject);
        }
    }

    /// <summary>
    /// Appelé lorsque le GameObject est désactivé ou détruit.
    /// Annule toutes les invocations restantes et détruit les tubes apparus pour éviter les fuites.
    /// </summary>
    void OnDisable()
    {
        CancelInvoke(); // Arrête tous les appels InvokeRepeating en attente
        // Détruit tous les tubes apparus par ce spawner
        foreach (var tubeInfo in _spawnedTubes)
        {
            if (tubeInfo != null && tubeInfo.tubeGameObject != null)
            {
                Destroy(tubeInfo.tubeGameObject);
            }
        }
        _spawnedTubes.Clear(); // Vide la liste
    }
}
LaserInfinyRotateConique.cs:

Code : Tout sélectionner

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

public class LaserInfinyRotateConique : MonoBehaviour
{
    [Header("Paramètres Généraux du Laser")]
    public float speed = 10f;
    public float laserLength = 50f;

    [Header("Intervalles d'Apparition")]
    [Tooltip("Intervalles d'apparition spécifiques pour les lasers multi-sources basés sur leur index (facultatif).")]
    public float[] intervalSpawns;

    // --- NOUVELLE DÉFINITION DES DIRECTIONS EN COORDONNÉES POLAIRES (SPHÉRIQUES) ---
    [System.Serializable]
    public class DirectionPrefab
    {
        [Tooltip("La latitude de la direction en degrés (angle par rapport au plan XZ). -90° est directement vers le bas, 0° est dans le plan XZ, 90° est directement vers le haut.")]
        [Range(-90f, 90f)]
        public float latitude; // En degrés

        [Tooltip("La longitude de la direction en degrés (angle dans le plan XZ, de l'axe Z+ vers l'axe X+). 0° est vers Z+, 90° vers X+, 180° vers Z-, -90° vers X- (ou 270°).")]
        [Range(-180f, 180f)] // Plage commune pour une couverture complète
        public float longitude; // En degrés

        [Tooltip("Le préfabriqué du tube de laser à instancier pour cette direction.")]
        public GameObject tubePrefab;

        // Propriété pour obtenir la direction cartésienne normalisée à partir des angles polaires
        public Vector3 CartesianDirection
        {
            get
            {
                // Convertir les degrés en radians
                float latRad = latitude * Mathf.Deg2Rad;
                float longRad = longitude * Mathf.Deg2Rad;

                // Calcul des composantes cartésiennes (pour un vecteur unitaire)
                float x = Mathf.Cos(latRad) * Mathf.Sin(longRad);
                float y = Mathf.Sin(latRad);
                float z = Mathf.Cos(latRad) * Mathf.Cos(longRad);

                // Retourne le vecteur normalisé (devrait déjà être unitaire si la trigonométrie est correcte)
                return new Vector3(x, y, z).normalized;
            }
        }
    }

    [Header("Directions de Départ & Préfabriqués")]
    [Tooltip("Définit les directions de base (en coordonnées polaires) et leurs préfabriqués de tubes associés. Cycles si plus de lasers que de définitions.")]
    public DirectionPrefab[] directionPrefabs;

    [Header("Rotation Longitudinale (Lacet)")]
    [Tooltip("Active la rotation longitudinale continue (autour de l'axe Y local / lacet) pour toutes les multi-sources apparues.")]
    public bool enableLongitudinalRotation = true;
    [Tooltip("Vitesse de la rotation longitudinale continue en degrés par seconde.")]
    public float longitudinalRotationSpeed = 60f;

    [Header("Oscillation Angulaire Calculée")]
    [Tooltip("Active l'oscillation angulaire calculée automatiquement.")]
    public bool enableAngularOscillation = false;
    [Tooltip("Vitesse angulaire moyenne de l'oscillation en degrés par seconde. Une valeur plus élevée rend l'oscillation plus rapide, comme la rotation longitudinale.")]
    public float oscillationSpeed = 60f; // Défaut à 60 deg/sec pour cohérence

    private List<MultiLaserSpawnerRotateConique> _activeMultiSourceSpawners = new List<MultiLaserSpawnerRotateConique>();

    void Start()
    {
        if (directionPrefabs == null || directionPrefabs.Length == 0)
        {
            Debug.LogError("[LaserInfinyRotateConique] Les 'directionPrefabs' ne sont pas définis ! Veuillez assigner au moins un 'DirectionPrefab' dans l'Inspector.");
            enabled = false;
            return;
        }

        bool anyPrefabAssigned = false;
        for (int i = 0; i < directionPrefabs.Length; i++)
        {
            DirectionPrefab dp = directionPrefabs[i];
            if (dp != null && dp.tubePrefab != null)
            {
                anyPrefabAssigned = true;

                Quaternion oscillationTargetRotationForThisDP = Quaternion.identity; // Rotation d'oscillation par défaut (aucune)
                bool isValidOscillationForThisPrefab = true; // Indicateur si l'oscillation est valide pour ce préfabriqué

                if (enableAngularOscillation)
                {
                    // --- UTILISATION DE CartesianDirection ICI ---
                    Vector3 startDirection = dp.CartesianDirection; // La direction de base convertie
                    Vector3 endDirection = new Vector3(0, dp.CartesianDirection.y, 0); // La direction cible (0, b, 0)

                    // Normalisation des directions pour le calcul de la rotation
                    if (startDirection.sqrMagnitude > 0.0001f) // Vérifie que la direction de départ n'est pas un vecteur nul
                    {
                        startDirection.Normalize();
                    }
                    else
                    {
                        Debug.LogWarning($"[LaserInfinyRotateConique] DirectionPrefab[{i}] a une direction de départ nulle (latitude ou longitude invalide pour un vecteur unitaire). L'oscillation angulaire sera désactivée pour ce préfabriqué.");
                        isValidOscillationForThisPrefab = false;
                    }

                    if (isValidOscillationForThisPrefab)
                    {
                        if (endDirection.sqrMagnitude < 0.0001f) // Vérifie si la direction d'arrivée est un vecteur nul
                        {
                            Debug.LogWarning($"[LaserInfinyRotateConique] DirectionPrefab[{i}] a une direction d'arrivée cible (0,Y,0) où Y=0. Oscillating vers (0,0,0) n'est pas une oscillation directionnelle valide. L'oscillation angulaire sera désactivée pour ce préfabriqué.");
                            isValidOscillationForThisPrefab = false;
                        }
                        else
                        {
                            endDirection.Normalize(); // Normalise la direction d'arrivée
                            // Calcule la rotation nécessaire pour passer de la direction de départ à la direction d'arrivée.
                            oscillationTargetRotationForThisDP = Quaternion.FromToRotation(startDirection, endDirection);

                            Debug.Log($"[LaserInfinyRotateConique] Direction[{i}] (Polar: Lat={dp.latitude:F2} Lon={dp.longitude:F2}, Cartesian: {dp.CartesianDirection.ToString("F3")}): " +
                                      $"Oscillation calculée de {startDirection.ToString("F3")} à {endDirection.ToString("F3")}");
                        }
                    }
                }

                // Crée le nouveau spawner et lui passe les paramètres d'oscillation calculés.
                CreateNewMultiSourceSpawner(
                    transform.position,
                    i, // Utilise l'index actuel pour le prefab (cycle automatique par % dans le spawner)
                    0, // Niveau de récursion initial
                    0f, // Délai
                    enableAngularOscillation && isValidOscillationForThisPrefab, // Active l'oscillation uniquement si valide
                    oscillationSpeed, // Passe la vitesse en deg/sec
                    oscillationTargetRotationForThisDP // Passe la rotation cible calculée
                );
            }
            else
            {
                Debug.LogWarning($"[LaserInfinyRotateConique] DirectionPrefab[{i}] est null ou n'a pas de préfabriqué de tube assigné. Veuillez l'assigner dans l'Inspector.");
            }
        }
        if (!anyPrefabAssigned)
        {
            Debug.LogError("[LaserInfinyRotateConique] Aucun préfabriqué de tube valide assigné dans 'directionPrefabs' ! Veuillez en assigner au moins un.");
            enabled = false;
            return;
        }
    }

    /// <summary>
    /// Crée un nouvel objet GameObject MultiLaserSpawnerRotateConique et l'initialise.
    /// </summary>
    /// <param name="position">Position mondiale du nouveau spawner.</param>
    /// <param name="laserIndex">Index pour choisir DirectionPrefab et l'intervalle des tableaux.</param>
    /// <param name="recursionLevel">Niveau de récursion actuel du spawner.</param>
    /// <param name="delay">Délai avant le début de l'apparition (non utilisé dans l'InvokeRepeating de cette version).</param>
    /// <param name="enableAngularOscillationForSpawner">Indique si l'oscillation angulaire est activée pour ce spawner.</param>
    /// <param name="oscillationSpeedPerSec">La vitesse angulaire de l'oscillation en degrés par seconde.</param>
    /// <param name="oscillationTargetRotation">La rotation cible pour l'oscillation angulaire.</param>
    public void CreateNewMultiSourceSpawner(
        Vector3 position,
        int laserIndex,
        int recursionLevel,
        float delay,
        bool enableAngularOscillationForSpawner,
        float oscillationSpeedPerSec,
        Quaternion oscillationTargetRotation
    )
    {
        Debug.Log($"[LaserInfinyRotateConique] Création d'un nouveau spawner multi-source au niveau {recursionLevel} pour l'index de laser {laserIndex}.");

        GameObject multiSourceSphere = new GameObject($"MultiSourceSpawner_Level{recursionLevel}_Laser{laserIndex}");
        multiSourceSphere.transform.position = position;

        MultiLaserSpawnerRotateConique multiSourceSpawner = multiSourceSphere.AddComponent<MultiLaserSpawnerRotateConique>();
        _activeMultiSourceSpawners.Add(multiSourceSpawner);

        float currentInterval = (intervalSpawns != null && intervalSpawns.Length > 0) ? intervalSpawns[laserIndex % intervalSpawns.Length] : 1f;

        multiSourceSpawner.Init(
            this,
            speed,
            currentInterval,
            position,
            recursionLevel,
            enableLongitudinalRotation,
            longitudinalRotationSpeed,
            enableAngularOscillationForSpawner,
            oscillationSpeedPerSec,
            oscillationTargetRotation
        );
    }

    /// <summary>
    /// Appelé lorsque le GameObject est désactivé ou détruit. Nettoie tous les objets enfants apparus.
    /// </summary>
    void OnDisable()
    {
        foreach (var spawner in _activeMultiSourceSpawners)
        {
            if (spawner != null)
            {
                Destroy(spawner.gameObject);
            }
        }
        _activeMultiSourceSpawners.Clear();
    }
}
Attacher seulement le dernier script à un objet laser et remplir les champs dédiés à Tube Prefab en faisant glisser les prefabs du dossier Prefabs vers chacun de ces champs
lien Prefabs:
https://drive.google.com/drive/folders/ ... sp=sharing

ça fonctionne (cf image jointe):
4 lasers rotatifs.png
4 lasers rotatifs.png (60.85 Kio) Consulté 876 fois
cf lien vidéo:
https://drive.google.com/file/d/1yH72xo ... sp=sharing

mais je ne comprends pas pourquoi lorsque nb_lasers>1 et quand l'oscillation angulaire est cochée,le nombre de lasers rotatifs est dupliqué !
Pouvez-vous m'aider?

merci de votre aide

Répondre

Revenir vers « (C#) CSharp »