chunk 1: core gameplay scripts scenes runtime assets
This commit is contained in:
706
Assets/Scripts/Editor/WaitingSceneTemplate.cs
Normal file
706
Assets/Scripts/Editor/WaitingSceneTemplate.cs
Normal file
@@ -0,0 +1,706 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEditor.SceneManagement;
|
||||
using Cinemachine;
|
||||
using TMPro;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
public class WaitingSceneTemplate : EditorWindow
|
||||
{
|
||||
[UnityEditor.MenuItem("Tools/Create Waiting Scene")]
|
||||
public static void CreateWaitingScene()
|
||||
{
|
||||
// Create a new scene
|
||||
var scene = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single);
|
||||
|
||||
// Create a basic scene setup
|
||||
CreateSceneSetup();
|
||||
|
||||
// Save the scene
|
||||
EditorSceneManager.SaveScene(scene, "Assets/Scenes/WaitingScene.unity");
|
||||
|
||||
Debug.Log("Waiting Scene created successfully!");
|
||||
}
|
||||
|
||||
private static void CreateSceneSetup()
|
||||
{
|
||||
// Create main camera
|
||||
var mainCamera = new GameObject("MainCamera");
|
||||
var camera = mainCamera.AddComponent<Camera>();
|
||||
mainCamera.tag = "MainCamera";
|
||||
camera.clearFlags = CameraClearFlags.Skybox;
|
||||
mainCamera.transform.position = new Vector3(0, 2, -10);
|
||||
|
||||
// Create Post-processing layer in project if needed
|
||||
CreateLayerIfNeeded("PostProcessing", 8);
|
||||
|
||||
// Ensure Ground layer exists
|
||||
CreateLayerIfNeeded("Ground", 9);
|
||||
|
||||
// Set up cinematic lighting
|
||||
CreateCinematicLighting();
|
||||
|
||||
// Set up atmospheric effects
|
||||
AddAtmosphericEffects();
|
||||
|
||||
// Set up post-processing
|
||||
CreatePostProcessingVolume();
|
||||
|
||||
// Create a dolly track with front viewing positions
|
||||
var dollyTrack = new GameObject("DollyTrack");
|
||||
var path = dollyTrack.AddComponent<CinemachineSmoothPath>();
|
||||
path.m_Waypoints = new CinemachineSmoothPath.Waypoint[5];
|
||||
|
||||
// Set up waypoints for a front-facing path where camera is in front of player
|
||||
// First point - directly in front of player, facing back toward spawn point
|
||||
path.m_Waypoints[0] = new CinemachineSmoothPath.Waypoint {
|
||||
position = new Vector3(0, 1.7f, -15),
|
||||
roll = 0
|
||||
};
|
||||
|
||||
// Second point - farther ahead (closer to beginning)
|
||||
path.m_Waypoints[1] = new CinemachineSmoothPath.Waypoint {
|
||||
position = new Vector3(0, 1.9f, -10),
|
||||
roll = 2 // Slight roll
|
||||
};
|
||||
|
||||
// Third point - far ahead (midway to beginning)
|
||||
path.m_Waypoints[2] = new CinemachineSmoothPath.Waypoint {
|
||||
position = new Vector3(0, 2.1f, -5),
|
||||
roll = -2 // Opposite roll
|
||||
};
|
||||
|
||||
// Fourth point - close to end (near beginning)
|
||||
path.m_Waypoints[3] = new CinemachineSmoothPath.Waypoint {
|
||||
position = new Vector3(0, 2.3f, -2),
|
||||
roll = 3 // More roll
|
||||
};
|
||||
|
||||
// Fifth point - final camera position (at beginning of path)
|
||||
path.m_Waypoints[4] = new CinemachineSmoothPath.Waypoint {
|
||||
position = new Vector3(0, 2.5f, 0),
|
||||
roll = 0 // Level out
|
||||
};
|
||||
|
||||
// Create a dolly camera
|
||||
var dollyCamera = new GameObject("DollyCamera");
|
||||
var virtualCamera = dollyCamera.AddComponent<CinemachineVirtualCamera>();
|
||||
virtualCamera.m_Priority = 10;
|
||||
virtualCamera.m_Lens.FieldOfView = 35; // Narrower FOV for more cinematic effect
|
||||
|
||||
// Add noise for handheld feel
|
||||
var noise = virtualCamera.AddCinemachineComponent<CinemachineBasicMultiChannelPerlin>();
|
||||
noise.m_AmplitudeGain = 0.15f; // Subtle shake
|
||||
noise.m_FrequencyGain = 0.3f;
|
||||
|
||||
// Set up composer for proper framing
|
||||
var composer = virtualCamera.AddCinemachineComponent<CinemachineComposer>();
|
||||
composer.m_TrackedObjectOffset = new Vector3(0, 0.5f, 0);
|
||||
composer.m_LookaheadTime = 0.2f;
|
||||
composer.m_DeadZoneWidth = 0.1f;
|
||||
composer.m_DeadZoneHeight = 0.1f;
|
||||
composer.m_SoftZoneWidth = 0.6f;
|
||||
composer.m_SoftZoneHeight = 0.6f;
|
||||
|
||||
// Set up transposer for smoother camera movement
|
||||
var transposer = virtualCamera.AddCinemachineComponent<CinemachineTransposer>();
|
||||
transposer.m_XDamping = 1f;
|
||||
transposer.m_YDamping = 1f;
|
||||
transposer.m_ZDamping = 1f;
|
||||
|
||||
// Set slight Dutch angle
|
||||
virtualCamera.m_Lens.Dutch = 2f;
|
||||
|
||||
// Add dolly cart
|
||||
var dollyCart = new GameObject("DollyCart");
|
||||
var cart = dollyCart.AddComponent<CinemachineDollyCart>();
|
||||
cart.m_Path = path;
|
||||
cart.m_Speed = 0f; // Initially stopped - will be controlled by script
|
||||
virtualCamera.transform.SetParent(dollyCart.transform);
|
||||
|
||||
// Create corridor-style entrance environment
|
||||
CreateEntranceEnvironment();
|
||||
|
||||
// Create spawn point - positioned for player to face TOWARD camera (changed direction)
|
||||
var spawnPoint = new GameObject("SpawnPoint");
|
||||
spawnPoint.transform.position = new Vector3(0, 0, -20); // Keep position but will make player face opposite direction
|
||||
|
||||
// Create UI canvas
|
||||
var canvas = new GameObject("Canvas", typeof(Canvas), typeof(UnityEngine.UI.CanvasScaler), typeof(UnityEngine.UI.GraphicRaycaster));
|
||||
var canvasComponent = canvas.GetComponent<Canvas>();
|
||||
canvasComponent.renderMode = RenderMode.ScreenSpaceOverlay;
|
||||
|
||||
// Create skip button - properly create UI elements with RectTransform
|
||||
var skipButton = new GameObject("SkipButton", typeof(RectTransform), typeof(UnityEngine.UI.Image));
|
||||
skipButton.transform.SetParent(canvas.transform, false);
|
||||
var buttonComponent = skipButton.AddComponent<UnityEngine.UI.Button>();
|
||||
var buttonRect = skipButton.GetComponent<RectTransform>();
|
||||
buttonRect.anchoredPosition = new Vector2(0, -200);
|
||||
buttonRect.sizeDelta = new Vector2(200, 50);
|
||||
|
||||
var buttonText = new GameObject("Text", typeof(RectTransform));
|
||||
buttonText.transform.SetParent(skipButton.transform, false);
|
||||
var text = buttonText.AddComponent<TMPro.TextMeshProUGUI>();
|
||||
text.text = "Skip";
|
||||
text.fontSize = 24;
|
||||
text.alignment = TMPro.TextAlignmentOptions.Center;
|
||||
var textRect = buttonText.GetComponent<RectTransform>();
|
||||
textRect.anchorMin = Vector2.zero;
|
||||
textRect.anchorMax = Vector2.one;
|
||||
textRect.sizeDelta = Vector2.zero;
|
||||
|
||||
// Create countdown text
|
||||
var countdownText = new GameObject("CountdownText", typeof(RectTransform));
|
||||
countdownText.transform.SetParent(canvas.transform, false);
|
||||
var countdown = countdownText.AddComponent<TMPro.TextMeshProUGUI>();
|
||||
countdown.text = "10";
|
||||
countdown.fontSize = 36;
|
||||
countdown.alignment = TMPro.TextAlignmentOptions.Center;
|
||||
var countdownRect = countdownText.GetComponent<RectTransform>();
|
||||
countdownRect.anchoredPosition = new Vector2(0, 200);
|
||||
countdownRect.sizeDelta = new Vector2(100, 50);
|
||||
|
||||
// Create loading overlay
|
||||
var loadingOverlay = new GameObject("LoadingOverlay", typeof(RectTransform), typeof(UnityEngine.UI.Image));
|
||||
loadingOverlay.transform.SetParent(canvas.transform, false);
|
||||
var loadingImage = loadingOverlay.GetComponent<UnityEngine.UI.Image>();
|
||||
loadingImage.color = new Color(0, 0, 0, 0.8f);
|
||||
var loadingRect = loadingOverlay.GetComponent<RectTransform>();
|
||||
loadingRect.anchorMin = Vector2.zero;
|
||||
loadingRect.anchorMax = Vector2.one;
|
||||
loadingRect.sizeDelta = Vector2.zero;
|
||||
loadingOverlay.SetActive(false);
|
||||
|
||||
// Create waiting scene manager
|
||||
var manager = new GameObject("WaitingSceneManager");
|
||||
var waitingSceneManager = manager.AddComponent<WaitingSceneManager>();
|
||||
waitingSceneManager.spawnPoint = spawnPoint.transform;
|
||||
waitingSceneManager.dollyCart = cart;
|
||||
waitingSceneManager.dollyCamera = virtualCamera;
|
||||
waitingSceneManager.skipButton = buttonComponent;
|
||||
waitingSceneManager.countdownText = countdown;
|
||||
waitingSceneManager.loadingOverlay = loadingOverlay;
|
||||
|
||||
// Setup cinematic lights reference
|
||||
var lights = GameObject.Find("CinematicLighting")?.GetComponentsInChildren<Light>();
|
||||
if (lights != null && lights.Length > 0)
|
||||
{
|
||||
waitingSceneManager.cinematicLights = lights;
|
||||
}
|
||||
|
||||
// Setup atmospheric effects reference
|
||||
var atmosphericEffectsObj = GameObject.Find("AtmosphericEffects");
|
||||
if (atmosphericEffectsObj != null)
|
||||
{
|
||||
// Get all child objects and convert to array
|
||||
int childCount = atmosphericEffectsObj.transform.childCount;
|
||||
var effectsList = new GameObject[childCount];
|
||||
for (int i = 0; i < childCount; i++)
|
||||
{
|
||||
effectsList[i] = atmosphericEffectsObj.transform.GetChild(i).gameObject;
|
||||
}
|
||||
waitingSceneManager.atmosphericEffects = effectsList;
|
||||
}
|
||||
|
||||
// Setup audio references from resources
|
||||
waitingSceneManager.dramaticMusic = Resources.Load<AudioClip>("Sounds/DramaticEntrance");
|
||||
waitingSceneManager.crowdCheering = Resources.Load<AudioClip>("Sounds/CrowdCheering");
|
||||
|
||||
// If sounds aren't found, try to create placeholder sounds
|
||||
if (waitingSceneManager.dramaticMusic == null)
|
||||
{
|
||||
Debug.LogWarning("DramaticEntrance audio clip not found. Create a 'Sounds/DramaticEntrance' audio clip in Resources folder for best experience.");
|
||||
}
|
||||
|
||||
if (waitingSceneManager.crowdCheering == null)
|
||||
{
|
||||
Debug.LogWarning("CrowdCheering audio clip not found. Create a 'Sounds/CrowdCheering' audio clip in Resources folder for best experience.");
|
||||
}
|
||||
}
|
||||
|
||||
private static void CreateCinematicLighting()
|
||||
{
|
||||
// Create a lighting rig parent object
|
||||
var lightingRig = new GameObject("CinematicLighting");
|
||||
|
||||
// Create three-point lighting system for night-time dramatic effect
|
||||
|
||||
// 1. Key Light - main illumination from front-right
|
||||
var keyLight = new GameObject("KeyLight");
|
||||
keyLight.transform.SetParent(lightingRig.transform);
|
||||
var keyLightComponent = keyLight.AddComponent<Light>();
|
||||
keyLightComponent.type = LightType.Spot;
|
||||
keyLightComponent.color = new Color(0.9f, 0.85f, 0.7f); // Warmer for night
|
||||
keyLightComponent.intensity = 2.5f; // Brighter for contrast against dark
|
||||
keyLightComponent.range = 50f;
|
||||
keyLightComponent.spotAngle = 50f; // Narrower for more dramatic shadows
|
||||
keyLightComponent.shadows = LightShadows.Soft;
|
||||
keyLightComponent.shadowStrength = 0.9f; // Stronger shadows
|
||||
keyLight.transform.position = new Vector3(5, 10, -5);
|
||||
keyLight.transform.LookAt(new Vector3(0, 1, -15)); // Look at player's expected walk path
|
||||
|
||||
// 2. Fill Light - softer light from opposite side to reduce shadows
|
||||
var fillLight = new GameObject("FillLight");
|
||||
fillLight.transform.SetParent(lightingRig.transform);
|
||||
var fillLightComponent = fillLight.AddComponent<Light>();
|
||||
fillLightComponent.type = LightType.Spot;
|
||||
fillLightComponent.color = new Color(0.5f, 0.6f, 0.9f); // Cool moonlight-like color
|
||||
fillLightComponent.intensity = 0.8f; // Lower intensity than key
|
||||
fillLightComponent.range = 50f;
|
||||
fillLightComponent.spotAngle = 70f; // Wider angle
|
||||
fillLightComponent.shadows = LightShadows.Soft;
|
||||
fillLightComponent.shadowStrength = 0.5f; // Softer shadows
|
||||
fillLight.transform.position = new Vector3(-8, 8, -10);
|
||||
fillLight.transform.LookAt(new Vector3(0, 1, -15));
|
||||
|
||||
// 3. Rim Light (Back Light) - creates outline/separation
|
||||
var rimLight = new GameObject("RimLight");
|
||||
rimLight.transform.SetParent(lightingRig.transform);
|
||||
var rimLightComponent = rimLight.AddComponent<Light>();
|
||||
rimLightComponent.type = LightType.Spot;
|
||||
rimLightComponent.color = new Color(0.7f, 0.8f, 1f); // Blue-tinted moonlight
|
||||
rimLightComponent.intensity = 2.8f; // Brighter to create rim effect
|
||||
rimLightComponent.range = 40f;
|
||||
rimLightComponent.spotAngle = 40f; // Narrower
|
||||
rimLightComponent.shadows = LightShadows.Hard; // Harder shadows for definition
|
||||
rimLightComponent.shadowStrength = 0.8f;
|
||||
rimLight.transform.position = new Vector3(0, 7, 5); // Behind player's walk path
|
||||
rimLight.transform.LookAt(new Vector3(0, 1, -15));
|
||||
|
||||
// 4. Dramatic Spotlight - for emphasis
|
||||
var spotLight = new GameObject("DramaticSpotlight");
|
||||
spotLight.transform.SetParent(lightingRig.transform);
|
||||
var spotLightComponent = spotLight.AddComponent<Light>();
|
||||
spotLightComponent.type = LightType.Spot;
|
||||
spotLightComponent.color = new Color(1f, 0.9f, 0.7f); // Warm dramatic light
|
||||
spotLightComponent.intensity = 3.5f; // Much brighter for night scene
|
||||
spotLightComponent.range = 30f;
|
||||
spotLightComponent.spotAngle = 25f; // Narrower beam for spotlight effect
|
||||
spotLightComponent.shadows = LightShadows.Soft;
|
||||
spotLightComponent.shadowStrength = 0.9f;
|
||||
spotLight.transform.position = new Vector3(0, 15, -15); // Above player's final position
|
||||
spotLight.transform.LookAt(new Vector3(0, 0, -15));
|
||||
|
||||
// 5. Ambient Floor Light - subtle uplighting
|
||||
var floorLight = new GameObject("FloorLight");
|
||||
floorLight.transform.SetParent(lightingRig.transform);
|
||||
var floorLightComponent = floorLight.AddComponent<Light>();
|
||||
floorLightComponent.type = LightType.Point;
|
||||
floorLightComponent.color = new Color(0.2f, 0.3f, 0.6f); // Blue-ish floor bounce
|
||||
floorLightComponent.intensity = 0.7f; // Subtle but visible
|
||||
floorLightComponent.range = 10f;
|
||||
floorLightComponent.shadows = LightShadows.None; // No shadows for ambient
|
||||
floorLight.transform.position = new Vector3(0, 0.1f, -15); // Just above floor
|
||||
|
||||
// 6. Add accent lights along the path for night-time effect
|
||||
for (int i = -20; i <= 0; i += 10)
|
||||
{
|
||||
// Left accent light
|
||||
var leftAccent = new GameObject($"LeftAccent_{i}");
|
||||
leftAccent.transform.SetParent(lightingRig.transform);
|
||||
var leftAccentLight = leftAccent.AddComponent<Light>();
|
||||
leftAccentLight.type = LightType.Point;
|
||||
leftAccentLight.color = new Color(0.1f, 0.2f, 0.7f); // Blue night light
|
||||
leftAccentLight.intensity = 1.5f;
|
||||
leftAccentLight.range = 8f;
|
||||
leftAccentLight.shadows = LightShadows.Soft;
|
||||
leftAccent.transform.position = new Vector3(-3, 0.5f, i);
|
||||
|
||||
// Right accent light
|
||||
var rightAccent = new GameObject($"RightAccent_{i}");
|
||||
rightAccent.transform.SetParent(lightingRig.transform);
|
||||
var rightAccentLight = rightAccent.AddComponent<Light>();
|
||||
rightAccentLight.type = LightType.Point;
|
||||
rightAccentLight.color = new Color(0.1f, 0.2f, 0.7f); // Blue night light
|
||||
rightAccentLight.intensity = 1.5f;
|
||||
rightAccentLight.range = 8f;
|
||||
rightAccentLight.shadows = LightShadows.Soft;
|
||||
rightAccent.transform.position = new Vector3(3, 0.5f, i);
|
||||
}
|
||||
|
||||
// Configure scene lighting settings for night-time
|
||||
RenderSettings.ambientMode = UnityEngine.Rendering.AmbientMode.Flat;
|
||||
RenderSettings.ambientLight = new Color(0.05f, 0.05f, 0.1f); // Very dark blue ambient for night
|
||||
RenderSettings.ambientIntensity = 0.2f; // Low ambient intensity
|
||||
RenderSettings.fog = true;
|
||||
RenderSettings.fogColor = new Color(0.02f, 0.02f, 0.05f); // Very dark night fog
|
||||
RenderSettings.fogMode = FogMode.Exponential;
|
||||
RenderSettings.fogDensity = 0.03f; // Slightly thicker fog for atmosphere
|
||||
|
||||
// Set night skybox if available
|
||||
Shader skyboxShader = Shader.Find("Skybox/Procedural");
|
||||
if (skyboxShader != null)
|
||||
{
|
||||
Material skyboxMaterial = new Material(skyboxShader);
|
||||
// Darker sky settings
|
||||
skyboxMaterial.SetFloat("_SunSize", 0.05f);
|
||||
skyboxMaterial.SetFloat("_AtmosphereThickness", 0.5f);
|
||||
skyboxMaterial.SetColor("_SkyTint", new Color(0.3f, 0.3f, 0.5f));
|
||||
skyboxMaterial.SetColor("_GroundColor", new Color(0.1f, 0.1f, 0.1f));
|
||||
skyboxMaterial.SetFloat("_Exposure", 0.8f);
|
||||
|
||||
RenderSettings.skybox = skyboxMaterial;
|
||||
}
|
||||
|
||||
Debug.Log("Created night-time cinematic lighting setup");
|
||||
}
|
||||
|
||||
private static void AddAtmosphericEffects()
|
||||
{
|
||||
// Create parent container
|
||||
var atmosphericEffects = new GameObject("AtmosphericEffects");
|
||||
|
||||
// 1. Dust Particles
|
||||
var dustParticles = new GameObject("DustParticles");
|
||||
dustParticles.transform.SetParent(atmosphericEffects.transform);
|
||||
var dustParticleSystem = dustParticles.AddComponent<ParticleSystem>();
|
||||
|
||||
// Configure dust particle system
|
||||
var dustMain = dustParticleSystem.main;
|
||||
dustMain.duration = 5.0f;
|
||||
dustMain.loop = true;
|
||||
dustMain.startLifetime = 8.0f;
|
||||
dustMain.startSpeed = 0.1f;
|
||||
dustMain.startSize = 0.05f;
|
||||
dustMain.maxParticles = 1000;
|
||||
dustMain.simulationSpace = ParticleSystemSimulationSpace.World;
|
||||
|
||||
// Set a default color that works without relying on materials
|
||||
dustMain.startColor = new ParticleSystem.MinMaxGradient(
|
||||
new Color(0.8f, 0.8f, 0.9f, 0.2f),
|
||||
new Color(0.9f, 0.9f, 1f, 0.05f)
|
||||
);
|
||||
|
||||
var dustEmission = dustParticleSystem.emission;
|
||||
dustEmission.rateOverTime = 30;
|
||||
|
||||
var dustShape = dustParticleSystem.shape;
|
||||
dustShape.shapeType = ParticleSystemShapeType.Box;
|
||||
dustShape.scale = new Vector3(10, 5, 30);
|
||||
dustShape.position = new Vector3(0, 2.5f, -10);
|
||||
|
||||
// Add renderer with material that works in all pipelines
|
||||
var dustRenderer = dustParticles.GetComponent<ParticleSystemRenderer>();
|
||||
if (dustRenderer != null)
|
||||
{
|
||||
dustRenderer.renderMode = ParticleSystemRenderMode.Billboard;
|
||||
dustRenderer.material = GetParticleMaterial(new Color(1f, 1f, 1f, 0.5f));
|
||||
}
|
||||
|
||||
dustParticles.transform.position = new Vector3(0, 0, -10);
|
||||
|
||||
// 2. Light Rays
|
||||
var lightRays = new GameObject("LightRays");
|
||||
lightRays.transform.SetParent(atmosphericEffects.transform);
|
||||
var lightRayParticleSystem = lightRays.AddComponent<ParticleSystem>();
|
||||
|
||||
// Configure light ray particle system
|
||||
var lightRayMain = lightRayParticleSystem.main;
|
||||
lightRayMain.duration = 5.0f;
|
||||
lightRayMain.loop = true;
|
||||
lightRayMain.startLifetime = 5.0f;
|
||||
lightRayMain.startSpeed = 0.0f;
|
||||
lightRayMain.startSize = 0.5f;
|
||||
lightRayMain.startColor = new Color(1f, 0.95f, 0.8f, 0.2f); // Warm light rays
|
||||
lightRayMain.maxParticles = 20;
|
||||
|
||||
var lightRayEmission = lightRayParticleSystem.emission;
|
||||
lightRayEmission.rateOverTime = 2;
|
||||
|
||||
var lightRayShape = lightRayParticleSystem.shape;
|
||||
lightRayShape.shapeType = ParticleSystemShapeType.Cone;
|
||||
lightRayShape.angle = 20;
|
||||
|
||||
// Add renderer with material that works in all pipelines
|
||||
var lightRayRenderer = lightRays.GetComponent<ParticleSystemRenderer>();
|
||||
if (lightRayRenderer != null)
|
||||
{
|
||||
lightRayRenderer.renderMode = ParticleSystemRenderMode.Billboard;
|
||||
lightRayRenderer.material = GetParticleMaterial(new Color(1f, 0.95f, 0.8f, 0.3f));
|
||||
}
|
||||
|
||||
lightRays.transform.position = new Vector3(5, 10, -5);
|
||||
lightRays.transform.rotation = Quaternion.Euler(45, -30, 0);
|
||||
|
||||
// 3. Fog Volume
|
||||
var fogVolume = new GameObject("FogVolume");
|
||||
fogVolume.transform.SetParent(atmosphericEffects.transform);
|
||||
var fogParticleSystem = fogVolume.AddComponent<ParticleSystem>();
|
||||
|
||||
// Configure fog particle system
|
||||
var fogMain = fogParticleSystem.main;
|
||||
fogMain.duration = 5.0f;
|
||||
fogMain.loop = true;
|
||||
fogMain.startLifetime = 10.0f;
|
||||
fogMain.startSpeed = 0.05f;
|
||||
fogMain.startSize = 2.0f;
|
||||
fogMain.startColor = new Color(0.1f, 0.1f, 0.2f, 0.1f); // Darker for night-time fog
|
||||
fogMain.maxParticles = 50;
|
||||
|
||||
var fogEmission = fogParticleSystem.emission;
|
||||
fogEmission.rateOverTime = 5;
|
||||
|
||||
var fogShape = fogParticleSystem.shape;
|
||||
fogShape.shapeType = ParticleSystemShapeType.Box;
|
||||
fogShape.scale = new Vector3(10, 0.5f, 30);
|
||||
|
||||
// Add renderer with material that works in all pipelines
|
||||
var fogRenderer = fogVolume.GetComponent<ParticleSystemRenderer>();
|
||||
if (fogRenderer != null)
|
||||
{
|
||||
fogRenderer.renderMode = ParticleSystemRenderMode.Billboard;
|
||||
fogRenderer.material = GetParticleMaterial(new Color(0.1f, 0.1f, 0.2f, 0.1f));
|
||||
}
|
||||
|
||||
fogVolume.transform.position = new Vector3(0, 0.25f, -10);
|
||||
|
||||
Debug.Log("Created atmospheric effects with compatible materials");
|
||||
}
|
||||
|
||||
private static Material GetParticleMaterial(Color color)
|
||||
{
|
||||
Material material = null;
|
||||
|
||||
// Try to find a suitable particle shader first
|
||||
Shader particleShader = Shader.Find("Universal Render Pipeline/Particles/Unlit");
|
||||
|
||||
if (particleShader == null)
|
||||
particleShader = Shader.Find("Particles/Standard Unlit");
|
||||
|
||||
if (particleShader == null)
|
||||
particleShader = Shader.Find("Mobile/Particles/Additive");
|
||||
|
||||
if (particleShader == null)
|
||||
particleShader = Shader.Find("Particles/Additive");
|
||||
|
||||
if (particleShader == null)
|
||||
particleShader = Shader.Find("Universal Render Pipeline/Particles/Unlit");
|
||||
|
||||
// Fallback to a basic shader
|
||||
if (particleShader == null)
|
||||
particleShader = Shader.Find("Unlit/Transparent");
|
||||
|
||||
if (particleShader == null)
|
||||
particleShader = Shader.Find("Sprites/Default");
|
||||
|
||||
// Last resort - try to use any available shader
|
||||
if (particleShader == null && Shader.Find("Standard") != null)
|
||||
particleShader = Shader.Find("Standard");
|
||||
|
||||
if (particleShader != null)
|
||||
{
|
||||
material = new Material(particleShader);
|
||||
material.color = color;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create a default unlit material if all else fails
|
||||
material = new Material(Shader.Find("Hidden/InternalErrorShader"))
|
||||
{
|
||||
color = color
|
||||
};
|
||||
Debug.LogWarning("Could not find suitable particle shader. Using fallback material.");
|
||||
}
|
||||
|
||||
return material;
|
||||
}
|
||||
|
||||
private static void CreateEntranceEnvironment()
|
||||
{
|
||||
var entranceEnvironment = new GameObject("EntranceEnvironment");
|
||||
|
||||
// Create floor/ground - keep this but make it simpler
|
||||
var ground = GameObject.CreatePrimitive(PrimitiveType.Plane);
|
||||
ground.name = "Ground";
|
||||
ground.transform.SetParent(entranceEnvironment.transform);
|
||||
ground.transform.position = Vector3.zero;
|
||||
ground.transform.localScale = new Vector3(10, 1, 10);
|
||||
|
||||
// Add a more interesting material to the ground with proper shader detection
|
||||
var groundMaterial = GetMaterial(new Color(0.15f, 0.15f, 0.2f)); // Darker floor for night scene
|
||||
if (groundMaterial != null && ground.GetComponent<Renderer>())
|
||||
{
|
||||
ground.GetComponent<Renderer>().material = groundMaterial;
|
||||
}
|
||||
|
||||
// Ensure ground is in the correct layer
|
||||
int groundLayerIndex = LayerMask.NameToLayer("Ground");
|
||||
ground.layer = groundLayerIndex != -1 ? groundLayerIndex : 0;
|
||||
|
||||
// Create a path without side walls
|
||||
var entrancePath = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
entrancePath.name = "EntrancePath";
|
||||
entrancePath.transform.SetParent(entranceEnvironment.transform);
|
||||
entrancePath.transform.position = new Vector3(0, -0.05f, -10);
|
||||
entrancePath.transform.localScale = new Vector3(6, 0.1f, 30);
|
||||
|
||||
// Add material to the entrance path
|
||||
var pathMaterial = GetMaterial(new Color(0.2f, 0.2f, 0.25f)); // Slightly brighter than ground
|
||||
if (pathMaterial != null && entrancePath.GetComponent<Renderer>())
|
||||
{
|
||||
entrancePath.GetComponent<Renderer>().material = pathMaterial;
|
||||
entrancePath.GetComponent<Renderer>().receiveShadows = true;
|
||||
}
|
||||
|
||||
// Ensure entrance path is in Ground layer
|
||||
entrancePath.layer = groundLayerIndex != -1 ? groundLayerIndex : 0;
|
||||
|
||||
// Create subtle markers along the path without obstructing walls
|
||||
for (int i = -25; i <= -5; i += 5)
|
||||
{
|
||||
// Create subtle floor markers instead of pillars
|
||||
var leftMarker = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
leftMarker.name = $"LeftMarker_{i}";
|
||||
leftMarker.transform.SetParent(entranceEnvironment.transform);
|
||||
leftMarker.transform.position = new Vector3(-2.5f, 0.05f, i);
|
||||
leftMarker.transform.localScale = new Vector3(0.5f, 0.02f, 0.5f); // Very thin
|
||||
|
||||
var rightMarker = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
rightMarker.name = $"RightMarker_{i}";
|
||||
rightMarker.transform.SetParent(entranceEnvironment.transform);
|
||||
rightMarker.transform.position = new Vector3(2.5f, 0.05f, i);
|
||||
rightMarker.transform.localScale = new Vector3(0.5f, 0.02f, 0.5f); // Very thin
|
||||
|
||||
// Add subtle glow material
|
||||
var markerMaterial = GetMaterial(new Color(0.3f, 0.4f, 0.9f));
|
||||
|
||||
if (markerMaterial != null)
|
||||
{
|
||||
if (leftMarker.GetComponent<Renderer>())
|
||||
{
|
||||
leftMarker.GetComponent<Renderer>().material = markerMaterial;
|
||||
leftMarker.GetComponent<Renderer>().receiveShadows = true;
|
||||
}
|
||||
|
||||
if (rightMarker.GetComponent<Renderer>())
|
||||
{
|
||||
rightMarker.GetComponent<Renderer>().material = markerMaterial;
|
||||
rightMarker.GetComponent<Renderer>().receiveShadows = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create a subtle end marker (instead of banner)
|
||||
var endMarker = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
|
||||
endMarker.name = "EndMarker";
|
||||
endMarker.transform.SetParent(entranceEnvironment.transform);
|
||||
endMarker.transform.position = new Vector3(0, 0.05f, 0);
|
||||
endMarker.transform.localScale = new Vector3(3f, 0.02f, 3f);
|
||||
endMarker.transform.rotation = Quaternion.Euler(0, 0, 0);
|
||||
|
||||
var endMarkerMaterial = GetMaterial(new Color(0.7f, 0.3f, 0.3f));
|
||||
if (endMarkerMaterial != null && endMarker.GetComponent<Renderer>())
|
||||
{
|
||||
endMarker.GetComponent<Renderer>().material = endMarkerMaterial;
|
||||
}
|
||||
|
||||
Debug.Log("Created minimalist entrance environment without walls");
|
||||
}
|
||||
|
||||
// Helper method to get appropriate material based on current render pipeline
|
||||
private static Material GetMaterial(Color color, float smoothness = 0.3f)
|
||||
{
|
||||
Material material = null;
|
||||
|
||||
// Try URP shader first
|
||||
Shader urpShader = Shader.Find("Universal Render Pipeline/Lit");
|
||||
if (urpShader != null)
|
||||
{
|
||||
material = new Material(urpShader);
|
||||
material.color = color;
|
||||
// URP specific properties
|
||||
material.SetFloat("_Smoothness", smoothness);
|
||||
}
|
||||
// Try HDRP shader
|
||||
else if (Shader.Find("HDRP/Lit") != null)
|
||||
{
|
||||
material = new Material(Shader.Find("HDRP/Lit"));
|
||||
material.color = color;
|
||||
// HDRP specific properties
|
||||
material.SetFloat("_Smoothness", smoothness);
|
||||
}
|
||||
// Try legacy Standard shader
|
||||
else if (Shader.Find("Standard") != null)
|
||||
{
|
||||
material = new Material(Shader.Find("Standard"));
|
||||
material.color = color;
|
||||
material.SetFloat("_Glossiness", smoothness);
|
||||
}
|
||||
// Fallback to built-in Diffuse shader which exists in all Unity versions
|
||||
else if (Shader.Find("Diffuse") != null)
|
||||
{
|
||||
material = new Material(Shader.Find("Diffuse"));
|
||||
material.color = color;
|
||||
}
|
||||
// Last resort fallback - Unlit color
|
||||
else
|
||||
{
|
||||
material = new Material(Shader.Find("Unlit/Color"));
|
||||
material.color = color;
|
||||
}
|
||||
|
||||
return material;
|
||||
}
|
||||
|
||||
// Create post-processing volume for cinematic look
|
||||
private static void CreatePostProcessingVolume()
|
||||
{
|
||||
// Create post-processing volume
|
||||
var ppVolumeObject = new GameObject("Post Process Volume");
|
||||
var postProcessVolume = ppVolumeObject.AddComponent<UnityEngine.Rendering.PostProcessing.PostProcessVolume>();
|
||||
ppVolumeObject.layer = LayerMask.NameToLayer("PostProcessing");
|
||||
|
||||
// If post-processing layer doesn't exist, use Default
|
||||
if (ppVolumeObject.layer == -1)
|
||||
{
|
||||
ppVolumeObject.layer = 0;
|
||||
}
|
||||
|
||||
postProcessVolume.isGlobal = true;
|
||||
postProcessVolume.priority = 1;
|
||||
|
||||
// Create a new profile
|
||||
var profile = ScriptableObject.CreateInstance<UnityEngine.Rendering.PostProcessing.PostProcessProfile>();
|
||||
postProcessVolume.profile = profile;
|
||||
|
||||
// Add post-processing layer to main camera
|
||||
var mainCamera = GameObject.FindGameObjectWithTag("MainCamera");
|
||||
if (mainCamera != null)
|
||||
{
|
||||
var ppLayer = mainCamera.AddComponent<UnityEngine.Rendering.PostProcessing.PostProcessLayer>();
|
||||
ppLayer.volumeLayer = 1 << 0; // Default layer
|
||||
ppLayer.antialiasingMode = UnityEngine.Rendering.PostProcessing.PostProcessLayer.Antialiasing.FastApproximateAntialiasing;
|
||||
}
|
||||
}
|
||||
|
||||
// Helper method to create a layer if it doesn't exist
|
||||
private static void CreateLayerIfNeeded(string layerName, int layerIndex)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
// Open tag manager
|
||||
SerializedObject tagManager = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/TagManager.asset")[0]);
|
||||
SerializedProperty layersProp = tagManager.FindProperty("layers");
|
||||
|
||||
// Check if layer already exists
|
||||
bool exists = false;
|
||||
for (int i = 0; i < layersProp.arraySize; i++)
|
||||
{
|
||||
SerializedProperty layerProp = layersProp.GetArrayElementAtIndex(i);
|
||||
if (layerProp.stringValue == layerName)
|
||||
{
|
||||
exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If layer doesn't exist and layer index is valid, add it
|
||||
if (!exists && layerIndex >= 8 && layerIndex <= 31)
|
||||
{
|
||||
layersProp.GetArrayElementAtIndex(layerIndex).stringValue = layerName;
|
||||
tagManager.ApplyModifiedProperties();
|
||||
Debug.Log($"Layer '{layerName}' created at index {layerIndex}");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user