• 08/10/13 02:10 PM
    Sign in to follow this  
    Followers 0

    Hide Objects Blocking Player View

    General and Gameplay Programming

    irrationalistic
    In most isometric-esque RTS-style game views, sometimes pesky walls can pop into view, hindering the player's connection with the protagonist. This isn't good but is easily solvable with many different solutions. One, highlight the player's outline when it is behind objects. Two, hide the interfering objects. Three, masking shaders to overlay over the screen. There are, of course, many other solutions, but I'll only explore these in this post through the use of Unity.

    Highlight The Player

    This method already has several existing code examples. Found on the UnifyCommunity wiki, the shader will draw an outline for the player or fill when part of the player is hidden: Silhouette-Outlined Diffuse This method is effective since it requires very little calculation and handles all possible situations. The con to this system is that you don't get a very good viewpoint of anything else on the other side of the wall including obstacles or enemies.

    Hide The Interfering Objects

    Another very simple execution with the right use of C# and/or shaders, this method will create a shader that adds transparency to overlapping objects and maintains visual understanding of the scene. First your script needs to detect all blocking objects. Just attach this to your camera and tell it to watch for the player, using walls and other hideable objects as the layermask. This will disable rendering the walls in the way, but you'll still collide with them. using UnityEngine; using System.Collections; using System.Collections.Generic; public class HideObjects : MonoBehaviour { public Transform WatchTarget; public LayerMask OccluderMask; private List _LastTransforms; void Start () { _LastTransforms = new List(); } void Update () { //reset and clear all the previous objects if(_LastTransforms.Count > 0){ foreach(Transform t in _LastTransforms) t.GetComponent().enabled = true; _LastTransforms.Clear(); } //Cast a ray from this object's transform the the watch target's transform. RaycastHit[] hits = Physics.RaycastAll( transform.position, WatchTarget.transform.position - transform.position, Vector3.Distance(WatchTarget.transform.position, transform.position), OccluderMask ); //Loop through all overlapping objects and disable their mesh renderer if(hits.Length > 0){ foreach(RaycastHit hit in hits){ if(hit.collider.gameObject.transform != WatchTarget && hit.collider.transform.root != WatchTarget){ hit.collider.gameObject.GetComponent().enabled = false; _LastTransforms.Add(hit.collider.gameObject.transform); } } } } }

    Use Shaders

    Finally, a nicer-looking option that retains shadows is to use shaders to de-occlude your walls. The shader is essentially adding transparency to the render while the object continues to cast shadows. The shader, which works wonders, was supplied by user ScroodgeM on UnityAnswers: Shader "Transparent/Diffuse with Shadow" { Properties { _Color ("Main Color", Color) = (1,1,1,1) _MainTex ("Base (RGB) Trans (A)", 2D) = "white" {} } SubShader { Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" } LOD 200 Blend SrcAlpha OneMinusSrcAlpha CGPROGRAM #pragma surface surf Lambert addshadow sampler2D _MainTex; fixed4 _Color; struct Input { float2 uv_MainTex; }; void surf (Input IN, inout SurfaceOutput o) { fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; o.Alpha = c.a; } ENDCG } Fallback "Transparent/VertexLit" } And the code that will toggle the shader in its basic entirety: using UnityEngine; using System.Collections; using System.Collections.Generic; public class HideObjects : MonoBehaviour { public Transform WatchTarget; public LayerMask OccluderMask; //This is the material with the Transparent/Diffuse With Shadow shader public Material HiderMaterial; private Dictionary _LastTransforms; void Start () { _LastTransforms = new Dictionary(); } void Update () { //reset and clear all the previous objects if(_LastTransforms.Count > 0){ foreach(Transform t in _LastTransforms.Keys){ t.renderer.material = _LastTransforms[t]; } _LastTransforms.Clear(); } //Cast a ray from this object's transform the the watch target's transform. RaycastHit[] hits = Physics.RaycastAll( transform.position, WatchTarget.transform.position - transform.position, Vector3.Distance(WatchTarget.transform.position, transform.position), OccluderMask ); //Loop through all overlapping objects and disable their mesh renderer if(hits.Length > 0){ foreach(RaycastHit hit in hits){ if(hit.collider.gameObject.transform != WatchTarget && hit.collider.transform.root != WatchTarget){ _LastTransforms.Add(hit.collider.gameObject.transform, hit.collider.gameObject.renderer.material); hit.collider.gameObject.renderer.material = HiderMaterial; } } } } } Just attach the script to your main camera, telling it to watch the player, use the walls and other occluding objects as the layermask, and pass it a material with the hiding shader attached. It will hotswap the materials on the fly. The result is a very clear indication of where walls are and how they are hiding the player. Don't forget to set the opacity down on your material!
    HideObjects_4.jpg HideObjects_3.jpg

    Conclusion

    I prefer the shader version since I want to be able to animate the fade and maintain visuals of obstacles. Either way, there are many more options to choose from such as forcing the viewpoint or changing the visuals with a blended shader. As always, check out the options and pick the one that best fits your project and timeline. 12 Jun 2013: Initial release
    0


    Sign in to follow this  
    Followers 0


    User Feedback

    Create an account or sign in to leave a review

    You need to be a member in order to leave a review

    Create an account

    Sign up for a new account in our community. It's easy!


    Register a new account

    Sign in

    Already have an account? Sign in here.


    Sign In Now

    bratiefanut

    • 5
      
    0

    Share this review


    Link to review
    Dragonsoulj

    • 5
      
    0

    Share this review


    Link to review
    ram64

    • 5
      
    0

    Share this review


    Link to review
    Ectara

    • 5
      
    0

    Share this review


    Link to review
    CJThomas

    • 5
      
    0

    Share this review


    Link to review
    hossainiir

    • 5
      
    0

    Share this review


    Link to review
    MrCodeSushi

    • 5
      
    0

    Share this review


    Link to review
    jbadams

    • 5
      
    0

    Share this review


    Link to review
    GrayScale

    • 5
      
    0

    Share this review


    Link to review
    EMascheG

    • 5
      
    0

    Share this review


    Link to review
    pizzafan

    • 5
      
    0

    Share this review


    Link to review
    GlenDC

    • 5
      
    0

    Share this review


    Link to review
    Dave Hunt

    • 5
      
    0

    Share this review


    Link to review
    shocobenn

    • 5
      
    0

    Share this review


    Link to review
    gezegond

    • 5
      
    0

    Share this review


    Link to review
    Zaoshi Kaba

    • 5
      
    0

    Share this review


    Link to review