using Fusion; using UnityEngine; namespace Projectiles { public struct HitscanData : INetworkStruct { public byte PrefabIndex; public byte BarrelIndex; public Vector3Compressed FirePosition; public Vector3Compressed FireDirection; public Vector3Compressed ImpactPosition; public Vector3Compressed ImpactNormal; } /// /// Projectile data buffer for hitscan projectiles. /// public class HitscanProjectileBuffer : NetworkDataBuffer { // PRIVATE MEMBERS [SerializeField] private HitscanProjectile[] _projectilePrefabs; private ProjectileContext _context; // PUBLIC METHODS public void AddProjectile(HitscanProjectile projectilePrefab, Vector3 firePosition, Vector3 direction, byte barrelIndex = 0) { int prefabIndex = _projectilePrefabs.IndexOf(projectilePrefab); if (prefabIndex < 0) { Debug.LogError($"Projectile {projectilePrefab} not found. Add it in HitscanProjectiles prefab array."); return; } // Temporarily assign correct context in case it will be needed in GetFireData projectilePrefab.Context = _context; var data = projectilePrefab.GetFireData(firePosition, direction); projectilePrefab.Context = null; data.PrefabIndex = (byte)prefabIndex; data.BarrelIndex = barrelIndex; AddData(data); } public void UpdateBarrelTransforms(Transform[] barrelTransforms) { _context.BarrelTransforms = barrelTransforms; } // NetworkDataBuffer INTERFACE [Networked, Capacity(32)] protected override NetworkArray DataBuffer { get; } protected override HitscanProjectile GetView(HitscanData data) { var projectile = Context.ObjectCache.Get(_projectilePrefabs[data.PrefabIndex]); Runner.MoveToRunnerScene(projectile); if (Runner.Config.PeerMode == NetworkProjectConfig.PeerModes.Multiple) { Runner.AddVisibilityNodes(projectile.gameObject); } projectile.Context = _context; projectile.Activate(ref data); return projectile; } protected override void ReturnView(HitscanProjectile projectile, bool misprediction) { if (projectile == null) return; projectile.Deactivate(); Context.ObjectCache.Return(projectile); } public override void Spawned() { base.Spawned(); _context.Runner = Runner; _context.Cache = Context.ObjectCache; _context.Owner = Object.InputAuthority; } // MONOBEHAVIOUR protected void Awake() { _context = new ProjectileContext(); } } }