Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Make object / wall 'See Through' when 'Player' is behind it ?

Discussion in 'Scripting' started by Deleted User, Feb 20, 2016.

  1. Deleted User

    Deleted User

    Guest

    Hi,

    I'm looking for some help scripting this, when my player is behind a wall, I want the wall to appear transparent, so that I can still see my player.

    I've searched many other scripts, but none of them seemingly relevant to what I need, most seem to 'fade' my player character instead of the wall. I should also mention that I am using a custom made shaderforge shader on the wall in question, I'm telling you this because I looked at this unitypackage, Easy Fade Obstruction , but it uses the Unity 5 shader's rendering mode ( set to fade ), which I don't have access to within my shaderforge shader.

    Ideally, something distance based would be great, so as you get closer, it starts to fade gradually down to a minimum transparency of half ( so that the wall can still be seen, but transparent ), and as you progress back out away from the wall, it regains it's full appearance again ?

    Thanks.
     
  2. Teravisor

    Teravisor

    Joined:
    Dec 29, 2014
    Posts:
    654
    How about writing stencil buffer in circle(or any shape you need) around player
    Then when drawing wall first check stencil and if it passes, then write transparent wall, otherwise write usual wall?

    Another way is if you have only one player, before drawing walls, set player position in walls shader then in shader compare distance to player and either make wall transparent or not depending on that.
     
  3. Deleted User

    Deleted User

    Guest

    Hi, Teravisor

    Thanks for your suggestions, sounds quite complicated for my feeble scripting abilities.

    I've come up with another way, using box collider with Is Trigger enabled and simply by swapping the material OnTriggerEnter. I'm going to 'try' and extend this further though, as I'd like this to happen over a period of time that I set, so the transition is smooth rather than an immediate 'pop'.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class triggerChangeMaterial : MonoBehaviour {
    5.  
    6.     public Material baseMaterial;
    7.     public Material fadeMaterial;
    8.  
    9.     void OnTriggerEnter (Collider other)
    10.     {
    11.         Debug.Log("Player has entered the trigger");
    12.  
    13.         if (other.gameObject.tag == "Player")
    14.         {
    15.             GetComponent<Renderer>().material = fadeMaterial;
    16.         }
    17.     }
    18.  
    19.     void OnTriggerExit (Collider other)
    20.     {
    21.         Debug.Log("Player has exited the trigger");
    22.  
    23.         if (other.gameObject.tag == "Player")
    24.         {
    25.             GetComponent<Renderer>().material = baseMaterial;
    26.         }
    27.     }
    28. }
     
    Last edited by a moderator: Feb 20, 2016
  4. Teravisor

    Teravisor

    Joined:
    Dec 29, 2014
    Posts:
    654
    Well, if you want very simple solutions, you could use raycasting. If raycast from camera to player hits wall, then hide wall. If it didn't, reactivate wall... It won't look very beautiful though.
     
  5. xXGrime

    xXGrime

    Joined:
    Aug 19, 2014
    Posts:
    16
  6. Deleted User

    Deleted User

    Guest

    Thanks, Teravisor and xXGrime,

    For the type of game I'm putting together, it doesn't need to be complicated, imagine a square arena with a fixed camera view, the wall at the front of the arena is the only wall I need to hide, so in this case, it's simpler to just go with the material replace option when triggered.

    Works great in my test scene, however, my actual 'ingame' wall has 3 different materials on it, I now need to find a way to replace all 3 mats at once, or alternatively just change their shader, as they all use the same 'fade' shader, I'll post back here if I'm successful or not.

    EDIT : Well, it worked, not sure if I'm calling the material.shader correctly ?, but it works, that's the main thing ! :)

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class triggerChangeShader : MonoBehaviour {
    5.  
    6.     public Shader baseShader;
    7.     public Shader fadeShader;
    8.  
    9.     void OnTriggerEnter (Collider other)
    10.     {
    11.         Debug.Log("Player has entered the trigger");
    12.  
    13.         if (other.gameObject.tag == "Player")
    14.         {
    15.             GetComponent<Renderer>().material.shader = fadeShader;
    16.         }
    17.     }
    18.  
    19.     void OnTriggerExit (Collider other)
    20.     {
    21.         Debug.Log("Player has exited the trigger");
    22.  
    23.         if (other.gameObject.tag == "Player")
    24.         {
    25.             GetComponent<Renderer>().material.shader = baseShader;
    26.         }
    27.     }
    28. }
     
    Last edited by a moderator: Feb 23, 2016
  7. robinloul

    robinloul

    Joined:
    Feb 1, 2015
    Posts:
    2
    Hello :),

    This is the code for a simple camera which is following a player. It can actually manage more than one object obstructing the view.
    Also I pass it a mask which I target with its name instead of checking for the collider name tag. Have fun.

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class followPlayer : MonoBehaviour
    4. {
    5.     public Transform player;
    6.     public Vector3 offset;
    7.     public Transform[] obstructions;
    8.  
    9.     private int oldHitsNumber;
    10.  
    11.     void Start()
    12.     {
    13.         oldHitsNumber = 0;
    14.     }
    15.  
    16.     private void LateUpdate()
    17.     {
    18.         viewObstructed();
    19.     }
    20.  
    21.     void Update()
    22.     {
    23.         transform.position = player.TransformPoint(offset);
    24.         transform.LookAt(player);
    25.     }
    26.  
    27.     void viewObstructed()
    28.     {
    29.         float characterDistance = Vector3.Distance(transform.position, player.transform.position);
    30.         int layerNumber = LayerMask.NameToLayer("Walls");
    31.         int layerMask = 1 << layerNumber;
    32.         RaycastHit[] hits = Physics.RaycastAll(transform.position, player.position - transform.position, characterDistance, layerMask);
    33.         if (hits.Length > 0)
    34.         {
    35.             // Means that some stuff is blocking the view
    36.             int newHits = hits.Length - oldHitsNumber;
    37.  
    38.             if (obstructions != null && obstructions.Length > 0 && newHits < 0)
    39.             {
    40.                 // Repaint all the previous obstructions. Because some of the stuff might be not blocking anymore
    41.                 for (int i = 0; i < obstructions.Length; i++)
    42.                 {
    43.                     obstructions[i].gameObject.GetComponent<MeshRenderer>().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.On;
    44.                 }
    45.             }
    46.             obstructions = new Transform[hits.Length];
    47.             // Hide the current obstructions
    48.             for (int i = 0; i < hits.Length; i++)
    49.             {
    50.                 Transform obstruction = hits[i].transform;
    51.                 obstruction.gameObject.GetComponent<MeshRenderer>().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.ShadowsOnly;
    52.                 obstructions[i] = obstruction;
    53.             }
    54.             oldHitsNumber = hits.Length;
    55.         }
    56.         else
    57.         {
    58.             // Mean that no more stuff is blocking the view and sometimes all the stuff is not blocking as the same time
    59.             if (obstructions != null && obstructions.Length > 0)
    60.             {
    61.                 for (int i = 0; i < obstructions.Length; i++)
    62.                 {
    63.                     obstructions[i].gameObject.GetComponent<MeshRenderer>().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.On;
    64.                 }
    65.                 oldHitsNumber = 0;
    66.                 obstructions = null;
    67.             }
    68.         }
    69.     }
    70. }
    71.  
     
  8. toorican

    toorican

    Joined:
    May 25, 2018
    Posts:
    16
    Last edited: Nov 20, 2022
    Slight0 likes this.
  9. ch_p

    ch_p

    Joined:
    May 30, 2017
    Posts:
    3
    Greetings!
    I slightly modified the @robinloul solution to support the opaque surface type and change the transparency over time for easing fading in/ fading out.
    You just need to set it up on your camera, change the layer tag to your liking and set up somewhere material with surface type = transparent.
    I hope you find it usefuil.
    Code (CSharp):
    1. using System.Collections.Generic;
    2. using UnityEngine;
    3.  
    4. public class MakeWallsTransparent : MonoBehaviour
    5. {
    6.     public Transform player;
    7.     public Vector3 offest;
    8.     [SerializeField]
    9.     private List<Transform> ObjectToHide = new List<Transform>();
    10.     private List<Transform> ObjectToShow = new List<Transform>();
    11.     private Dictionary<Transform, Material> originalMaterials = new Dictionary<Transform, Material>();
    12.  
    13.     void Start()
    14.     {
    15.     }
    16.  
    17.     private void LateUpdate()
    18.     {
    19.         ManageBlockingView();
    20.  
    21.         foreach (var obstruction in ObjectToHide)
    22.         {
    23.             HideObstruction(obstruction);
    24.         }
    25.  
    26.         foreach (var obstruction in ObjectToShow)
    27.         {
    28.             ShowObstruction(obstruction);
    29.         }
    30.     }
    31.  
    32.     void Update()
    33.     {
    34.      
    35.     }
    36.    
    37.     void ManageBlockingView()
    38.     {
    39.         Vector3 playerPosition = player.transform.position + offest;
    40.         float characterDistance = Vector3.Distance(transform.position, playerPosition);
    41.         int layerNumber = LayerMask.NameToLayer("floor");
    42.         int layerMask = 1 << layerNumber;
    43.         RaycastHit[] hits = Physics.RaycastAll(transform.position, playerPosition - transform.position, characterDistance, layerMask);
    44.         if (hits.Length > 0)
    45.         {
    46.             // Repaint all the previous obstructions. Because some of the stuff might be not blocking anymore
    47.             foreach (var obstruction in ObjectToHide)
    48.             {
    49.                 ObjectToShow.Add(obstruction);
    50.             }
    51.  
    52.             ObjectToHide.Clear();
    53.  
    54.             // Hide the current obstructions
    55.             foreach (var hit in hits)
    56.             {
    57.                 Transform obstruction = hit.transform;
    58.                 ObjectToHide.Add(obstruction);
    59.                 ObjectToShow.Remove(obstruction);
    60.                 SetModeTransparent(obstruction);
    61.             }
    62.         }
    63.         else
    64.         {
    65.             // Mean that no more stuff is blocking the view and sometimes all the stuff is not blocking as the same time
    66.            
    67.             foreach (var obstruction in ObjectToHide)
    68.             {
    69.                 ObjectToShow.Add(obstruction);
    70.             }
    71.  
    72.             ObjectToHide.Clear();
    73.  
    74.         }
    75.     }
    76.  
    77.     private void HideObstruction(Transform obj)
    78.     {
    79.         //obj.GetComponent<MeshRenderer>().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.ShadowsOnly;
    80.         var color = obj.GetComponent<Renderer>().material.color;
    81.         color.a = Mathf.Max(0, color.a - WorldConfigurator.Instance.ObstructionFadingSpeed * Time.deltaTime);
    82.         obj.GetComponent<Renderer>().material.color = color;
    83.  
    84.     }
    85.  
    86.     private void SetModeTransparent(Transform tr)
    87.     {
    88.         MeshRenderer renderer = tr.GetComponent<MeshRenderer>();
    89.         Material originalMat = renderer.sharedMaterial;
    90.         if (!originalMaterials.ContainsKey(tr))
    91.         {
    92.             originalMaterials.Add(tr, originalMat);
    93.         }
    94.         else
    95.         {
    96.             return;
    97.         }
    98.         Material materialTrans = new Material(WorldConfigurator.Instance.transparentMaterial);
    99.         //materialTrans.CopyPropertiesFromMaterial(originalMat);
    100.         renderer.material = materialTrans;
    101.         renderer.material.mainTexture = originalMat.mainTexture;
    102.     }
    103.  
    104.     private void SetModeOpaque(Transform tr)
    105.     {
    106.         if (originalMaterials.ContainsKey(tr))
    107.         {
    108.             tr.GetComponent<MeshRenderer>().material = originalMaterials[tr];
    109.             originalMaterials.Remove(tr);
    110.         }
    111.  
    112.     }
    113.  
    114.     private void ShowObstruction(Transform obj)
    115.     {
    116.         var color = obj.GetComponent<Renderer>().material.color;
    117.         color.a = Mathf.Min(1, color.a + WorldConfigurator.Instance.ObstructionFadingSpeed * Time.deltaTime);
    118.         obj.GetComponent<Renderer>().material.color = color;
    119.         if (Mathf.Approximately(color.a, 1f))
    120.         {
    121.             SetModeOpaque(obj);
    122.         }
    123.     }
    124. }
    125.  
     
    JUGoWATER and alfredbaudisch like this.