Туман войны для 2d игры

Программирование на Юнити.

Туман войны для 2d игры

Сообщение MrDmitry 20 июл 2019, 17:41

Делаю простенькую 2d игру с видом с верху и появилась необходимость сделать туман войны. В голову сразу пришла мысль кинуть на сцену спрайт с полу прозрачностью, с триггером, все что попало в область триггера, кроме нашего персонажа, становится прозрачным, все что покинуло область триггера, становится видимым. Это сейчас работает и вопросов не возникает.
Теперь нужно сделать чтоб персонаж открывал область тумана а также чтоб объекты входящие не полностью в триггер тумана становились видимыми. И как это сделать у меня ума уже хватило. Гуглил как делается туман войны, но все примере которые я нашел были для 3D и мне не подходят. Либо же предлагалось использовать шейдеры, с ними я не работал (
Может кто то знает какие то ссылки которые могли бы помочь реализовать туман войны 2d? Или у кого то есть какие то мысли?
MrDmitry
UNITрон
 
Сообщения: 223
Зарегистрирован: 05 авг 2017, 17:21

Re: Туман войны для 2d игры

Сообщение MrDmitry 21 июл 2019, 16:40

Пришла мысль сделать через sprite mask. Нарисовал маску обзора, растянул на всю карту черный квадрат, прикрепил маску к персонажу, растянул ее под нужным углом, и вроде бы все отображается примерно как хотел. Но как теперь закрывать часть обзора, если например на пути обзора стена? Опять же я кинул raycast но как закрыть область за стеной оставив часть обзора не попадающего за стену? Примеры в скриншотах.


Изображение
А вот так хотелось бы чтоб было. То что зачеркнуто видно не должно быть.
Изображение
MrDmitry
UNITрон
 
Сообщения: 223
Зарегистрирован: 05 авг 2017, 17:21

Re: Туман войны для 2d игры

Сообщение MrDmitry 21 июл 2019, 18:56

Я как бы не прошу какого-то готового решения, просто подскажите в каком направлении двигаться. Если через шейдеры, то может быть кто то подскажет какой то хороший ресурс где можно вообще понять как с ними работать...
MrDmitry
UNITрон
 
Сообщения: 223
Зарегистрирован: 05 авг 2017, 17:21

Re: Туман войны для 2d игры

Сообщение MrDmitry 22 июл 2019, 21:04

В общем коль уж я общаюсь в этой теме сам с собой. Сделал туман войны как мне надо, но по моему очень тупым и тормазнутым способом. Вариант надо допиливать но пока хоть что то. А сделал я так.
В фотошопе нарисовал черный квадрат 32 на 32 пикселя.
На персонажа повесил пустой объект с циркуль триггером(Это некий обзор персонажа) с тегом review. Стены которые закрывают обзор повесил тег notView
На спрайт черного квадрата повесил тег FogOfWar и скрипт

Синтаксис:
Используется csharp
public class Look : MonoBehaviour {
    private GameObject Player;
    private GameObject Circle;
    private bool Trigger = false;

 void Start()
    {
        Player = GameObject.FindGameObjectWithTag("Player");
    }

    private void OnTriggerEnter2D(Collider2D col)
    {
        if (col.gameObject.tag == "review")
        {
            Trigger = true;
        }
    }

    private void Update()
    {
        bool wall = false;
        if (Trigger)
        {
            RaycastHit2D[] allHits = Physics2D.LinecastAll(gameObject.transform.position, Player.transform.position);
            for (int i = 0; i < allHits.Length; i++)
            {
                if (allHits[i].transform.tag == "notView")
                {
                    SpriteRenderer _sprite = gameObject.GetComponent<SpriteRenderer>();
                    Color color = new Color(_sprite.color.r, _sprite.color.g, _sprite.color.b, 255);
                    _sprite.color = color;
                    wall = true;
                    break;
                }
            }
            if (!wall)
            {
                SpriteRenderer _sprite = gameObject.GetComponent<SpriteRenderer>();
                Color color = new Color(_sprite.color.r, _sprite.color.g, _sprite.color.b, 0);
                _sprite.color = color;
            }
        }
    }

    private void OnTriggerExit2D(Collider2D col)
    {
        if (col.gameObject.tag == "review")
        {
            SpriteRenderer _sprite = gameObject.GetComponent<SpriteRenderer>();
            if (_sprite.color == new Color(_sprite.color.r, _sprite.color.g, _sprite.color.b, 0))
            {
                Color color = new Color(_sprite.color.r, _sprite.color.g, _sprite.color.b, 130);
                _sprite.color = color;
            }
            Trigger = false;
        }
    }
}


Расскланировал круг на всю карту. Результат:

Изображение
и вид в самой игре
Изображение
MrDmitry
UNITрон
 
Сообщения: 223
Зарегистрирован: 05 авг 2017, 17:21

Re: Туман войны для 2d игры

Сообщение waruiyume 22 июл 2019, 22:32

Это называется не "туман войны", а "зона видимости", по сути это просто тени от стен.

Кустарное решение:
Делаем 3д трубы которые описывают очертания стен и используем встроенные в движок тени.
Как показали тесты, это решение крайне производительно ( [unity 3D] 2019), но несколько вырвиглазно выглядит в окне сцены.

Готовые решения по 2д теням:
Их много, и судя по отзывам производительность сосёт https://www.google.ru/search?newwindow= ... d+lighting

Моя третья попытка сделать 2д тени:
Успех! Правда всё, чем этот способ лучше встроенных теней, это то, что в окне сцены выглядит не так всосно и то что можно нарисовать тени с разной прозрачностью без хитрой возни со слоями.
Изображение
Синтаксис:
Используется glsl
// Made with Amplify Shader Editor
// Available at the Unity Asset Store - http://u3d.as/y3X
Shader "Shadow2d"
{
        Properties
        {
                _Plane("Plane", Vector) = (1,0,1,0)
                _Color0("Color 0", Color) = (0,0,0,0)
                _Offset("Offset", Vector) = (0,0,0,0)
                [HideInInspector] __dirty( "", Int ) = 1
        }

        SubShader
        {
                Tags{ "RenderType" = "Custom"  "Queue" = "Transparent+0" "IgnoreProjector" = "True" "IsEmissive" = "true"  }
                Cull Back
                ZWrite Off
                Stencil
                {
                        Ref 1
                        Comp NotEqual
                        Pass Replace
                }
                Blend SrcAlpha OneMinusSrcAlpha
               
                CGPROGRAM
                #pragma target 3.0
                #pragma surface surf Unlit keepalpha noshadow noambient novertexlights nolightmap  nodynlightmap nodirlightmap nofog nometa noforwardadd vertex:vertexDataFunc
                struct Input
                {
                        half filler;
                };

                uniform float3 CastPos;
                uniform float3 _Plane;
                uniform float3 _Offset;
                uniform float4 _Color0;

                void vertexDataFunc( inout appdata_full v, out Input o )
                {
                        UNITY_INITIALIZE_OUTPUT( Input, o );
                        float3 ase_vertex3Pos = v.vertex.xyz;
                        float4 appendResult41 = (float4(ase_vertex3Pos , 1.0));
                        float4 transform26 = mul(unity_ObjectToWorld,appendResult41);
                        float4 appendResult42 = (float4(CastPos , 1.0));
                        float4 transform39 = mul(unity_WorldToObject,( ( ( transform26 - appendResult42 ) * float4( _Plane , 0.0 ) * v.color.r ) + float4( _Offset , 0.0 ) ));
                        v.vertex.xyz = ( transform39 + float4( ase_vertex3Pos , 0.0 ) ).xyz;
                }

                inline half4 LightingUnlit( SurfaceOutput s, half3 lightDir, half atten )
                {
                        return half4 ( 0, 0, 0, s.Alpha );
                }

                void surf( Input i , inout SurfaceOutput o )
                {
                        o.Emission = _Color0.rgb;
                        o.Alpha = _Color0.a;
                }

                ENDCG
        }
        CustomEditor "ASEMaterialInspector"
}
/*ASEBEGIN
Version=16201
1091;8;1895;984;1557.817;618.1328;1.6;True;False
Node;AmplifyShaderEditor.PosVertexDataNode;8;-1024.305,371.3244;Float;False;0;0;5;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4
Node;AmplifyShaderEditor.Vector3Node;15;-745.9826,190.6079;Float;False;Global;CastPos;CastPos;1;0;Create;True;0;0;False;0;0,0,0;30.98,0,-2.31;0;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3
Node;AmplifyShaderEditor.DynamicAppendNode;41;-996.3758,-118.1287;Float;False;FLOAT4;4;0;FLOAT3;0,0,0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;1;False;1;FLOAT4;0
Node;AmplifyShaderEditor.DynamicAppendNode;42;-668.3175,56.33099;Float;False;FLOAT4;4;0;FLOAT3;0,0,0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;1;False;1;FLOAT4;0
Node;AmplifyShaderEditor.ObjectToWorldTransfNode;26;-842.496,-141.0438;Float;False;1;0;FLOAT4;0,0,0,1;False;5;FLOAT4;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4
Node;AmplifyShaderEditor.Vector3Node;5;-456.3494,97.68843;Float;False;Property;_Plane;Plane;0;0;Create;True;0;0;False;0;1,0,1;10,0,10;0;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3
Node;AmplifyShaderEditor.VertexColorNode;7;-408.6138,248.9176;Float;False;0;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4
Node;AmplifyShaderEditor.SimpleSubtractOpNode;4;-481.1105,-93.74715;Float;False;2;0;FLOAT4;0,0,0,0;False;1;FLOAT4;0,0,0,0;False;1;FLOAT4;0
Node;AmplifyShaderEditor.Vector3Node;24;-114.4876,231.709;Float;False;Property;_Offset;Offset;3;0;Create;True;0;0;False;0;0,0,0;0,-0.5,0;0;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3
Node;AmplifyShaderEditor.SimpleMultiplyOpNode;6;-158.9209,63.06424;Float;False;3;3;0;FLOAT4;0,0,0,0;False;1;FLOAT3;0,0,0;False;2;FLOAT;0;False;1;FLOAT4;0
Node;AmplifyShaderEditor.SimpleAddOpNode;43;59.71889,116.5163;Float;False;2;2;0;FLOAT4;0,0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT4;0
Node;AmplifyShaderEditor.WorldToObjectTransfNode;39;205.8984,211.8971;Float;False;1;0;FLOAT4;0,0,0,1;False;5;FLOAT4;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4
Node;AmplifyShaderEditor.SimpleAddOpNode;17;510.1764,362.9408;Float;False;2;2;0;FLOAT4;0,0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT4;0
Node;AmplifyShaderEditor.ColorNode;18;423.6914,42.53105;Float;False;Property;_Color0;Color 0;1;0;Create;True;0;0;False;0;0,0,0,0;0,0,0,0.2862745;True;0;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4
Node;AmplifyShaderEditor.StandardSurfaceOutputNode;23;778.3077,184.1331;Float;False;True;2;Float;ASEMaterialInspector;0;0;Unlit;Shadow2d;False;False;False;False;True;True;True;True;True;True;True;True;False;False;True;False;False;False;False;False;Back;2;False;-1;0;False;-1;False;0;False;-1;0;False;-1;False;1;Custom;0.5;True;False;0;True;Custom;;Transparent;All;True;True;True;True;True;True;True;True;True;True;True;True;True;True;True;True;True;0;False;-1;True;1;False;-1;255;False;-1;255;False;-1;6;False;-1;3;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;False;2;15;10;25;False;0.5;False;2;5;False;-1;10;False;-1;0;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;0;0,0,0,0;VertexOffset;True;False;Cylindrical;False;Absolute;0;;2;-1;-1;-1;0;False;0;0;False;-1;-1;0;False;-1;0;0;0;15;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;2;FLOAT3;0,0,0;False;3;FLOAT;0;False;4;FLOAT;0;False;6;FLOAT3;0,0,0;False;7;FLOAT3;0,0,0;False;8;FLOAT;0;False;9;FLOAT;0;False;10;FLOAT;0;False;13;FLOAT3;0,0,0;False;11;FLOAT3;0,0,0;False;12;FLOAT3;0,0,0;False;14;FLOAT4;0,0,0,0;False;15;FLOAT3;0,0,0;False;0
WireConnection;41;0;8;0
WireConnection;42;0;15;0
WireConnection;26;0;41;0
WireConnection;4;0;26;0
WireConnection;4;1;42;0
WireConnection;6;0;4;0
WireConnection;6;1;5;0
WireConnection;6;2;7;1
WireConnection;43;0;6;0
WireConnection;43;1;24;0
WireConnection;39;0;43;0
WireConnection;17;0;39;0
WireConnection;17;1;8;0
WireConnection;23;2;18;0
WireConnection;23;9;18;4
WireConnection;23;11;17;0
ASEEND*/

//CHKSM=72B09891E7C7D29C7BDCD302B92777E899441CA1
 


Синтаксис:
Используется csharp
using UnityEngine;

[ExecuteInEditMode]
public class CasterPositionSetter : MonoBehaviour
{
    void Update()
    {
        Shader.SetGlobalVector("CastPos", transform.position);
    }
}
 

Геометрию тени можно подготовить следующим образом:
Делаем кубик
Удаляем дно и крышку
Верхние вершины красим в чёрный, нижние в красный
Скукоживаем вершины пока верхние и нижние не окажутся на одной плоскости.
Пакедж со тестом: https://yadi.sk/d/E4sq-9lRcBN_Cw

Аватара пользователя
waruiyume
Адепт
 
Сообщения: 6143
Зарегистрирован: 30 окт 2010, 05:03
Откуда: Ростов на Дону

Re: Туман войны для 2d игры

Сообщение MrDmitry 23 июл 2019, 07:56

Ваш вариант интересный, но он создает 2D тени на 3D сцене(Если я правильно понял), а у меня все же проект полностью 2D
MrDmitry
UNITрон
 
Сообщения: 223
Зарегистрирован: 05 авг 2017, 17:21

Re: Туман войны для 2d игры

Сообщение waruiyume 23 июл 2019, 08:34

Очень интересно, как это вы "проект полностью 2D" смогли сделать, если [unity 3D] всё своё "2D" рисует 3D геометрией на плоскости?
Аватара пользователя
waruiyume
Адепт
 
Сообщения: 6143
Зарегистрирован: 30 окт 2010, 05:03
Откуда: Ростов на Дону

Re: Туман войны для 2d игры

Сообщение MrDmitry 23 июл 2019, 08:59

У меня плоские спрайты, как я могу прикрепить ваш вариант? Переводить проект в 3D режим?
MrDmitry
UNITрон
 
Сообщения: 223
Зарегистрирован: 05 авг 2017, 17:21


Вернуться в Скрипты

Кто сейчас на конференции

Сейчас этот форум просматривают: Yandex [Bot] и гости: 12