摄像机区域的架构改动

This commit is contained in:
2026-05-15 14:47:24 +08:00
parent 1b37297585
commit f264329751
3591 changed files with 1687228 additions and 446503 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 71fb573462425de408507447a0bf2241
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,240 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
namespace SpriteShadersUltimate
{
[CustomEditor(typeof(InteractiveWindSSU)), CanEditMultipleObjects]
public class InteractiveWindSSUEditor : Editor
{
bool displaySetup;
bool displayTroubleshooting;
bool displayInformation;
public override void OnInspectorGUI()
{
//References:
GUIStyle style = new GUIStyle(GUI.skin.label);
style.richText = true;
InteractiveWindSSU wind = (InteractiveWindSSU)target;
//Header:
EditorGUILayout.BeginVertical("Helpbox");
EditorGUILayout.LabelField("<size=14><b>Interactive Wind</b></size>", style);
EditorGUILayout.LabelField(" ", GUILayout.Height(1));
DisplayHints(ref displaySetup, "Setup",
"- Attach this to a <b>SpriteRenderer</b> with the <b>Wind</b> shader.",
"- Set <b>Mesh Type</b> to <b>Full Rect</b> in the sprite's settings.",
"- Attach a <b>BoxCollider2D</b> to this gameobject.",
"- Set <b>Is Trigger</b> to true in the <b>BoxCollider2D</b>.",
"- Have a single active <b>WindManager</b> component in your scene.",
" ",
"- You can <b>flip</b> the shader for hanging objects.",
"- You can combine the shader with <b>UV Distort</b>."
);
EditorGUILayout.LabelField(" ", GUILayout.Height(1));
DisplayHints(ref displayTroubleshooting, "Troubleshooting",
" ",
"<b>Pixels are clipping out:</b>",
"- Make sure the sprite's <b>Mesh Type</b> is <b>Full Rect</b>.",
"- <b>Sprite Sheets</b> need the <b>Sprite Sheet Fix</b> option.",
"- Expand the sprite's texture horizontally with empty pixels.",
" ",
"<b>Wind is not visible:</b>",
"- Make sure the SpriteRenderer is using the <b>Wind</b> shader.",
"- If using a <b>Uber Shader</b> you need to enable <b>Wind</b>.",
"- Make sure you have a single active <b>WindManager</b> component.",
"- Check your <b>WindManager's</b> and <b>material's</b> settings.",
" ",
"<b>Physical interaction is not happening:</b>",
"- Check this <b>component's</b> and the <b>material's</b> settings.",
"- Make sure the <b>BoxCollider2D</b> is positioned properly.",
"- Set the <b>BoxCollider2D</b> to a <b>trigger</b>.",
"- Make sure a collision with the <b>BoxCollider2D</b> is happening.",
" "
);
EditorGUILayout.LabelField(" ", GUILayout.Height(1));
DisplayHints(ref displayInformation, "Information",
" ",
"<b>Summary:</b>",
"- Interaction will <b>bend</b> and <b>squish</b> the sprite.",
"- Can be used for <b>Grass, Trees, Chains, Vines</b> and more.",
" ",
"<b>Temporary Interaction:</b>",
"- Disable <b>Stay Bent</b> to have a temporary interaction.",
"- Only objects moving faster than <b>" + Mathf.RoundToInt(wind.minBendSpeed) + " unit/s</b> will interact.",
" "
);
EditorGUILayout.EndVertical();
EditorGUILayout.Space();
//Rotation:
EditorGUILayout.BeginVertical("Helpbox");
EditorGUILayout.LabelField("<b>Rotation:</b>", style);
EditorGUILayout.PropertyField(serializedObject.FindProperty("rotationFactor"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("bendInSpeed"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("bendOutSpeed"));
EditorGUILayout.EndVertical();
EditorGUILayout.Space();
//Temporary:
EditorGUILayout.BeginVertical("Helpbox");
EditorGUILayout.LabelField("<b>Method:</b>", style);
EditorGUILayout.PropertyField(serializedObject.FindProperty("stayBent"));
if(!wind.stayBent)
{
EditorGUILayout.PropertyField(serializedObject.FindProperty("minBendSpeed"));
}
EditorGUILayout.EndVertical();
EditorGUILayout.Space();
//Hyper Performance:
EditorGUILayout.BeginVertical("Helpbox");
EditorGUILayout.LabelField("<b>Hyper Performance:</b>", style);
EditorGUILayout.PropertyField(serializedObject.FindProperty("hyperPerformanceMode"));
if (wind.hyperPerformanceMode)
{
EditorGUILayout.PropertyField(serializedObject.FindProperty("randomOffsetZ"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("customMaterial"));
if (wind.customMaterial)
{
EditorGUILayout.PropertyField(serializedObject.FindProperty("inactiveMaterial"));
}
else
{
EditorGUILayout.PropertyField(serializedObject.FindProperty("inactiveShader"));
}
//Hint:
GUI.color = new Color(1, 1, 1, 0.7f);
EditorGUILayout.LabelField("- GPU performance boost for <b>lowest-end</b> mobile phones.", style);
if(!wind.customMaterial)
{
EditorGUILayout.LabelField("- Sets the shader to <b>" + wind.inactiveShader + "</b> while inactive.", style);
}
else
{
if(wind.inactiveMaterial != null)
{
EditorGUILayout.LabelField("- Sets the material to <b>" + wind.inactiveMaterial.name + "</b> while inactive.", style);
}
else
{
GUIStyle warningStyle = new GUIStyle(GUI.skin.label);
warningStyle.richText = true;
if (EditorGUIUtility.isProSkin)
{
warningStyle.normal.textColor = new Color(1, 0.7f, 0.7f, 1);
}
else
{
warningStyle.normal.textColor = new Color(0.3f, 0f, 0f, 1);
}
EditorGUILayout.LabelField("- Please reference a material in <b>Inactive Material</b>.", warningStyle);
}
}
EditorGUILayout.LabelField("- Use this if you want <b>physical interaction</b> but don't need <b>Wind</b>.", style);
EditorGUILayout.LabelField("- You must set <b>Rotation Wind Factor</b> to <b>0</b> in the material.", style);
EditorGUILayout.Space();
EditorGUILayout.LabelField("- Enabling <b>Random Offset Z</b> will prevent resorting of render order.", style);
GUI.color = Color.white;
}
EditorGUILayout.EndVertical();
EditorGUILayout.Space();
//Other:
EditorGUILayout.BeginVertical("Helpbox");
EditorGUILayout.LabelField("<b>Other:</b>", style);
EditorGUILayout.PropertyField(serializedObject.FindProperty("randomizeWiggle"));
EditorGUILayout.PropertyField(serializedObject.FindProperty("allowCustomLayer"));
EditorGUILayout.EndVertical();
serializedObject.ApplyModifiedProperties();
//Fix Layer:
if(wind.gameObject.layer != 2 && !wind.allowCustomLayer)
{
wind.gameObject.layer = 2;
}
//Fix BoxCollider2D:
BoxCollider2D boxCollider = wind.gameObject.GetComponent<BoxCollider2D>();
if(boxCollider == null)
{
//Create new BoxCollider2D:
boxCollider = wind.gameObject.AddComponent<BoxCollider2D>();
boxCollider.isTrigger = true;
}
//Fix Variables:
if(wind.bendInSpeed < 0)
{
wind.bendInSpeed = 0;
}
if (wind.bendOutSpeed < 0)
{
wind.bendOutSpeed = 0;
}
if (wind.minBendSpeed < 0)
{
wind.minBendSpeed = 0;
}
}
void DisplayHints(ref bool toggleVariable, string title,params string[] lines)
{
GUIStyle style = new GUIStyle(GUI.skin.label);
style.richText = true;
GUIStyle button = new GUIStyle(GUI.skin.button);
button.richText = true;
if (toggleVariable)
{
GUI.color = new Color(1, 1, 1, 0.7f);
}
else
{
GUI.color = new Color(1, 1, 1, 0.5f);
}
title = "<b>" + title + "</b>";
EditorGUILayout.BeginVertical(GUI.skin.box);
EditorGUILayout.BeginHorizontal();
GUI.color = Color.white;
EditorGUILayout.LabelField(title, style);
if (GUILayout.Button("<size=10>" + (toggleVariable ? "▼" : "▲") + "</size>", button, GUILayout.Width(20)))
{
toggleVariable = !toggleVariable;
}
EditorGUILayout.EndHorizontal();
if (toggleVariable == true)
{
GUI.color = new Color(1, 1, 1, 0.7f);
for(int l = 0; l < lines.Length; l++)
{
if(lines[l] == " ")
{
EditorGUILayout.LabelField(lines[l], style,GUILayout.Height(6));
}
else
{
EditorGUILayout.LabelField(lines[l], style);
}
}
}
GUI.color = Color.white;
EditorGUILayout.EndVertical();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fe9161b8dce72364680eee7fa2e4853b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,34 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
namespace SpriteShadersUltimate
{
[CustomEditor(typeof(WindManagerSSU)), CanEditMultipleObjects]
public class WindManagerSSUEditor : Editor
{
public override void OnInspectorGUI()
{
//Draw Inspector:
base.OnInspectorGUI();
//References:
GUIStyle style = new GUIStyle(GUI.skin.label);
style.richText = true;
//Info Box:
EditorGUILayout.Space();
EditorGUILayout.BeginVertical("Helpbox");
EditorGUILayout.LabelField("<b><size=14>Information</size></b>", style);
GUI.color = new Color(1, 1, 1, 0.7f);
EditorGUILayout.LabelField("- This component will handle the global wind settings.", style);
EditorGUILayout.LabelField("- Only have one active <b>WindManager</b> at a time.", style);
EditorGUILayout.LabelField("- This updates the global variables used by my <b>wind shader</b>.", style);
GUI.color = new Color(1, 1, 1, 1f);
EditorGUILayout.EndVertical();
serializedObject.ApplyModifiedProperties();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c51829b6566625342bc6a1469388a8c2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,25 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
namespace SpriteShadersUltimate
{
[CustomEditor(typeof(WindParallaxSSU))]
public class WindParallaxSSUEditor : Editor
{
public override void OnInspectorGUI()
{
GUIStyle style = new GUIStyle(GUI.skin.label);
style.richText = true;
EditorGUILayout.BeginVertical("Helpbox");
GUI.color = new Color(1, 1, 1, 0.7f);
EditorGUILayout.LabelField("Fixes <b>parallax</b> or <b>movement</b> issues for the <b>Wind</b> shader.", style);
EditorGUILayout.LabelField("Attach this to <b>sprite renderers</b> and enable <b>Is Parallax</b>.", style);
EditorGUILayout.LabelField("Set's <b>X Position</b> on <b>Awake()</b> to a static value.", style);
GUI.color = Color.white;
EditorGUILayout.EndVertical();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0c1ff3a724f59354d8c3234f3a894521
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,64 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class InteractiveSquishSSU : MonoBehaviour
{
[Header("Settings:")]
public float squishSpeed = 5f;
public bool staySquished = true;
public float squishDuration = 0.1f;
//References:
Material mat;
//Internal:
float currentSquish;
float lastTriggerStayTime;
void Start()
{
mat = GetComponent<SpriteRenderer>().material;
currentSquish = 0f;
}
void OnTriggerStay2D(Collider2D collision)
{
if (staySquished)
{
lastTriggerStayTime = Time.time;
}
}
void OnTriggerEnter2D(Collider2D collision)
{
lastTriggerStayTime = Time.time;
}
void Update()
{
float newSquish = currentSquish;
if(Time.time > lastTriggerStayTime + squishDuration)
{
newSquish = Mathf.Lerp(newSquish, -0.1f, Time.deltaTime * squishSpeed);
}
else
{
newSquish = Mathf.Lerp(newSquish, 1.1f, Time.deltaTime * squishSpeed);
}
newSquish = Mathf.Clamp01(newSquish);
if(newSquish != currentSquish)
{
currentSquish = newSquish;
UpdateSquish();
}
}
void UpdateSquish()
{
mat.SetFloat("_SquishFade", currentSquish);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a81f379efd25989449160ecd5ad450b8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,254 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace SpriteShadersUltimate
{
public class InteractiveWindSSU : InstancerSSU
{
[Tooltip("How much physical interaction bends the sprite.")]
public float rotationFactor = 1.5f;
[Tooltip("How fast physical interaction bending fades in.")]
public float bendInSpeed = 8f;
[Tooltip("How fast physical interaction bending fades out.")]
public float bendOutSpeed = 8f;
[Tooltip("If disabled the sprite will only bend during active movement.")]
public bool stayBent = true;
[Tooltip("The minimum speed of the interacting object to trigger bending.")]
public float minBendSpeed = 1f;
[Tooltip("Swaps the material with the default sprite material while inactive.")]
public bool hyperPerformanceMode = false;
[Tooltip("Adds a tiny little offset to the Z position on start.\nTo prevent random resorting of render order.")]
public bool randomOffsetZ = true;
[Tooltip("Define a material to switch to while inactive.")]
public bool customMaterial = false;
[Tooltip("The shader used for the default sprite material.")]
public string inactiveShader = "Sprites/Default";
[Tooltip("The material used when inactive.")]
public Material inactiveMaterial;
[Tooltip("Slightly changes 'Wiggle Frequency', to desync the wiggle shaders of multiple sprites.")]
public bool randomizeWiggle = false;
[Tooltip("The editor-side script set's the layer to 'Ignore Raycast' to fix potential issues. Enable this to disable that and set the layer to a different one.")]
public bool allowCustomLayer = false;
//Variables:
HashSet<Collider2D> collidersInside;
BoxCollider2D boxCollider;
//Runtime:
float currentBending;
float currentRotationDirection;
bool isActive;
bool newDirection;
float lastPosition;
float lastBend;
float currentBendTarget;
bool bentInLastFrame;
SpriteRenderer sr;
static Material defaultMaterial;
int rotationId;
void Start()
{
//Initialize Variables:
collidersInside = new HashSet<Collider2D>();
boxCollider = GetComponent<BoxCollider2D>();
sr = GetComponent<SpriteRenderer>();
runtimeMaterial = sr.material;
if(defaultMaterial == null)
{
if (customMaterial)
{
defaultMaterial = inactiveMaterial;
}
else
{
defaultMaterial = new Material(Shader.Find(inactiveShader));
}
}
if(hyperPerformanceMode)
{
sr.material = defaultMaterial;
if(randomOffsetZ)
{
//Prevent Resorting:
Vector3 position = transform.position;
position.z += Random.value * 0.1f;
transform.position = position;
}
}
if(randomizeWiggle && runtimeMaterial != null)
{
float wiggleFrequency = runtimeMaterial.GetFloat("_WiggleFrequency") * (0.9f + 0.2f * Random.value);
runtimeMaterial.SetFloat("_WiggleFrequency", wiggleFrequency);
}
rotationId = Shader.PropertyToID("_WindRotation");
}
void FixedUpdate()
{
if (isActive == false) return;
Vector2 localPosition = new Vector2(0, -1000000);
foreach(Collider2D collider in collidersInside)
{
if(collider != null)
{
if(localPosition.y < -99999)
{
localPosition = collider.bounds.center - transform.position; //Collider Position
}
else
{
if (!newDirection) {
Vector2 newLocalPosition = (collider.bounds.center - transform.position);
if((currentRotationDirection < 0 && newLocalPosition.x > localPosition.x) || (currentRotationDirection > 0 && newLocalPosition.x < localPosition.x))
{
localPosition = newLocalPosition; //Take most heavy position
}
}
else
{
localPosition = ((Vector2)(collider.bounds.center - transform.position) + localPosition) * 0.5f; //Position Deviation (multiple colliders)
}
}
}
}
if (localPosition.y > -99999) //Colliders are interacting with the wind sprite.
{
//Bend Direction:
if (newDirection)
{
if(localPosition.x < 0)
{
currentRotationDirection = -1;
}else
{
currentRotationDirection = 1;
}
newDirection = false;
}
//Bend Target:
float targetBending = 0;
if(currentRotationDirection < 0)
{
targetBending = Mathf.Clamp01((localPosition.x + boxCollider.size.x * 0.5f) / boxCollider.size.x);
}
else
{
targetBending = Mathf.Clamp01((boxCollider.size.x * 0.5f - localPosition.x) / boxCollider.size.x);
}
if(stayBent)
{
//Staying Bend:
currentBendTarget = targetBending;
}
else
{
//Temporary Bend:
bool moved = Mathf.Abs(lastPosition - localPosition.x) > Time.fixedDeltaTime * minBendSpeed;
if(moved && lastBend != 0 && currentRotationDirection > 0 == (localPosition.x - lastPosition) > 0)
{
moved = false;
}
if (moved || bentInLastFrame)
{
currentBendTarget = targetBending;
lastBend = targetBending;
bentInLastFrame = true;
if (!moved)
{
bentInLastFrame = false;
}
}
else
{
currentBendTarget = Mathf.Lerp(currentBendTarget, 0, Time.fixedDeltaTime * bendInSpeed);
if (Mathf.Abs(currentBending) < 0.01f)
{
newDirection = true;
}
}
lastPosition = localPosition.x;
}
//Fade In Bending:
currentBending += (currentBendTarget * currentRotationDirection - currentBending) * Mathf.Min(bendInSpeed * Time.fixedDeltaTime, 1);
UpdateShader();
}
else
{
//Fade Out Bending:
currentBending -= currentBending * Mathf.Min(bendOutSpeed * Time.fixedDeltaTime,1);
UpdateShader();
if (Mathf.Abs(currentBending) < 0.005f)
{
isActive = false;
lastBend = 0;
if (hyperPerformanceMode)
{
sr.material = defaultMaterial;
}
}
}
}
public void UpdateShader()
{
runtimeMaterial.SetFloat(rotationId, -1f * currentBending * rotationFactor);
}
void OnTriggerEnter2D(Collider2D collision)
{
if(collidersInside.Count == 0 || Mathf.Abs(currentBending) < 0.2f)
{
newDirection = true;
}
collidersInside.Add(collision);
if (hyperPerformanceMode && isActive == false)
{
sr.material = runtimeMaterial;
}
isActive = true;
}
void OnTriggerExit2D(Collider2D collision)
{
if (collidersInside.Contains(collision))
{
collidersInside.Remove(collision);
}
}
//Other:
public static void DefaultCollider(BoxCollider2D box)
{
box.isTrigger = true;
box.size = new Vector2(2, 1);
box.offset = new Vector2(0, -0.5f);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9fa14830c2cebb942b11ced84dbab634
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,53 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace SpriteShadersUltimate
{
public class WindManagerSSU : MonoBehaviour
{
[Header("Settings:")]
[Tooltip("Smaller values will result in more frequent changes in wind.")]
public float windNoiseScale = 0.1f;
private float lastWindNoiseScale;
[Tooltip("Speed at which the wind pattern moves horizontally.")]
public float windNoiseSpeed = 1;
[Tooltip("The wind intensity will be between this value and 'Wind Intensity To'.")]
public float windIntensityFrom = -0.4f;
private float lastWindIntensityFrom;
[Tooltip("The wind intensity will be between this value and 'Wind Intensity From'.")]
public float windIntensityTo = 0.4f;
private float lastWindIntensityTo;
//Runtime:
float currentTime;
void Start()
{
currentTime = 0;
}
void FixedUpdate()
{
ModifyIfChanged(ref windNoiseScale,ref lastWindNoiseScale, "WindNoiseScale");
ModifyIfChanged(ref windIntensityFrom, ref lastWindIntensityFrom, "WindMinIntensity");
ModifyIfChanged(ref windIntensityTo, ref lastWindIntensityTo, "WindMaxIntensity");
currentTime += Time.fixedDeltaTime * windNoiseSpeed;
Shader.SetGlobalFloat("WindTime", currentTime);
}
public void ModifyIfChanged(ref float currentValue, ref float oldValue, string globalShaderName)
{
if(oldValue != currentValue)
{
oldValue = currentValue;
Shader.SetGlobalFloat(globalShaderName, currentValue);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 22dc68242d36c804f80751218b65e768
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 394972c0895cd9d49a5892a6c9c9ac2d, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,21 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace SpriteShadersUltimate
{
public class WindParallaxSSU : MonoBehaviour
{
float originalXPosition;
void Awake()
{
originalXPosition = transform.position.x;
}
void Start()
{
GetComponent<Renderer>().material.SetFloat("_WindXPosition", originalXPosition);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1335c4c1d648f6e48b60f23fa12ffe6c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: