- Home /
How to achieve diablo style walls?
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:
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..
Answer by GameVortex · Jan 10, 2014 at 10:25 AM
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[i].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[i])
{
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[i];
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.
GameVortex, this is basically what I did, however I didn't keep a list of objects in the way. I figured that little things didn't matter only large objects like walls and buildings. When building my levels, I put all buildings and walls that have the potential to get in the way of the camera on their own layer. The ray simply checks to see if an object on that layer is in the way, then it does something.
Either way, I think both of us got it right. This way works as I have tested it and have been testing it for a couple of days now. The issue now is how to get the shaders to do what I need them to do in order to create the necessary "bubble effect" around the player when an object is in the way.
In another thread someone mentioned the article below:
http://technology.blurst.com/camera-render-with-shader/
The thing is, I don't know enough about shaders and I don't know much about Javascript to really know what's going on 100%. I do know that what we're trying to do is basically the same.
The issue is what does what? I figured that the secondary camera makes some kind of render texture and that is then merged with the main camera view to create the bubble. I just don't know how that's done. Perhaps more heads wrapped around the problem will find a solution.
I see. You specifically want the round window (bubble effect) through the walls ins$$anonymous$$d of hiding the walls. I misinterpreted your question apparently.
This as you say would require two cameras. One rendering the scene without the walls to the game view and the other rendering everything to a render texture. To create the hole you can use **this** masking shader. Add the shader to a material, add the render texture as base and another texture with an alpha circle in the middle as the mask. Put a plane infront of the main camera that renders the scene without the walls and add the material to the plane.
This requires accurate adjustments of the scale and position of the plane so it matches the scene. Also Render Textures are a Unity Pro feature.
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, $$anonymous$$y 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.
Answer by Tasarran · Nov 06, 2012 at 05:51 AM
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'm working on this very problem and I think I have the basic idea down. However, getting any real information about it is hard and there doesn't seem to be a lot of information or talk about it. Perhaps a group of us can pool resources to get it done and then post it out there for people to use.
At the moment, I followed a couple of the examples and have two cameras that are exactly the same, except the secondary camera doesn't render a certain layer. This layer is for all walls and such that could get in the way of the player's view.
I then cast a ray to the player character and check for anything that gets in the way and when that happens it should do something. However, I don't know much about shaders and so I'm not sure what to do next once it is deter$$anonymous$$ed some item is in the way.
$$anonymous$$y understanding of this is that the secondary camera is enabled and uses some kind of shader with a mask to get a render of that camera view, then it's turned off. That render texture is then composted onto the main view. I'm just now sure how to go about this. Perhaps someone else has some suggestions.
Answer by thornekey · Jan 10, 2014 at 12:08 PM
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 :)
Answer by MichiealO · Nov 04, 2015 at 11:24 PM
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. :D 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 :)
Your answer
Follow this Question
Related Questions
Changing shaders in a game during runtime 1 Answer
How do I render a scene's depth buffer when I have custom vertex shaders? 0 Answers
rendering things in order 0 Answers
CommandBuffer's CameraEvent ordering not in sync with shader rendering queue? 1 Answer
How Do I Make Camera Follow Sprite 2.5D 0 Answers