You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
118 lines
3.9 KiB
C#
118 lines
3.9 KiB
C#
using Fusion;
|
|
using System.Collections.Generic;
|
|
using Fusion.LagCompensation;
|
|
using UnityEngine;
|
|
|
|
namespace Projectiles
|
|
{
|
|
/// <summary>
|
|
/// This utility unifies handling of lag compensated casts across the project.
|
|
/// </summary>
|
|
public static class ProjectileUtility
|
|
{
|
|
public static bool ProjectileCast(NetworkRunner runner, PlayerRef owner, Vector3 firePosition, Vector3 direction, float distance, LayerMask hitMask, out LagCompensatedHit hit, bool ignoreInputAuthority = true)
|
|
{
|
|
var hitOptions = HitOptions.IncludePhysX | HitOptions.SubtickAccuracy;
|
|
|
|
if (ignoreInputAuthority == true)
|
|
{
|
|
hitOptions |= HitOptions.IgnoreInputAuthority;
|
|
}
|
|
|
|
return runner.LagCompensation.Raycast(firePosition, direction, distance, owner, out hit, hitMask, hitOptions);
|
|
}
|
|
|
|
public static bool ProjectileCastAll(NetworkRunner runner, PlayerRef owner, int ownerObjectInstanceID, Vector3 firePosition, Vector3 direction, float distance, LayerMask hitMask, List<LagCompensatedHit> validHits)
|
|
{
|
|
return ProjectileCastAll(runner, owner, ownerObjectInstanceID, firePosition, direction, 0f, distance, hitMask, validHits);
|
|
}
|
|
|
|
public static bool ProjectileCastAll(NetworkRunner runner, PlayerRef owner, int ownerObjectInstanceID, Vector3 firePosition, Vector3 direction, float distanceToTarget, float raycastDistance, LayerMask hitMask, List<LagCompensatedHit> validHits)
|
|
{
|
|
validHits.Clear();
|
|
|
|
var hits = ListPool.Get<LagCompensatedHit>(16);
|
|
|
|
var hitOptions = HitOptions.IncludePhysX | HitOptions.SubtickAccuracy | HitOptions.IgnoreInputAuthority;
|
|
int hitCount = runner.LagCompensation.RaycastAll(firePosition, direction, raycastDistance, owner, hits, hitMask, true, hitOptions);
|
|
|
|
if (hitCount <= 0)
|
|
{
|
|
ListPool.Return(hits);
|
|
return false;
|
|
}
|
|
|
|
var hitRoots = ListPool.Get<int>(16);
|
|
|
|
float ignoreDistanceMin = 3f;
|
|
float ignoreDistanceMax = Mathf.Max(distanceToTarget - 1f, ignoreDistanceMin);
|
|
|
|
hits.SortDistance();
|
|
|
|
for (int i = 0; i < hits.Count; i++)
|
|
{
|
|
var hit = hits[i];
|
|
|
|
if (distanceToTarget > 0f)
|
|
{
|
|
// For 3rd person cast it is possible that we want to shoot through environment objects a little bit if we already know the destination point
|
|
// => ray from camera is different than ray from 3rd person character
|
|
if (hit.Distance >= ignoreDistanceMin && hit.Distance < ignoreDistanceMax && hit.GameObject != null && ObjectLayerMask.Environment.value.IsBitSet(hit.GameObject.layer))
|
|
continue;
|
|
}
|
|
|
|
int hitRootID = hit.Hitbox != null ? hit.Hitbox.Root.gameObject.GetInstanceID() : 0;
|
|
|
|
if (hitRootID != 0)
|
|
{
|
|
if (hitRootID == ownerObjectInstanceID)
|
|
continue; // Owner was hit
|
|
|
|
if (hitRoots.Contains(hitRootID) == true)
|
|
continue; // Same object was hit multiple times
|
|
|
|
hitRoots.Add(hitRootID);
|
|
}
|
|
|
|
validHits.Add(hits[i]);
|
|
}
|
|
|
|
ListPool.Return(hitRoots);
|
|
ListPool.Return(hits);
|
|
|
|
return validHits.Count > 0;
|
|
}
|
|
|
|
public static bool CircleCast(NetworkRunner runner, PlayerRef owner, Vector3 firePosition, Vector3 direction, float distance, float radius, int numberOfRays, LayerMask hitMask, out LagCompensatedHit hit)
|
|
{
|
|
hit = default;
|
|
|
|
float angleStep = numberOfRays > 2 ? (2f * Mathf.PI) / (numberOfRays - 1) : 0f;
|
|
Matrix4x4 rotationMatrix = Matrix4x4.Rotate(Quaternion.LookRotation(direction));
|
|
|
|
for (int i = 0; i < numberOfRays; i++)
|
|
{
|
|
Vector3 position = firePosition;
|
|
|
|
// First ray is always directly in the center
|
|
if (i > 0)
|
|
{
|
|
float angle = angleStep * (i - 1);
|
|
var offset = new Vector3(radius * Mathf.Cos(angle), radius * Mathf.Sin(angle), 0f);
|
|
position += rotationMatrix.MultiplyPoint3x4(offset);
|
|
}
|
|
|
|
if (ProjectileCast(runner, owner, position, direction, distance, hitMask, out LagCompensatedHit currentHit) == true)
|
|
{
|
|
if (hit.Type == HitType.None || currentHit.Distance < hit.Distance)
|
|
{
|
|
hit = currentHit;
|
|
}
|
|
}
|
|
}
|
|
|
|
return hit.Type != HitType.None;
|
|
}
|
|
}
|
|
}
|