using UnityEngine; [CreateAssetMenu(menuName = "Abilities/Freeze Shard")] public class FreezeShardAbility : Ability { public GameObject projectilePrefab; public float speed = 20f; public float damage = 0f; // optional direct damage public float freezeDuration = 3f; public float lifeTime = 4f; public float spawnOffset = 0.5f; public override void Activate(AbilityUser user) { if (!user || !projectilePrefab) return; // Get player camera (from FPS controller or fallback to Camera.main) Camera cam = null; if (Polyart.FirstPersonController.instance) cam = Polyart.FirstPersonController.instance.GetComponentInChildren(); if (!cam) cam = Camera.main; // Start slightly in front of the cast position Vector3 castPos = user.CastPos() + user.Forward() * spawnOffset; // Default direction if no camera found Vector3 dir = user.Forward(); if (cam) { // Ray from camera forward Ray ray = new Ray(cam.transform.position, cam.transform.forward); Vector3 targetPoint; if (Physics.Raycast(ray, out RaycastHit hit, 1000f, ~0, QueryTriggerInteraction.Ignore)) targetPoint = hit.point; else targetPoint = ray.origin + ray.direction * 1000f; dir = (targetPoint - castPos).normalized; } // Spawn projectile oriented to camera direction var go = Instantiate(projectilePrefab, castPos, Quaternion.LookRotation(dir)); // Push it forward var rb = go.GetComponent(); if (rb) rb.velocity = dir * speed; // Apply freeze shard properties var shard = go.GetComponent(); if (!shard) shard = go.AddComponent(); shard.damage = damage; shard.freezeDuration = freezeDuration; shard.ownerRoot = user.transform; // Ignore collisions with the caster var projCol = go.GetComponent(); if (projCol) { foreach (var oc in user.GetComponentsInChildren()) Physics.IgnoreCollision(projCol, oc, true); } Destroy(go, lifeTime); } }