So, I’m creating Game Objects on the server (rooms) as the host. I have a script that works great on the host to turn walls invisible that are blocking my camera from seeing a target. It also partially works on the client. The script is a local monobehavior script that executes only on the client side so the wall is not altered on every client when it blocks my camera focus. It utilizes ShereCastNonAlloc and I have tried BoxCastNonAlloc as well. As the host it detects both walls from each room that butt up to one another, recognizes that they have a Fade Object component, and adds them to the Objects that are blocking array, and fades them. As the client, it seems to only recognize one wall, and the other isnt added to the array to fade. The BoxCastNonAlloc is supposed to return all colliders it collides with and does this perfectly when running as a host, but only returns one collider when running as a client. Is this a bug or am I missing something that changes when you are a host vs a client running local monobehaviors?
Here is the script attached to the object that will fade:
using System;
using System.Collections.Generic;
//using Unity.VisualScripting;
using UnityEngine;
public class FadingObject : MonoBehaviour, IEquatable<FadingObject>
{
public List<Renderer> Renderers = new List<Renderer>();
public Vector3 Position;
public List<Material> Materials = new List<Material>();
[HideInInspector]
public float InitialAlpha;
public List<float> InitialAlphas = new List<float>(); // initial material alpha list
private void Awake()
{
Position = transform.position;
if (Renderers.Count == 0)
{
Renderers.AddRange(GetComponentsInChildren<Renderer>());
}
foreach(Renderer renderer in Renderers)
{
Materials.AddRange(renderer.materials);
}
foreach (Material material in Materials) // save our initial aplha values
{
InitialAlphas.Add(material.color.a);
}
InitialAlpha = Materials[0].color.a; // not used now
}
public bool Equals(FadingObject other)
{
return Position.Equals(other.Position);
}
public override int GetHashCode()
{
return Position.GetHashCode();
}
}
** Here is the detection of fading objects script:**
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class FadeObjectBlockingObject : MonoBehaviour
{
[SerializeField]
private LayerMask LayerMask;
[SerializeField]
private Transform Target;
[SerializeField]
private Camera Camera;
[SerializeField]
[Range(0, 1f)]
private float FadedAlpha = 0.15f;
[SerializeField]
private bool RetainShadows = true;
[SerializeField]
private Vector3 TargetPositionOffset = Vector3.up;
[SerializeField]
private float FadeSpeed = 5;
[Header("Read Only Data")]
[SerializeField]
private List<FadingObject> ObjectsBlockingView = new List<FadingObject>();
private Dictionary<FadingObject, Coroutine> RunningCoroutines = new Dictionary<FadingObject, Coroutine>();
private RaycastHit[] Hits = new RaycastHit[20];
//private RaycastHit[] hits = new RaycastHit[20];
private void OnEnable()
{
Debug.Log("starting fade detection from enable");
StartCoroutine(CheckForObjects());
}
private IEnumerator CheckForObjects()
{
while (true) //true
{
//Debug.Log("SphereCasting");
/*
int hits = Physics.SphereCastNonAlloc(
Camera.transform.position, 1.0f,
(Target.transform.position + TargetPositionOffset - Camera.transform.position).normalized,
Hits,
Vector3.Distance(Camera.transform.position, Target.transform.position + TargetPositionOffset),
LayerMask
);*/
int hits = Physics.BoxCastNonAlloc(
Camera.transform.position, new Vector3(1,1,1),
(Target.transform.position + TargetPositionOffset - Camera.transform.position).normalized,
Hits,
Quaternion.identity,
Vector3.Distance(Camera.transform.position, Target.transform.position + TargetPositionOffset),
LayerMask
);
if (hits > 0)
{
Debug.Log("SphereCast hit!!!!!.... ");
Debug.Log(Hits[0].collider.gameObject.name);
//Debug.Log(Hits[1].collider.gameObject.name);
}
Debug.DrawRay(Camera.transform.position, (Target.transform.position + TargetPositionOffset - Camera.transform.position).normalized * Vector3.Distance(Camera.transform.position, Target.transform.position + TargetPositionOffset), Color.yellow);
if (hits > 0 )
{
for (int i = 0; i < hits; i++)
{
FadingObject fadingObject = GetFadingObjectFromHit(Hits[i]);
if (fadingObject != null && !ObjectsBlockingView.Contains(fadingObject))
{
if (RunningCoroutines.ContainsKey(fadingObject))
{
if (RunningCoroutines[fadingObject] != null)
{
StopCoroutine(RunningCoroutines[fadingObject]);
}
RunningCoroutines.Remove(fadingObject);
}
RunningCoroutines.Add(fadingObject, StartCoroutine(FadeObjectOut(fadingObject)));
ObjectsBlockingView.Add(fadingObject);
}
}
}
/*if(cam_target.cameraMode == 1) { //remove fade in first person
ObjectsBlockingView.Clear();
}*/
FadeObjectsNoLongerBeingHit();
ClearHits();
yield return null;
}
}
private void FadeObjectsNoLongerBeingHit()
{
List<FadingObject> objectsToRemove = new List<FadingObject>(ObjectsBlockingView.Count);
foreach (FadingObject fadingObject in ObjectsBlockingView)
{
bool objectIsBeingHit = false;
for (int i = 0; i < Hits.Length; i++)
{
FadingObject hitFadingObject = GetFadingObjectFromHit(Hits[i]);
if (hitFadingObject != null && fadingObject == hitFadingObject && cam_target.cameraMode == 0) // only list hit if in third person
{
objectIsBeingHit = true;
break;
}
}
if (!objectIsBeingHit)
{
if (RunningCoroutines.ContainsKey(fadingObject))
{
if (RunningCoroutines[fadingObject] != null)
{
StopCoroutine(RunningCoroutines[fadingObject]);
}
RunningCoroutines.Remove(fadingObject);
}
RunningCoroutines.Add(fadingObject, StartCoroutine(FadeObjectIn(fadingObject)));
objectsToRemove.Add(fadingObject);
}
}
foreach(FadingObject removeObject in objectsToRemove)
{
ObjectsBlockingView.Remove(removeObject);
}
}
private IEnumerator FadeObjectOut(FadingObject FadingObject)
{
foreach (Material material in FadingObject.Materials)
{
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
material.SetInt("_ZWrite", 0);
material.SetInt("_Surface", 1);
material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
material.SetShaderPassEnabled("DepthOnly", false);
material.SetShaderPassEnabled("SHADOWCASTER", RetainShadows);
material.SetOverrideTag("RenderType", "Transparent");
material.EnableKeyword("_SURFACE_TYPE_TRANSPARENT");
material.EnableKeyword("_ALPHAPREMULTIPLY_ON");
}
float time = 0;
while (FadingObject.Materials[0].color.a > FadedAlpha)
{
foreach (Material material in FadingObject.Materials)
{
if (material.HasProperty("_Color"))
{
material.color = new Color(
material.color.r,
material.color.g,
material.color.b,
Mathf.Lerp(FadingObject.InitialAlpha, FadedAlpha, time * FadeSpeed)
);
}
}
time += Time.deltaTime;
yield return null;
}
if (RunningCoroutines.ContainsKey(FadingObject))
{
StopCoroutine(RunningCoroutines[FadingObject]);
RunningCoroutines.Remove(FadingObject);
}
}
private IEnumerator FadeObjectIn(FadingObject FadingObject)
{
float time = 0;
while (FadingObject.Materials[0].color.a < FadingObject.InitialAlpha)
{
foreach (Material material in FadingObject.Materials)
{
if (material.HasProperty("_Color"))
{
material.color = new Color(
material.color.r,
material.color.g,
material.color.b,
FadingObject.InitialAlphas[FadingObject.Materials.IndexOf(material)]
//Mathf.Lerp(FadedAlpha, FadingObject.InitialAlpha, time * FadeSpeed)
);
}
}
time += Time.deltaTime;
yield return null;
}
foreach (Material material in FadingObject.Materials)
{
if (material.color.a == 1f) // opaque if material alpha is 1f otherwise the material remains transparent
{
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
material.SetInt("_ZWrite", 1);
material.SetInt("_Surface", 0);
material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Geometry;
material.SetShaderPassEnabled("DepthOnly", true);
material.SetShaderPassEnabled("SHADOWCASTER", true);
material.SetOverrideTag("RenderType", "Opaque");
material.DisableKeyword("_SURFACE_TYPE_TRANSPARENT");
material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
}
}
if (RunningCoroutines.ContainsKey(FadingObject))
{
StopCoroutine(RunningCoroutines[FadingObject]);
RunningCoroutines.Remove(FadingObject);
}
}
private void ClearHits()
{
System.Array.Clear(Hits, 0, Hits.Length);
}
private FadingObject GetFadingObjectFromHit(RaycastHit Hit)
{
return Hit.collider != null ? Hit.collider.GetComponent<FadingObject>() : null;
}
}