chunk 1: core gameplay scripts scenes runtime assets

This commit is contained in:
2026-04-06 11:02:34 +03:00
parent fa0388bc79
commit 0d11a097d8
703 changed files with 2292651 additions and 0 deletions

View File

@@ -0,0 +1,81 @@
using UnityEngine;
using UnityEditor;
using UnityEditor.SceneManagement;
using System.Collections.Generic;
using System.Linq;
#if UNITY_EDITOR
public class BuildSettingsUpdater
{
[UnityEditor.MenuItem("Tools/Update Build Settings with Waiting Scene")]
public static void AddWaitingSceneToBuild()
{
// Get current scenes in build settings
List<EditorBuildSettingsScene> scenes = new List<EditorBuildSettingsScene>(EditorBuildSettings.scenes);
// Path to the waiting scene
string waitingScenePath = "Assets/Scenes/WaitingScene.unity";
// Check if the waiting scene exists in the project
if (!System.IO.File.Exists(waitingScenePath))
{
Debug.LogError("WaitingScene.unity does not exist. Please create it first using Tools/Create Waiting Scene.");
return;
}
// Check if the waiting scene is already in build settings
bool alreadyInBuild = scenes.Any(scene => scene.path == waitingScenePath);
if (!alreadyInBuild)
{
// Add the waiting scene right after the MenuScene (position 1)
int menuSceneIndex = -1;
for (int i = 0; i < scenes.Count; i++)
{
if (scenes[i].path.Contains("MenuScene"))
{
menuSceneIndex = i;
break;
}
}
if (menuSceneIndex >= 0)
{
scenes.Insert(menuSceneIndex + 1, new EditorBuildSettingsScene(waitingScenePath, true));
}
else
{
// If MenuScene not found, add it before Game scene
int gameSceneIndex = -1;
for (int i = 0; i < scenes.Count; i++)
{
if (scenes[i].path.Contains("Game"))
{
gameSceneIndex = i;
break;
}
}
if (gameSceneIndex >= 0)
{
scenes.Insert(gameSceneIndex, new EditorBuildSettingsScene(waitingScenePath, true));
}
else
{
// If no Game scene found, add to the end
scenes.Add(new EditorBuildSettingsScene(waitingScenePath, true));
}
}
// Save changes
EditorBuildSettings.scenes = scenes.ToArray();
Debug.Log("WaitingScene added to build settings.");
}
else
{
Debug.Log("WaitingScene is already in build settings.");
}
}
}
#endif

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 6a3e604b59727f135ad7d82878202662

View File

@@ -0,0 +1,73 @@
using UnityEngine;
using UnityEditor;
using UnityEditorInternal;
[CustomEditor(typeof(DeviceDisplayConfigurator))]
public class DeviceDisplayConfiguratorEditor : UnityEditor.Editor
{
private ReorderableList listDeviceSets;
private SerializedProperty disconnectedDeviceProperty;
private void OnEnable()
{
DrawListOfDevices();
disconnectedDeviceProperty = serializedObject.FindProperty("disconnectedDeviceSettings");
}
public override void OnInspectorGUI()
{
serializedObject.Update();
EditorGUILayout.LabelField("Device Sets", EditorStyles.boldLabel);
listDeviceSets.DoLayoutList();
EditorGUILayout.PropertyField(disconnectedDeviceProperty);
serializedObject.ApplyModifiedProperties();
}
void DrawListOfDevices()
{
listDeviceSets = new ReorderableList(serializedObject, serializedObject.FindProperty("listDeviceSets"), true, true, true, true);
listDeviceSets.drawHeaderCallback = (Rect rect) => {
EditorGUI.LabelField(CalculateColumn(rect, 1, 15, 0), "Raw Path Name");
EditorGUI.LabelField(CalculateColumn(rect, 2, 15, 0), "Device Display Settings");
};
listDeviceSets.drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) => {
var element = listDeviceSets.serializedProperty.GetArrayElementAtIndex(index);
rect.y += 2;
EditorGUI.PropertyField(CalculateColumn(rect, 1, 0, 0), element.FindPropertyRelative("deviceRawPath"), GUIContent.none);
EditorGUI.PropertyField(CalculateColumn(rect, 2, 10, 10), element.FindPropertyRelative("deviceDisplaySettings"), GUIContent.none);
};
}
Rect CalculateColumn(Rect rect, int columnNumber, float xPadding, float xWidth)
{
float xPosition = rect.x;
switch (columnNumber)
{
case 1:
xPosition = rect.x + xPadding;
break;
case 2:
xPosition = rect.x + rect.width/2 + xPadding;
break;
}
return new Rect(xPosition, rect.y, rect.width / 2 - xWidth, EditorGUIUtility.singleLineHeight);
}
}

View File

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

View File

