Hide Object between Player and Camera

Ya know… I was going mad about hide objects that are between camera and player.
Mainly because I liked the idea of the fixed camera… but on that way, could happen to have the MainCamera inside some objects, and if the camera is “fixed” you can’t even use the the “collide” extension 'cause it would move the camera and the player still haven’t any control on it and so, you can’t even reposition it… and even if you try, well, the result most of the time will sux a lot. :sweat_smile:

The problem about casting a RayCast is that it will return only surface that are facing the camera.
But if your camera sit inside a tree, so you are looking a tree from inside, the “normals” are moving on the opposite way and the raycast will fail.

All of this blah-blah to reach the solution (sorry if I was talkative but explanation would needed for newbie I guess). So, the solution is simple 'cause the player will never be inside any object, 'cause the capsule-collider and also because the navMeshAgent, so instead of raycasting from camera to the player, all you have to do is the inverse! :grin:

So we start RayCasting from the targetPosition (the player) and we calculate the direction from camera position to the Player.

Physics.Raycast(targetPosition, transform.position - targetPosition, out hit, distance)

[EDIT]
It’s been a bit hard to achive it for me, but here it is… and looks fine
Please if you have any advice on getting this code better please share your knowledge with us! :wink:

 public class RemoveObstructer : MonoBehaviour
    {
        [SerializeField] private Transform target;
        [SerializeField] private float yOffset = 1f;
        [SerializeField] private LayerMask targetLayer; // The layer where we will allow to be hidden.
        [Space]
        [SerializeField] bool debugRay;
        private Camera cam;
        [SerializeField] private List<GameObject> prevHit = new List<GameObject>();    // List of objects which are hidden (determinare by physics hits)

        Vector3 targetPosition;
        private float distance;                                       // Distance between the camera and target, used to limit the RayCast


        void Start()
        {
            target = GetComponent<CinemachineVirtualCamera>().Follow;
            distance = Vector3.Distance(transform.position, target.position);

            cam = Camera.main;
        }


        void LateUpdate()
        {
            if (debugRay)
                DrawRay();

            ObsctructorManager();
        }

        private void DrawRay()
        {
            targetPosition = new Vector3(target.position.x, target.position.y + yOffset, target.position.z);
            distance = Vector3.Distance(targetPosition, transform.position);
            Vector3 direction = transform.position - targetPosition;

            Debug.DrawRay(targetPosition, direction, Color.red);
        }

        private void ObsctructorManager()
        {
            targetPosition = new Vector3(target.position.x, target.position.y + yOffset, target.position.z);
            distance = Vector3.Distance(targetPosition, transform.position);

            int layerNumber = targetLayer;
            int layerMask = 1 << layerNumber;

            RaycastHit[] hits;

             // Cast ray from target.position to camera.position and check if the specified layers sits in the middle
             // Please note I'm not using the LayerMask 'cause at the moment still fail ^_^"
            Ray ray = new Ray(targetPosition, transform.position - targetPosition);
            hits = Physics.RaycastAll(ray, distance);

            if (hits.Length > 0)
            {
                for (int i = 0; i < hits.Length; i++)
                {
                    RaycastHit hit;
                    hit = hits[i];

                    if (hit.transform.CompareTag("Player"))
                    {
                        Debug.Log("Hey Player!");
                        continue; }

                    Transform objectHit = hit.transform;

                    // There should be a meshRendereer component on the object we hit
                    if (objectHit.gameObject.GetComponent<MeshRenderer>() == null) continue;

                    if (prevHit.Contains(objectHit.gameObject))
                    {
                        ToggleVisibility(objectHit.gameObject, false);
                    }
                    else
                    {
                        prevHit.Add(objectHit.gameObject);
                        ToggleVisibility(objectHit.gameObject, false);
                    }
                }
            }
            else
            {
                // No hits on the RayCast? Swap the materials back to there original states
                for (int j = prevHit.Count - 1; j >= 0; j--)
                {
                    ToggleVisibility(prevHit[j]);
                    prevHit.Remove(prevHit[j]);
                }
            }

        }
               
        private void ToggleVisibility(GameObject go, bool isVisible = true)
        {
            if (isVisible)
            {
                Debug.Log(go.name + " Shown");
                go.GetComponent<MeshRenderer>().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.On;

            }
            else
            {
                Debug.Log(go.name + " Hidden");
                go.GetComponent<MeshRenderer>().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.ShadowsOnly;
            }
        }
    }

Privacy & Terms