How to achieve diablo style walls? (55047)

So i want to achieve walls like diablo that parts of it disappear if it is blocking the sight to the player or any other AI character
I did read this:

http://forum.unity3d.com/threads/76310-Diablo-style-walls-that-become-visible-hidden-depending-on-the-character-s-location

but it provided nothing important other than this Visibility bubble thing:

http://forum.unity3d.com/threads/130480-Visibility-bubble-Titan-Quest-like

Which i completely dont understand:

"You have it mostly right, this kind of effect probably requires you to render the scene twice if you want things like dynamic shadows to work. Have your second camera draw into a separate render texture and then have the main camera composite that back on top of the scene. The simplest way would be to make a post processing effect that simply draws the second render texture with an alpha mask.

If you don’t need shadows casting on the rocks then you could probably get away with putting a shader on the rocks that alpha blends using a screen space mask. The surface shader example section of the documentation shows how to sample textures in screen space, just set the alpha to the mask texture value."

I wasnt able to understand any of this since i have no experience with shader programming so can anyone please explain what exactly should i be doing to achieve this wall system?

PS: I have unity free so i am not worried about shadows or anything like that if it matters.
Also I am using the bird eye view camera and not the third person view one..

With a top-down view (birdsEye?,) a player will rarely be blocked, right? Only pressed against the far side of a wall tilted by perspective?

Well, its not exactly above the player since there is a small difference on the x position and the x rotation in order to give a better view of the character therefore the character can sometime be hidden by walls and thats why diablo used the system of making walls disappear (or at least the part of that hides the character) in order to have a better visual of the player..

4 Answers

4

In my opinion, the first thing you have to keep in mind when approaching this is that surfaces (triangles) in Unity only have one side.
Create a plane, and rotate it around, you’ll see what I mean.

I think the first way to attempt to tackle this problem is to build your walls, but make sure you have inward-facing surfaces, as well.
Assign a regular material to the side that will face the player, and a similar, but halfway transparent material assigned to the ‘inside’ of the wall.

This way, the walls that are with their backs turned to the camera, so to speak, will be transparent, the ones facing the camera will look normal.

All done with modelling, no scripting required.

This might not get you all the way to the effect you want, but I think its a good place for you to start.

Well thats a really nice approach but i dont think it would be useful to me since i am using a bird eye view camera (Sorry for not mentioning that but i added it to the question) also i was thinking about using raycasting and if the camera cant find any of the available characters or the player then it makes the opposing mesh transparent?? Thanks alot for giving the time to answer my question

I have read your discussions here and you are getting near to a solution. @EDarkness solution is a good way to go.

First let us keep it simple and avoid any advanced shaders, post process image effects or render textures as we are on Unity Free.

Lay out the steps we need for this to work:

1: Cast a ray from the camera to the player at all times.

2: Add all objects the ray hit which is not the player into a list.

3: Disable the renderer for all those objects.

4: Remove Objects from the list that the ray no longer hits.

5: Enable the renderer on all of those objects again.

We want to add all objects we find because there could be multiple objects in the way, but we could also of course keep it simple and say that we only want to hide Walls and Pillars and not other small objects. Still it is wise to be able to hide all Walls and Pillars we find.

So here is my example code to accomplish this:

using UnityEngine;
using System.Collections.Generic;

public class HideWalls : MonoBehaviour
{
    //The player to shoot the ray at
    public Transform player;
    //The camera to shoot the ray from
    public Transform camera;

    //List of all objects that we have hidden.
    public List<Transform> hiddenObjects;

    //Layers to hide
    public LayerMask layerMask;

    private void Start()
    {
        //Initialize the list
        hiddenObjects = new List<Transform>();
    }

    void Update()
    {
        //Find the direction from the camera to the player
        Vector3 direction = player.position - camera.position;

        //The magnitude of the direction is the distance of the ray
        float distance = direction.magnitude;

        //Raycast and store all hit objects in an array. Also include the layermaks so we only hit the layers we have specified
        RaycastHit[] hits = Physics.RaycastAll(camera.position, direction, distance, layerMask);

        //Go through the objects
        for (int i = 0; i < hits.Length; i++)
        {
            Transform currentHit = hits*.transform;*

//Only do something if the object is not already in the list
if (!hiddenObjects.Contains(currentHit))
{
//Add to list and disable renderer
hiddenObjects.Add(currentHit);
currentHit.renderer.enabled = false;
}
}

//clean the list of objects that are in the list but not currently hit.
for (int i = 0; i < hiddenObjects.Count; i++)
{
bool isHit = false;
//Check every object in the list against every hit
for (int j = 0; j < hits.Length; j++)
{
if (hits[j].transform == hiddenObjects*)*
{
isHit = true;
break;
}
}

//If it is not among the hits
if (!isHit)
{
//Enable renderer, remove from list, and decrement the counter because the list is one smaller now
Transform wasHidden = hiddenObjects*;*
wasHidden.renderer.enabled = true;
hiddenObjects.RemoveAt(i);
i–;
}
}
}
}
This assumes that all objects that has the layer mask has the renderer on the same object as the collider. If not then you should use GetComponentInChildren() instead.
I have not tested this code very thoroughly, but It should work. Or you can at least base your system on it.
After getting this to work we could expand on it and get the objects to fade in and out using the color of the shader instead of just simply turning them on and off.

Yep. I know it's something like this. However, what I want at this point is to have an accurate record for everyone who wants to do it. This way, the question can be answered and put away for anyone who wants to know how to do it. Anyway, I have two cameras that are exactly the same with the only difference being the secondary camera doesn't render objects that can be in the way. The issue is really getting the hole in the middle and the two cameras to merge together.

Thanks everyone for your input, My theory is to make the model itself divided into two parts, A lower part of the wall for exapmle that will never get in the way of the camera and the upper part that propaply will, Then when the camera hit the upper part it should fade it untill its transparent using ITween then fade it again untill it appears when its no longer in the way of the camera?

@abdosaher, it should be easy to do. Just make the call to iTween when the item is hit. When nothing is going on change the item back to the way it was.

and in addition to what has been said already, the default project of unity from before was angry bots. this had the same style (in a sense a “dungeon crawler”) maybe look back and study it :slight_smile:

The third person mmo controller project by Unity makes use of the camera distance to alpha the main character out, so as not to block the camera or show the character’s model innards. I mention this, because it gives the same basic illusion that the diablo style walls give.
What I would offer to this, is that you could place a spherical raycast onto the player gameobject. if the cast hits a wall that has been tagged, then adjust the hit object’s alpha value.
This would fade the wall out, to reveal the player standing behind it.
The other option would be to place a masked texture onto a Quad above the player, and a camera that looks at the player. Set the camera to render to texture, and the rendered texture onto the quad, mask it so that it is round or some other shape and so that you can alpha fade out the edges so it’s not some blocky square. Just a couple of basic thoughts. :smiley:
Good luck, and let me know how you crack this!

I actually used the first method to deal with the situation but the second one you proposed seems really interesting and could be really cool to try, Thanks for helping out :)