@@ -0,0 +1,158 @@
using UnityEngine;
using UnityEditor;
using UnityEditorInternal;
[CustomEditor(typeof(DeviceDisplaySettings))]
public class DeviceDisplaySettingsEditor : UnityEditor.Editor
{
private DeviceDisplaySettings deviceDisplaySettings;
//Display Name
public SerializedProperty deviceDisplayNameProperty;
//Display Color
public SerializedProperty deviceDisplayColorProperty;
//Icons
public SerializedProperty deviceHasContextIconsProperty;
//Icons - Action Buttons
public SerializedProperty buttonNorthIconProperty;
public SerializedProperty buttonSouthIconProperty;
public SerializedProperty buttonWestIconProperty;
public SerializedProperty buttonEastIconProperty;
//Icon - Triggers
public SerializedProperty triggerRightFrontIconProperty;
public SerializedProperty triggerRightBackIconProperty;
public SerializedProperty triggerLeftFrontIconProperty;
public SerializedProperty triggerLeftBackIconProperty;
//Icon - Custom Contexts
private ReorderableList customInputContextIconList;
void OnEnable()
{
//Display Name
deviceDisplayNameProperty = serializedObject.FindProperty("deviceDisplayName");
//Display Color
deviceDisplayColorProperty = serializedObject.FindProperty("deviceDisplayColor");
//Icons
deviceHasContextIconsProperty = serializedObject.FindProperty("deviceHasContextIcons");
//Icons - Action Buttons
buttonNorthIconProperty = serializedObject.FindProperty("buttonNorthIcon");
buttonSouthIconProperty = serializedObject.FindProperty("buttonSouthIcon");
buttonWestIconProperty = serializedObject.FindProperty("buttonWestIcon");
buttonEastIconProperty = serializedObject.FindProperty("buttonEastIcon");
//Icon - Triggers
triggerRightFrontIconProperty = serializedObject.FindProperty("triggerRightFrontIcon");
triggerRightBackIconProperty = serializedObject.FindProperty("triggerRightBackIcon");
triggerLeftFrontIconProperty = serializedObject.FindProperty("triggerLeftFrontIcon");
triggerLeftBackIconProperty = serializedObject.FindProperty("triggerLeftBackIcon");
DrawCustomContextList();
}
void DrawCustomContextList()
{
customInputContextIconList = new ReorderableList(serializedObject, serializedObject.FindProperty("customContextIcons"), true, true, true, true);
customInputContextIconList.drawHeaderCallback = (Rect rect) => {
EditorGUI.LabelField(CalculateColumn(rect, 1, 15, 0), "Input Binding String");
EditorGUI.LabelField(CalculateColumn(rect, 2, 15, 0), "Display Icon");
};
customInputContextIconList.drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) => {
var element = customInputContextIconList.serializedProperty.GetArrayElementAtIndex(index);
rect.y += 2;
EditorGUI.PropertyField(CalculateColumn(rect, 1, 0, 0), element.FindPropertyRelative("customInputContextString"), GUIContent.none);
EditorGUI.PropertyField(CalculateColumn(rect, 2, 10, 10), element.FindPropertyRelative("customInputContextIcon"), GUIContent.none);
};
}
public override void OnInspectorGUI()
{
deviceDisplaySettings = (DeviceDisplaySettings)target;
serializedObject.Update();
EditorGUILayout.LabelField("Display Name", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(deviceDisplayNameProperty);
DrawSpaceGUI(2);
EditorGUILayout.LabelField("Display Color", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(deviceDisplayColorProperty);
DrawSpaceGUI(2);
EditorGUILayout.LabelField("Icon Settings", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(deviceHasContextIconsProperty);
if(deviceDisplaySettings.deviceHasContextIcons == true)
{
DrawSpaceGUI(3);
EditorGUILayout.LabelField("Icons - Action Buttons", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(buttonNorthIconProperty);
EditorGUILayout.PropertyField(buttonSouthIconProperty);
EditorGUILayout.PropertyField(buttonWestIconProperty);
EditorGUILayout.PropertyField(buttonEastIconProperty);
DrawSpaceGUI(3);
EditorGUILayout.LabelField("Icons - Triggers", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(triggerRightFrontIconProperty);
EditorGUILayout.PropertyField(triggerRightBackIconProperty);
EditorGUILayout.PropertyField(triggerLeftFrontIconProperty);
EditorGUILayout.PropertyField(triggerLeftBackIconProperty);
DrawSpaceGUI(3);
EditorGUILayout.LabelField("Icons - Custom Contexts", EditorStyles.boldLabel);
customInputContextIconList.DoLayoutList();
}
serializedObject.ApplyModifiedProperties();
}
void DrawSpaceGUI(int amountOfSpace)
{
for(int i = 0; i < amountOfSpace; i++)
{
EditorGUILayout.Space();
}
}
Rect CalculateColumn(Rect rect, int columnNumber, float xPadding, float xWidth)
{
float xPosition = rect.x;
switch (columnNumber)
{
case 1:
xPosition = rect.x + xPadding;
break;
case 2:
xPosition = rect.x + rect.width/2 + xPadding;
break;
}
return new Rect(xPosition, rect.y, rect.width / 2 - xWidth, EditorGUIUtility.singleLineHeight);
}
}

View File

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

View File

@@ -0,0 +1,101 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEngine.InputSystem;
//[CustomEditor(typeof(GameManager))]
public class GameManagerEditor : UnityEditor.Editor
{
private GameManager gameManager;
//Game Mode
private SerializedProperty currentGameModeProperty;
//Single Player
private SerializedProperty inScenePlayerProperty;
private SerializedProperty singlePlayerCameraModeProperty;
//Local Multiplayer
private SerializedProperty playerPrefabProperty;
private SerializedProperty numberOfPlayersProperty;
private SerializedProperty spawnRingCenterProperty;
private SerializedProperty spawnRingRadiusProperty;
void OnEnable()
{
//Game Mode
currentGameModeProperty = serializedObject.FindProperty("currentGameMode");
//Single Player
inScenePlayerProperty = serializedObject.FindProperty("inScenePlayer");
singlePlayerCameraModeProperty = serializedObject.FindProperty("singlePlayerCameraMode");
//Local Multiplayer
playerPrefabProperty = serializedObject.FindProperty("playerPrefab");
numberOfPlayersProperty = serializedObject.FindProperty("numberOfPlayers");
spawnRingCenterProperty = serializedObject.FindProperty("spawnRingCenter");
spawnRingRadiusProperty = serializedObject.FindProperty("spawnRingRadius");
}
public override void OnInspectorGUI()
{
gameManager = (GameManager)target;
serializedObject.Update();
DrawGameModeGUI();
DrawSpaceGUI(3);
EditorGUILayout.LabelField("Initialization Mode Settings", EditorStyles.boldLabel);
if(gameManager.currentGameMode == GameMode.SinglePlayer)
{
DrawSinglePlayerGUI();
}
if(gameManager.currentGameMode == GameMode.LocalMultiplayer)
{
DrawLocalMultiplayerGUI();
}
serializedObject.ApplyModifiedProperties();
}
void DrawGameModeGUI()
{
EditorGUILayout.LabelField("Game Mode", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(currentGameModeProperty);
}
void DrawSinglePlayerGUI()
{
EditorGUILayout.PropertyField(inScenePlayerProperty);
EditorGUILayout.PropertyField(singlePlayerCameraModeProperty);
}
void DrawLocalMultiplayerGUI()
{
EditorGUILayout.PropertyField(playerPrefabProperty);
EditorGUILayout.PropertyField(numberOfPlayersProperty);
EditorGUILayout.PropertyField(spawnRingCenterProperty);
EditorGUILayout.PropertyField(spawnRingRadiusProperty);
}
void DrawSpaceGUI(int amountOfSpace)
{
for(int i = 0; i < amountOfSpace; i++)
{
EditorGUILayout.Space();
}
}
}

View File

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

View File

@@ -0,0 +1,20 @@
<!-- auto-generated. do not modify by hand. -->
<dependencies>
<androidPackages>
<repositories>
<repository>https://unity3ddist.jfrog.io/artifactory/unity-mediation-mvn-prod-local/</repository>
</repositories>
<!-- Mediation Android SDK -->
<androidPackage spec="com.unity3d.mediation:mediation-sdk:[1.0,2.0[" mediation-identifier="mediation-sdk" mediation-version="1.0" />
<!-- Mediation SDK Android Adapters -->
<androidPackage spec="com.unity3d.mediation:unityads-adapter:[1.0,2.0[" mediation-identifier="unityads-adapter" mediation-version="latest" />
</androidPackages>
<iosPods>
<!-- Mediation iOS SDK -->
<iosPod name="UnityMediationSdk" version="~> 1.0" source="'https://github.com/Unity-Technologies/unity-mediation-cocoapods-prod.git'" mediation-identifier="mediation-sdk" mediation-version="1.0" />
<!-- Mediation Dependency Required For resolution -->
<iosPod name="Protobuf" />
<!-- Mediation SDK iOS Adapters -->
<iosPod name="UnityMediationUnityAdapter" version="" source="'https://github.com/Unity-Technologies/unity-mediation-cocoapods-prod.git'" mediation-identifier="unityads-adapter" mediation-version="latest" />
</iosPods>
</dependencies>

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 5dd64be34b3b22743a1ad9b9770b6f90
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 51d97f49686311824acfded63e6bf7ec

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 2f406f2d89aeacb1faa5c06de01f690c

View 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

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: e3ecaf5ab9e99bd2c98a634c72cf672f