├── .gitignore ├── Animation_Triggers.cs ├── AudioManager.cs ├── CameraController.cs ├── ChangeScenes.cs ├── DataManager.cs ├── DialogueSystem.cs ├── FPS.cs ├── FirstPersonControl.cs ├── GameManager.cs ├── HealthSystem.cs ├── HideTrigger.cs ├── InventorySystem.cs ├── LICENSE ├── Light_Flirking ├── ObjectPooler.cs ├── PanelOpener.cs ├── PauseMenu.cs ├── PlayerController.cs ├── QuestSystem.cs ├── README.md ├── RaycastDetection.cs ├── SaveSystem.cs ├── Sound_on_Trigger ├── TooltipManager.cs ├── UIresize.cs ├── objectRotate.cs ├── openurl.cs ├── popup.cs └── sound_volume_slider.cs /.gitignore: -------------------------------------------------------------------------------- 1 | # Unity generated 2 | [Ll]ibrary/ 3 | [Tt]emp/ 4 | [Oo]bj/ 5 | [Bb]uild/ 6 | [Bb]uilds/ 7 | [Ll]ogs/ 8 | [Uu]ser[Ss]ettings/ 9 | 10 | # Unity3D generated meta files 11 | *.pidb.meta 12 | *.pdb.meta 13 | *.mdb.meta 14 | 15 | # Unity3D generated file on crash reports 16 | sysinfo.txt 17 | 18 | # Builds 19 | *.apk 20 | *.aab 21 | *.unitypackage 22 | *.app 23 | 24 | # Crashlytics generated file 25 | crashlytics-build.properties 26 | 27 | # Visual Studio 28 | .vs/ 29 | *.csproj 30 | *.unityproj 31 | *.sln 32 | *.suo 33 | *.tmp 34 | *.user 35 | *.userprefs 36 | *.pidb 37 | *.booproj 38 | *.svd 39 | *.pdb 40 | *.mdb 41 | *.opendb 42 | *.VC.db 43 | 44 | # OS generated 45 | .DS_Store 46 | .DS_Store? 47 | ._* 48 | .Spotlight-V100 49 | .Trashes 50 | ehthumbs.db 51 | Thumbs.db -------------------------------------------------------------------------------- /Animation_Triggers.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | Using inputsystm; 5 | 6 | public class Animation_Triggers : MonoBehaviour 7 | { 8 | [SerializeField] private Animator myAnimationController; 9 | 10 | private void OnTriggerEnter (Collider other) 11 | { 12 | if (other.CompareTag("Player")) 13 | { //ADD YOUR PARAMETERS THERE TO PLAY ANIMATION 14 | myAnimationController. SetBool("YOUR PARAMETERS", true); 15 | } 16 | } 17 | 18 | private void OnTriggerExit (Collider other) 19 | { 20 | if (other.CompareTag("Player")) 21 | { 22 | myAnimationController.SetBool("playSpin2", false); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /AudioManager.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEngine.Audio; 3 | using System.Collections.Generic; 4 | using System; 5 | 6 | public class AudioManager : MonoBehaviour 7 | { 8 | public static AudioManager Instance { get; private set; } 9 | 10 | [Header("Audio Sources")] 11 | [SerializeField] private AudioSource musicSource; 12 | [SerializeField] private AudioSource sfxSource; 13 | [SerializeField] private AudioSource ambienceSource; 14 | [SerializeField] private AudioSource uiSource; 15 | 16 | [Header("Audio Mixers")] 17 | [SerializeField] private AudioMixer audioMixer; 18 | 19 | [Header("Sound Collections")] 20 | [SerializeField] private Sound[] musicTracks; 21 | [SerializeField] private Sound[] sfxSounds; 22 | [SerializeField] private Sound[] ambienceSounds; 23 | [SerializeField] private Sound[] uiSounds; 24 | 25 | // Dictionary for quick lookup of sounds by name 26 | private Dictionary soundDictionary = new Dictionary(); 27 | 28 | // Track currently playing sounds 29 | private string currentMusicTrack; 30 | private string currentAmbience; 31 | 32 | // Volume settings 33 | private float masterVolume = 1f; 34 | private float musicVolume = 1f; 35 | private float sfxVolume = 1f; 36 | private float ambienceVolume = 1f; 37 | private float uiVolume = 1f; 38 | 39 | // For fade effects 40 | private Coroutine musicFadeCoroutine; 41 | private Coroutine ambienceFadeCoroutine; 42 | 43 | private void Awake() 44 | { 45 | // Singleton pattern 46 | if (Instance == null) 47 | { 48 | Instance = this; 49 | DontDestroyOnLoad(gameObject); 50 | } 51 | else 52 | { 53 | Destroy(gameObject); 54 | return; 55 | } 56 | 57 | // Initialize sound dictionary 58 | RegisterSounds(musicTracks); 59 | RegisterSounds(sfxSounds); 60 | RegisterSounds(ambienceSounds); 61 | RegisterSounds(uiSounds); 62 | 63 | // Set up audio sources if not assigned 64 | if (musicSource == null) 65 | { 66 | musicSource = gameObject.AddComponent(); 67 | musicSource.loop = true; 68 | musicSource.playOnAwake = false; 69 | } 70 | 71 | if (sfxSource == null) 72 | { 73 | sfxSource = gameObject.AddComponent(); 74 | sfxSource.loop = false; 75 | sfxSource.playOnAwake = false; 76 | } 77 | 78 | if (ambienceSource == null) 79 | { 80 | ambienceSource = gameObject.AddComponent(); 81 | ambienceSource.loop = true; 82 | ambienceSource.playOnAwake = false; 83 | } 84 | 85 | if (uiSource == null) 86 | { 87 | uiSource = gameObject.AddComponent(); 88 | uiSource.loop = false; 89 | uiSource.playOnAwake = false; 90 | } 91 | 92 | // Load saved volumes 93 | LoadVolumeSettings(); 94 | ApplyVolumeSettings(); 95 | } 96 | 97 | private void RegisterSounds(Sound[] sounds) 98 | { 99 | foreach (Sound sound in sounds) 100 | { 101 | if (!soundDictionary.ContainsKey(sound.name)) 102 | { 103 | soundDictionary.Add(sound.name, sound); 104 | } 105 | else 106 | { 107 | Debug.LogWarning("Duplicate sound name found: " + sound.name); 108 | } 109 | } 110 | } 111 | 112 | #region Music Functions 113 | 114 | public void PlayMusic(string name, float fadeInDuration = 1f) 115 | { 116 | if (name == currentMusicTrack && musicSource.isPlaying) 117 | return; 118 | 119 | if (!soundDictionary.ContainsKey(name)) 120 | { 121 | Debug.LogWarning("Music track not found: " + name); 122 | return; 123 | } 124 | 125 | Sound sound = soundDictionary[name]; 126 | 127 | if (fadeInDuration > 0 && musicSource.isPlaying) 128 | { 129 | StartCoroutine(FadeMusicTrack(sound, fadeInDuration)); 130 | } 131 | else 132 | { 133 | musicSource.clip = sound.clip; 134 | musicSource.volume = sound.volume * musicVolume; 135 | musicSource.pitch = sound.pitch; 136 | musicSource.Play(); 137 | } 138 | 139 | currentMusicTrack = name; 140 | } 141 | 142 | private System.Collections.IEnumerator FadeMusicTrack(Sound newTrack, float fadeDuration) 143 | { 144 | float startVolume = musicSource.volume; 145 | float timer = 0; 146 | 147 | // Fade out current track 148 | while (timer < fadeDuration / 2) 149 | { 150 | timer += Time.deltaTime; 151 | musicSource.volume = Mathf.Lerp(startVolume, 0, timer / (fadeDuration / 2)); 152 | yield return null; 153 | } 154 | 155 | // Switch to new track 156 | musicSource.clip = newTrack.clip; 157 | musicSource.pitch = newTrack.pitch; 158 | musicSource.Play(); 159 | 160 | // Fade in new track 161 | timer = 0; 162 | while (timer < fadeDuration / 2) 163 | { 164 | timer += Time.deltaTime; 165 | musicSource.volume = Mathf.Lerp(0, newTrack.volume * musicVolume, timer / (fadeDuration / 2)); 166 | yield return null; 167 | } 168 | 169 | musicSource.volume = newTrack.volume * musicVolume; 170 | } 171 | 172 | public void StopMusic(float fadeOutDuration = 1f) 173 | { 174 | if (!musicSource.isPlaying) 175 | return; 176 | 177 | if (fadeOutDuration > 0) 178 | { 179 | StartCoroutine(FadeOut(musicSource, fadeOutDuration)); 180 | } 181 | else 182 | { 183 | musicSource.Stop(); 184 | } 185 | 186 | currentMusicTrack = null; 187 | } 188 | 189 | private System.Collections.IEnumerator FadeOut(AudioSource source, float fadeDuration) 190 | { 191 | float startVolume = source.volume; 192 | float timer = 0; 193 | 194 | while (timer < fadeDuration) 195 | { 196 | timer += Time.deltaTime; 197 | source.volume = Mathf.Lerp(startVolume, 0, timer / fadeDuration); 198 | yield return null; 199 | } 200 | 201 | source.Stop(); 202 | source.volume = startVolume; 203 | } 204 | 205 | #endregion 206 | 207 | #region SFX Functions 208 | 209 | public void PlaySFX(string name) 210 | { 211 | if (!soundDictionary.ContainsKey(name)) 212 | { 213 | Debug.LogWarning("SFX not found: " + name); 214 | return; 215 | } 216 | 217 | Sound sound = soundDictionary[name]; 218 | sfxSource.PlayOneShot(sound.clip, sound.volume * sfxVolume); 219 | } 220 | 221 | public void PlaySFXAtPosition(string name, Vector3 position, float minDistance = 1f, float maxDistance = 50f) 222 | { 223 | if (!soundDictionary.ContainsKey(name)) 224 | { 225 | Debug.LogWarning("SFX not found: " + name); 226 | return; 227 | } 228 | 229 | Sound sound = soundDictionary[name]; 230 | 231 | // Create temporary audio source at the specified position 232 | GameObject tempAudio = new GameObject("TempAudio"); 233 | tempAudio.transform.position = position; 234 | 235 | AudioSource tempSource = tempAudio.AddComponent(); 236 | tempSource.clip = sound.clip; 237 | tempSource.volume = sound.volume * sfxVolume; 238 | tempSource.pitch = sound.pitch; 239 | tempSource.spatialBlend = 1f; // 3D sound 240 | tempSource.minDistance = minDistance; 241 | tempSource.maxDistance = maxDistance; 242 | tempSource.rolloffMode = AudioRolloffMode.Linear; 243 | tempSource.Play(); 244 | 245 | // Destroy the GameObject after the sound is done playing 246 | float clipLength = sound.clip.length; 247 | Destroy(tempAudio, clipLength + 0.1f); 248 | } 249 | 250 | #endregion 251 | 252 | #region Ambience Functions 253 | 254 | public void PlayAmbience(string name, float fadeInDuration = 2f) 255 | { 256 | if (name == currentAmbience && ambienceSource.isPlaying) 257 | return; 258 | 259 | if (!soundDictionary.ContainsKey(name)) 260 | { 261 | Debug.LogWarning("Ambience not found: " + name); 262 | return; 263 | } 264 | 265 | Sound sound = soundDictionary[name]; 266 | 267 | if (fadeInDuration > 0 && ambienceSource.isPlaying) 268 | { 269 | StartCoroutine(FadeAmbienceTrack(sound, fadeInDuration)); 270 | } 271 | else 272 | { 273 | ambienceSource.clip = sound.clip; 274 | ambienceSource.volume = sound.volume * ambienceVolume; 275 | ambienceSource.pitch = sound.pitch; 276 | ambienceSource.Play(); 277 | } 278 | 279 | currentAmbience = name; 280 | } 281 | 282 | private System.Collections.IEnumerator FadeAmbienceTrack(Sound newTrack, float fadeDuration) 283 | { 284 | float startVolume = ambienceSource.volume; 285 | float timer = 0; 286 | 287 | // Fade out current track 288 | while (timer < fadeDuration / 2) 289 | { 290 | timer += Time.deltaTime; 291 | ambienceSource.volume = Mathf.Lerp(startVolume, 0, timer / (fadeDuration / 2)); 292 | yield return null; 293 | } 294 | 295 | // Switch to new track 296 | ambienceSource.clip = newTrack.clip; 297 | ambienceSource.pitch = newTrack.pitch; 298 | ambienceSource.Play(); 299 | 300 | // Fade in new track 301 | timer = 0; 302 | while (timer < fadeDuration / 2) 303 | { 304 | timer += Time.deltaTime; 305 | ambienceSource.volume = Mathf.Lerp(0, newTrack.volume * ambienceVolume, timer / (fadeDuration / 2)); 306 | yield return null; 307 | } 308 | 309 | ambienceSource.volume = newTrack.volume * ambienceVolume; 310 | } 311 | 312 | public void StopAmbience(float fadeOutDuration = 2f) 313 | { 314 | if (!ambienceSource.isPlaying) 315 | return; 316 | 317 | if (fadeOutDuration > 0) 318 | { 319 | StartCoroutine(FadeOut(ambienceSource, fadeOutDuration)); 320 | } 321 | else 322 | { 323 | ambienceSource.Stop(); 324 | } 325 | 326 | currentAmbience = null; 327 | } 328 | 329 | #endregion 330 | 331 | #region UI Sound Functions 332 | 333 | public void PlayUISound(string name) 334 | { 335 | if (!soundDictionary.ContainsKey(name)) 336 | { 337 | Debug.LogWarning("UI sound not found: " + name); 338 | return; 339 | } 340 | 341 | Sound sound = soundDictionary[name]; 342 | uiSource.PlayOneShot(sound.clip, sound.volume * uiVolume); 343 | } 344 | 345 | #endregion 346 | 347 | #region Volume Control 348 | 349 | public void SetMasterVolume(float volume) 350 | { 351 | masterVolume = Mathf.Clamp01(volume); 352 | ApplyVolumeSettings(); 353 | SaveVolumeSettings(); 354 | } 355 | 356 | public void SetMusicVolume(float volume) 357 | { 358 | musicVolume = Mathf.Clamp01(volume); 359 | ApplyVolumeSettings(); 360 | SaveVolumeSettings(); 361 | } 362 | 363 | public void SetSFXVolume(float volume) 364 | { 365 | sfxVolume = Mathf.Clamp01(volume); 366 | ApplyVolumeSettings(); 367 | SaveVolumeSettings(); 368 | } 369 | 370 | public void SetAmbienceVolume(float volume) 371 | { 372 | ambienceVolume = Mathf.Clamp01(volume); 373 | ApplyVolumeSettings(); 374 | SaveVolumeSettings(); 375 | } 376 | 377 | public void SetUIVolume(float volume) 378 | { 379 | uiVolume = Mathf.Clamp01(volume); 380 | ApplyVolumeSettings(); 381 | SaveVolumeSettings(); 382 | } 383 | 384 | public float GetMasterVolume() => masterVolume; 385 | public float GetMusicVolume() => musicVolume; 386 | public float GetSFXVolume() => sfxVolume; 387 | public float GetAmbienceVolume() => ambienceVolume; 388 | public float GetUIVolume() => uiVolume; 389 | 390 | private void ApplyVolumeSettings() 391 | { 392 | // Apply volumes to audio mixer if available 393 | if (audioMixer != null) 394 | { 395 | // Convert linear volume to logarithmic for better control 396 | float masterVolumeDB = masterVolume > 0.001f ? 20f * Mathf.Log10(masterVolume) : -80f; 397 | float musicVolumeDB = musicVolume > 0.001f ? 20f * Mathf.Log10(musicVolume) : -80f; 398 | float sfxVolumeDB = sfxVolume > 0.001f ? 20f * Mathf.Log10(sfxVolume) : -80f; 399 | float ambienceVolumeDB = ambienceVolume > 0.001f ? 20f * Mathf.Log10(ambienceVolume) : -80f; 400 | float uiVolumeDB = uiVolume > 0.001f ? 20f * Mathf.Log10(uiVolume) : -80f; 401 | 402 | audioMixer.SetFloat("MasterVolume", masterVolumeDB); 403 | audioMixer.SetFloat("MusicVolume", musicVolumeDB); 404 | audioMixer.SetFloat("SFXVolume", sfxVolumeDB); 405 | audioMixer.SetFloat("AmbienceVolume", ambienceVolumeDB); 406 | audioMixer.SetFloat("UIVolume", uiVolumeDB); 407 | } 408 | 409 | // Apply directly to sources if mixer not available 410 | if (musicSource != null && musicSource.clip != null && soundDictionary.ContainsKey(currentMusicTrack)) 411 | { 412 | musicSource.volume = soundDictionary[currentMusicTrack].volume * musicVolume * masterVolume; 413 | } 414 | 415 | if (ambienceSource != null && ambienceSource.clip != null && soundDictionary.ContainsKey(currentAmbience)) 416 | { 417 | ambienceSource.volume = soundDictionary[currentAmbience].volume * ambienceVolume * masterVolume; 418 | } 419 | } 420 | 421 | private void SaveVolumeSettings() 422 | { 423 | PlayerPrefs.SetFloat("MasterVolume", masterVolume); 424 | PlayerPrefs.SetFloat("MusicVolume", musicVolume); 425 | PlayerPrefs.SetFloat("SFXVolume", sfxVolume); 426 | PlayerPrefs.SetFloat("AmbienceVolume", ambienceVolume); 427 | PlayerPrefs.SetFloat("UIVolume", uiVolume); 428 | PlayerPrefs.Save(); 429 | } 430 | 431 | private void LoadVolumeSettings() 432 | { 433 | masterVolume = PlayerPrefs.GetFloat("MasterVolume", 1f); 434 | musicVolume = PlayerPrefs.GetFloat("MusicVolume", 1f); 435 | sfxVolume = PlayerPrefs.GetFloat("SFXVolume", 1f); 436 | ambienceVolume = PlayerPrefs.GetFloat("AmbienceVolume", 1f); 437 | uiVolume = PlayerPrefs.GetFloat("UIVolume", 1f); 438 | } 439 | 440 | #endregion 441 | } 442 | 443 | [System.Serializable] 444 | public class Sound 445 | { 446 | public string name; 447 | public AudioClip clip; 448 | [Range(0f, 1f)] 449 | public float volume = 1f; 450 | [Range(0.1f, 3f)] 451 | public float pitch = 1f; 452 | } -------------------------------------------------------------------------------- /CameraController.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | public class CameraController : MonoBehaviour 4 | { 5 | [Header("Target Settings")] 6 | public Transform target; 7 | public Vector3 offset = new Vector3(0, 5, -10); 8 | 9 | [Header("Smooth Settings")] 10 | public float smoothSpeed = 5f; 11 | public float rotationSpeed = 2f; 12 | 13 | [Header("Boundaries")] 14 | public float minY = 2f; 15 | public float maxY = 10f; 16 | public float minX = -10f; 17 | public float maxX = 10f; 18 | 19 | private void LateUpdate() 20 | { 21 | if (target == null) return; 22 | 23 | // Calculate desired position 24 | Vector3 desiredPosition = target.position + offset; 25 | 26 | // Clamp position within boundaries 27 | desiredPosition.y = Mathf.Clamp(desiredPosition.y, minY, maxY); 28 | desiredPosition.x = Mathf.Clamp(desiredPosition.x, minX, maxX); 29 | 30 | // Smoothly move camera 31 | Vector3 smoothedPosition = Vector3.Lerp(transform.position, desiredPosition, smoothSpeed * Time.deltaTime); 32 | transform.position = smoothedPosition; 33 | 34 | // Look at target 35 | Vector3 targetPosition = new Vector3(target.position.x, target.position.y, target.position.z); 36 | Quaternion targetRotation = Quaternion.LookRotation(targetPosition - transform.position); 37 | transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, rotationSpeed * Time.deltaTime); 38 | } 39 | } -------------------------------------------------------------------------------- /ChangeScenes.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine.SceneManagement; 4 | using UnityEngine; 5 | //xaimo 6 | public class ChangeScenes : MonoBehaviour 7 | { 8 | void OnTriggerEnter(Collider other) 9 | 10 | { 11 | SceneManager.LoadScene(0); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /DataManager.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System; 3 | 4 | public class DataManager : MonoBehaviour 5 | { 6 | public static DataManager Instance { get; private set; } 7 | 8 | private void Awake() 9 | { 10 | if (Instance == null) 11 | { 12 | Instance = this; 13 | DontDestroyOnLoad(gameObject); 14 | } 15 | else 16 | { 17 | Destroy(gameObject); 18 | } 19 | } 20 | 21 | public void SaveData(string key, object value) 22 | { 23 | if (value is int intValue) 24 | PlayerPrefs.SetInt(key, intValue); 25 | else if (value is float floatValue) 26 | PlayerPrefs.SetFloat(key, floatValue); 27 | else if (value is string stringValue) 28 | PlayerPrefs.SetString(key, stringValue); 29 | else 30 | Debug.LogError($"Unsupported data type for saving: {value.GetType()}"); 31 | 32 | PlayerPrefs.Save(); 33 | } 34 | 35 | public T LoadData(string key, T defaultValue) 36 | { 37 | if (!PlayerPrefs.HasKey(key)) 38 | return defaultValue; 39 | 40 | if (typeof(T) == typeof(int)) 41 | return (T)Convert.ChangeType(PlayerPrefs.GetInt(key), typeof(T)); 42 | else if (typeof(T) == typeof(float)) 43 | return (T)Convert.ChangeType(PlayerPrefs.GetFloat(key), typeof(T)); 44 | else if (typeof(T) == typeof(string)) 45 | return (T)Convert.ChangeType(PlayerPrefs.GetString(key), typeof(T)); 46 | else 47 | { 48 | Debug.LogError($"Unsupported data type for loading: {typeof(T)}"); 49 | return defaultValue; 50 | } 51 | } 52 | 53 | public void DeleteData(string key) 54 | { 55 | if (PlayerPrefs.HasKey(key)) 56 | { 57 | PlayerPrefs.DeleteKey(key); 58 | PlayerPrefs.Save(); 59 | } 60 | } 61 | 62 | public void DeleteAllData() 63 | { 64 | PlayerPrefs.DeleteAll(); 65 | PlayerPrefs.Save(); 66 | } 67 | } -------------------------------------------------------------------------------- /DialogueSystem.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEngine.UI; 3 | using System.Collections; 4 | using System.Collections.Generic; 5 | using TMPro; 6 | 7 | public class DialogueSystem : MonoBehaviour 8 | { 9 | public static DialogueSystem Instance { get; private set; } 10 | 11 | [Header("UI Components")] 12 | [SerializeField] private GameObject dialoguePanel; 13 | [SerializeField] private TextMeshProUGUI nameText; 14 | [SerializeField] private TextMeshProUGUI dialogueText; 15 | [SerializeField] private Image speakerImage; 16 | [SerializeField] private Button continueButton; 17 | 18 | [Header("Typing Settings")] 19 | [SerializeField] private float typingSpeed = 0.05f; 20 | [SerializeField] private AudioClip typingSound; 21 | [SerializeField] private AudioSource audioSource; 22 | 23 | private Queue sentences; 24 | private string currentSpeaker; 25 | private Sprite currentSpeakerImage; 26 | private bool isTyping = false; 27 | private Coroutine typingCoroutine; 28 | 29 | private void Awake() 30 | { 31 | if (Instance == null) 32 | { 33 | Instance = this; 34 | DontDestroyOnLoad(gameObject); 35 | sentences = new Queue(); 36 | } 37 | else 38 | { 39 | Destroy(gameObject); 40 | } 41 | } 42 | 43 | private void Start() 44 | { 45 | dialoguePanel.SetActive(false); 46 | if (continueButton != null) 47 | continueButton.onClick.AddListener(DisplayNextSentence); 48 | } 49 | 50 | public void StartDialogue(Dialogue dialogue) 51 | { 52 | dialoguePanel.SetActive(true); 53 | 54 | sentences.Clear(); 55 | 56 | foreach (string sentence in dialogue.sentences) 57 | { 58 | sentences.Enqueue(sentence); 59 | } 60 | 61 | currentSpeaker = dialogue.speakerName; 62 | currentSpeakerImage = dialogue.speakerImage; 63 | 64 | if (nameText != null) 65 | nameText.text = currentSpeaker; 66 | 67 | if (speakerImage != null && currentSpeakerImage != null) 68 | speakerImage.sprite = currentSpeakerImage; 69 | 70 | DisplayNextSentence(); 71 | } 72 | 73 | public void DisplayNextSentence() 74 | { 75 | if (isTyping) 76 | { 77 | // If currently typing, display full text immediately 78 | if (typingCoroutine != null) 79 | StopCoroutine(typingCoroutine); 80 | 81 | dialogueText.text = dialogueText.text; // Set to full text 82 | isTyping = false; 83 | return; 84 | } 85 | 86 | if (sentences.Count == 0) 87 | { 88 | EndDialogue(); 89 | return; 90 | } 91 | 92 | string sentence = sentences.Dequeue(); 93 | 94 | if (typingCoroutine != null) 95 | StopCoroutine(typingCoroutine); 96 | 97 | typingCoroutine = StartCoroutine(TypeSentence(sentence)); 98 | } 99 | 100 | private IEnumerator TypeSentence(string sentence) 101 | { 102 | isTyping = true; 103 | dialogueText.text = ""; 104 | 105 | foreach (char letter in sentence.ToCharArray()) 106 | { 107 | dialogueText.text += letter; 108 | 109 | if (typingSound != null && audioSource != null) 110 | audioSource.PlayOneShot(typingSound); 111 | 112 | yield return new WaitForSeconds(typingSpeed); 113 | } 114 | 115 | isTyping = false; 116 | } 117 | 118 | private void EndDialogue() 119 | { 120 | dialoguePanel.SetActive(false); 121 | } 122 | } 123 | 124 | [System.Serializable] 125 | public class Dialogue 126 | { 127 | public string speakerName; 128 | public Sprite speakerImage; 129 | public string[] sentences; 130 | } -------------------------------------------------------------------------------- /FPS.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEngine.UI; 5 | 6 | public class FPS : MonoBehaviour 7 | { 8 | 9 | public Text text; 10 | public int fps; 11 | 12 | void Start() 13 | { 14 | text = GetComponent(); 15 | StartCoroutine(UpdateFPS()); 16 | } 17 | 18 | void Update() 19 | { 20 | fps = (int)(1f / Time.deltaTime); 21 | } 22 | 23 | IEnumerator UpdateFPS() 24 | { 25 | while (true) 26 | { 27 | text.text = "" + fps + " FPS"; 28 | yield return new WaitForSeconds(0.16f); 29 | } 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /FirstPersonControl.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | public class FirstPersonControl : MonoBehaviour { 6 | 7 | public GameObject player ; 8 | 9 | private bool inMouseMode = false ; 10 | private float rotationX ; 11 | private float rotationY ; 12 | 13 | void Start() 14 | { 15 | Cursor.lockState = CursorLockMode.Locked ; 16 | Cursor.visible = false ; 17 | } 18 | 19 | void Update () 20 | { 21 | if(Input.GetKeyDown(KeyCode.Space)) { 22 | Cursor.lockState = CursorLockMode.None ; 23 | Cursor.visible = true ; 24 | inMouseMode = true ; 25 | } 26 | if(Input.GetKeyUp(KeyCode.Space)) { 27 | Cursor.lockState = CursorLockMode.Locked ; 28 | Cursor.visible = false ; 29 | inMouseMode = false ; 30 | } 31 | 32 | if(!inMouseMode) { 33 | player.transform.Translate(Input.GetAxis("Horizontal") * Time.deltaTime * 10f, 0f, 0f) ; 34 | player.transform.Translate(0f, 0f, Input.GetAxis("Vertical") * Time.deltaTime * 10f) ; 35 | rotationY += transform.localEulerAngles.y + Input.GetAxis("Mouse X") * 2.0f ; 36 | rotationX += Input.GetAxis("Mouse Y") * 2.0f ; 37 | Camera.main.transform.localEulerAngles = new Vector3(-rotationX, 0f, 0f) ; 38 | player.transform.localEulerAngles = new Vector3(0f, rotationY, 0f) ; 39 | } 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /GameManager.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | 4 | public class GameManager : MonoBehaviour 5 | { 6 | public static GameManager Instance { get; private set; } 7 | 8 | public bool isGamePaused { get; private set; } 9 | public bool isGameOver { get; private set; } 10 | 11 | private void Awake() 12 | { 13 | if (Instance == null) 14 | { 15 | Instance = this; 16 | DontDestroyOnLoad(gameObject); 17 | } 18 | else 19 | { 20 | Destroy(gameObject); 21 | } 22 | } 23 | 24 | public void PauseGame() 25 | { 26 | isGamePaused = true; 27 | Time.timeScale = 0f; 28 | } 29 | 30 | public void ResumeGame() 31 | { 32 | isGamePaused = false; 33 | Time.timeScale = 1f; 34 | } 35 | 36 | public void GameOver() 37 | { 38 | isGameOver = true; 39 | // Add your game over logic here 40 | } 41 | 42 | public void RestartGame() 43 | { 44 | isGameOver = false; 45 | // Add your restart logic here 46 | } 47 | } -------------------------------------------------------------------------------- /HealthSystem.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEngine.Events; 3 | 4 | public class HealthSystem : MonoBehaviour 5 | { 6 | [Header("Health Settings")] 7 | public float maxHealth = 100f; 8 | public float currentHealth; 9 | public bool isInvulnerable = false; 10 | 11 | [Header("Events")] 12 | public UnityEvent onDeath; 13 | public UnityEvent onHealthChanged; 14 | public UnityEvent onDamageTaken; 15 | public UnityEvent onHealed; 16 | 17 | private void Start() 18 | { 19 | currentHealth = maxHealth; 20 | onHealthChanged?.Invoke(currentHealth); 21 | } 22 | 23 | public void TakeDamage(float damage) 24 | { 25 | if (isInvulnerable) return; 26 | 27 | currentHealth = Mathf.Max(0, currentHealth - damage); 28 | onDamageTaken?.Invoke(damage); 29 | onHealthChanged?.Invoke(currentHealth); 30 | 31 | if (currentHealth <= 0) 32 | { 33 | Die(); 34 | } 35 | } 36 | 37 | public void Heal(float amount) 38 | { 39 | currentHealth = Mathf.Min(maxHealth, currentHealth + amount); 40 | onHealed?.Invoke(amount); 41 | onHealthChanged?.Invoke(currentHealth); 42 | } 43 | 44 | public void SetInvulnerable(bool invulnerable) 45 | { 46 | isInvulnerable = invulnerable; 47 | } 48 | 49 | private void Die() 50 | { 51 | onDeath?.Invoke(); 52 | // Add additional death logic here 53 | } 54 | 55 | public float GetHealthPercentage() 56 | { 57 | return currentHealth / maxHealth; 58 | } 59 | 60 | public bool IsAlive() 61 | { 62 | return currentHealth > 0; 63 | } 64 | } -------------------------------------------------------------------------------- /HideTrigger.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEngine.UI; 5 | 6 | public class HideTrigger : MonoBehaviour 7 | { 8 | public GameObject EnterText; 9 | 10 | void OnTriggerEnter(Collider other) 11 | { 12 | EnterText.GetComponent().text = "Your Text"; 13 | } 14 | 15 | void OnTriggerExit(Collider other) 16 | { 17 | EnterText.GetComponent().text = ""; 18 | } 19 | 20 | 21 | } 22 | -------------------------------------------------------------------------------- /InventorySystem.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections.Generic; 3 | using UnityEngine.Events; 4 | 5 | public class InventorySystem : MonoBehaviour 6 | { 7 | public static InventorySystem Instance { get; private set; } 8 | 9 | [Header("Settings")] 10 | [SerializeField] private int maxInventorySlots = 20; 11 | 12 | // Events 13 | public UnityEvent OnItemAdded; 14 | public UnityEvent OnItemRemoved; 15 | public UnityEvent OnItemUsed; 16 | public UnityEvent OnInventoryChanged; 17 | 18 | private List inventoryItems = new List(); 19 | 20 | private void Awake() 21 | { 22 | if (Instance == null) 23 | { 24 | Instance = this; 25 | DontDestroyOnLoad(gameObject); 26 | } 27 | else 28 | { 29 | Destroy(gameObject); 30 | } 31 | 32 | // Initialize events if null 33 | if (OnItemAdded == null) OnItemAdded = new UnityEvent(); 34 | if (OnItemRemoved == null) OnItemRemoved = new UnityEvent(); 35 | if (OnItemUsed == null) OnItemUsed = new UnityEvent(); 36 | if (OnInventoryChanged == null) OnInventoryChanged = new UnityEvent(); 37 | } 38 | 39 | public bool AddItem(InventoryItem item) 40 | { 41 | if (inventoryItems.Count >= maxInventorySlots) 42 | { 43 | Debug.Log("Inventory is full!"); 44 | return false; 45 | } 46 | 47 | // Check if the item is stackable and already exists 48 | if (item.isStackable) 49 | { 50 | InventoryItem existingItem = inventoryItems.Find(i => i.itemID == item.itemID); 51 | 52 | if (existingItem != null) 53 | { 54 | existingItem.quantity += item.quantity; 55 | OnInventoryChanged.Invoke(); 56 | OnItemAdded.Invoke(item); 57 | return true; 58 | } 59 | } 60 | 61 | // Add new item 62 | inventoryItems.Add(item); 63 | OnInventoryChanged.Invoke(); 64 | OnItemAdded.Invoke(item); 65 | return true; 66 | } 67 | 68 | public bool RemoveItem(string itemID, int quantity = 1) 69 | { 70 | InventoryItem item = inventoryItems.Find(i => i.itemID == itemID); 71 | 72 | if (item == null) 73 | { 74 | Debug.Log("Item not found in inventory!"); 75 | return false; 76 | } 77 | 78 | if (item.quantity < quantity) 79 | { 80 | Debug.Log("Not enough items to remove!"); 81 | return false; 82 | } 83 | 84 | item.quantity -= quantity; 85 | 86 | if (item.quantity <= 0) 87 | { 88 | inventoryItems.Remove(item); 89 | } 90 | 91 | OnInventoryChanged.Invoke(); 92 | OnItemRemoved.Invoke(item); 93 | return true; 94 | } 95 | 96 | public bool UseItem(string itemID) 97 | { 98 | InventoryItem item = inventoryItems.Find(i => i.itemID == itemID); 99 | 100 | if (item == null) 101 | { 102 | Debug.Log("Item not found in inventory!"); 103 | return false; 104 | } 105 | 106 | // Handle consumable items 107 | if (item.isConsumable) 108 | { 109 | item.quantity--; 110 | 111 | if (item.quantity <= 0) 112 | { 113 | inventoryItems.Remove(item); 114 | } 115 | } 116 | 117 | OnInventoryChanged.Invoke(); 118 | OnItemUsed.Invoke(item); 119 | return true; 120 | } 121 | 122 | public List GetAllItems() 123 | { 124 | return new List(inventoryItems); 125 | } 126 | 127 | public InventoryItem GetItem(string itemID) 128 | { 129 | return inventoryItems.Find(i => i.itemID == itemID); 130 | } 131 | 132 | public int GetItemCount(string itemID) 133 | { 134 | InventoryItem item = inventoryItems.Find(i => i.itemID == itemID); 135 | return item != null ? item.quantity : 0; 136 | } 137 | 138 | public bool HasItem(string itemID, int quantity = 1) 139 | { 140 | return GetItemCount(itemID) >= quantity; 141 | } 142 | 143 | public void ClearInventory() 144 | { 145 | inventoryItems.Clear(); 146 | OnInventoryChanged.Invoke(); 147 | } 148 | } 149 | 150 | [System.Serializable] 151 | public class InventoryItem 152 | { 153 | public string itemID; 154 | public string itemName; 155 | public string description; 156 | public Sprite icon; 157 | public int quantity = 1; 158 | public bool isStackable = true; 159 | public bool isConsumable = false; 160 | public ItemType itemType = ItemType.Misc; 161 | public Dictionary stats = new Dictionary(); 162 | 163 | public InventoryItem(string id, string name, string desc, Sprite itemIcon, int qty = 1) 164 | { 165 | itemID = id; 166 | itemName = name; 167 | description = desc; 168 | icon = itemIcon; 169 | quantity = qty; 170 | } 171 | } 172 | 173 | public enum ItemType 174 | { 175 | Weapon, 176 | Armor, 177 | Consumable, 178 | Quest, 179 | Misc 180 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Unity Tool Scripts 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /Light_Flirking: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | public class Light_Flirking : MonoBehaviour 6 | { 7 | public bool IsFlickering = false; 8 | public float timeDelay; 9 | 10 | void Update() 11 | { 12 | if (IsFlickering == false) 13 | { 14 | StartCoroutine(FlirkingLight()); 15 | } 16 | } 17 | IEnumerator FlirkingLight() 18 | { 19 | IsFlickering = true; 20 | this.gameObject.GetComponent().enabled = false; 21 | timeDelay = Random.Range(0.01f, 0.1f); 22 | yield return new WaitForSeconds(timeDelay); 23 | this.gameObject.GetComponent().enabled = true; 24 | timeDelay = Random.Range(0.01f, 0.1f); 25 | yield return new WaitForSeconds(timeDelay); 26 | IsFlickering = false; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ObjectPooler.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections.Generic; 3 | 4 | public class ObjectPooler : MonoBehaviour 5 | { 6 | public static ObjectPooler Instance { get; private set; } 7 | 8 | [System.Serializable] 9 | public class Pool 10 | { 11 | public string tag; 12 | public GameObject prefab; 13 | public int size; 14 | public bool expandable = true; 15 | } 16 | 17 | [SerializeField] private List pools; 18 | 19 | private Dictionary> poolDictionary; 20 | private Dictionary prefabDictionary; 21 | private Dictionary expandableDictionary; 22 | private Dictionary objectToTagDictionary; 23 | 24 | private void Awake() 25 | { 26 | if (Instance == null) 27 | { 28 | Instance = this; 29 | DontDestroyOnLoad(gameObject); 30 | } 31 | else 32 | { 33 | Destroy(gameObject); 34 | return; 35 | } 36 | 37 | poolDictionary = new Dictionary>(); 38 | prefabDictionary = new Dictionary(); 39 | expandableDictionary = new Dictionary(); 40 | objectToTagDictionary = new Dictionary(); 41 | 42 | InitializePools(); 43 | } 44 | 45 | private void InitializePools() 46 | { 47 | foreach (Pool pool in pools) 48 | { 49 | Queue objectPool = new Queue(); 50 | 51 | // Create a parent object for organization 52 | GameObject poolParent = new GameObject(pool.tag + "_Pool"); 53 | poolParent.transform.SetParent(transform); 54 | 55 | for (int i = 0; i < pool.size; i++) 56 | { 57 | GameObject obj = Instantiate(pool.prefab, poolParent.transform); 58 | obj.SetActive(false); 59 | objectPool.Enqueue(obj); 60 | objectToTagDictionary.Add(obj, pool.tag); 61 | } 62 | 63 | poolDictionary.Add(pool.tag, objectPool); 64 | prefabDictionary.Add(pool.tag, pool.prefab); 65 | expandableDictionary.Add(pool.tag, pool.expandable); 66 | } 67 | } 68 | 69 | public GameObject SpawnFromPool(string tag, Vector3 position, Quaternion rotation) 70 | { 71 | if (!poolDictionary.ContainsKey(tag)) 72 | { 73 | Debug.LogWarning("Pool with tag " + tag + " doesn't exist!"); 74 | return null; 75 | } 76 | 77 | Queue objectPool = poolDictionary[tag]; 78 | 79 | // If the pool is empty and not expandable, return null 80 | if (objectPool.Count == 0 && !expandableDictionary[tag]) 81 | { 82 | Debug.LogWarning("No more objects in pool " + tag + " and it's not expandable!"); 83 | return null; 84 | } 85 | 86 | // If the pool is empty but expandable, create a new object 87 | if (objectPool.Count == 0) 88 | { 89 | GameObject newObj = Instantiate(prefabDictionary[tag], transform.Find(tag + "_Pool")); 90 | objectToTagDictionary.Add(newObj, tag); 91 | newObj.SetActive(false); 92 | objectPool.Enqueue(newObj); 93 | } 94 | 95 | GameObject objectToSpawn = objectPool.Dequeue(); 96 | objectToSpawn.SetActive(true); 97 | objectToSpawn.transform.position = position; 98 | objectToSpawn.transform.rotation = rotation; 99 | 100 | // Call OnObjectSpawn method if the object has IPooledObject interface 101 | IPooledObject pooledObj = objectToSpawn.GetComponent(); 102 | if (pooledObj != null) 103 | { 104 | pooledObj.OnObjectSpawn(); 105 | } 106 | 107 | return objectToSpawn; 108 | } 109 | 110 | public void ReturnToPool(GameObject obj) 111 | { 112 | if (!objectToTagDictionary.ContainsKey(obj)) 113 | { 114 | Debug.LogWarning("This object wasn't created from a pool!"); 115 | return; 116 | } 117 | 118 | string tag = objectToTagDictionary[obj]; 119 | obj.SetActive(false); 120 | poolDictionary[tag].Enqueue(obj); 121 | } 122 | 123 | public void ClearPool(string tag) 124 | { 125 | if (!poolDictionary.ContainsKey(tag)) 126 | { 127 | Debug.LogWarning("Pool with tag " + tag + " doesn't exist!"); 128 | return; 129 | } 130 | 131 | Queue objectPool = poolDictionary[tag]; 132 | while (objectPool.Count > 0) 133 | { 134 | GameObject obj = objectPool.Dequeue(); 135 | Destroy(obj); 136 | } 137 | } 138 | 139 | public void ClearAllPools() 140 | { 141 | foreach (var pool in poolDictionary) 142 | { 143 | ClearPool(pool.Key); 144 | } 145 | } 146 | } 147 | 148 | // Interface for objects that need special initialization when spawned from pool 149 | public interface IPooledObject 150 | { 151 | void OnObjectSpawn(); 152 | } -------------------------------------------------------------------------------- /PanelOpener.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | public class PanelOpener : MonoBehaviour 6 | { 7 | public GameObject Panel; 8 | 9 | public void openPanel() 10 | { 11 | if(Panel != null) 12 | { 13 | Panel.SetActive(true); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /PauseMenu.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEngine.SceneManagement; 5 | 6 | public class PauseMenu : MonoBehaviour 7 | { 8 | public static bool GameIsPaused = false; 9 | 10 | public GameObject PauseMenuUI; 11 | 12 | // Update is called once per frame 13 | void Update() { 14 | if (Input.GetKeyDown(KeyCode.Escape)) 15 | { 16 | if (GameIsPaused) 17 | { 18 | Resume(); 19 | } else 20 | { 21 | Pause(); 22 | } 23 | } 24 | } 25 | 26 | public void Resume() 27 | { 28 | PauseMenuUI.SetActive(false); 29 | Time.timeScale = 1f; 30 | GameIsPaused = false; 31 | } 32 | void Pause () 33 | { 34 | PauseMenuUI.SetActive(true); 35 | Time.timeScale = 0f; 36 | GameIsPaused = true; 37 | } 38 | public void LoadMenu() 39 | { 40 | Time.timeScale = 1f; 41 | SceneManager.LoadScene("Menu"); 42 | } 43 | 44 | public void QuitGame() 45 | { 46 | Debug.Log ("Quiting Game..."); 47 | Application.Quit(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /PlayerController.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using UnityEngine; 3 | using UnityEngine.InputSystem.Interactions; 4 | 5 | // Use action set asset instead of lose InputActions directly on component. 6 | public class SimpleController_UsingActionAsset : MonoBehaviour 7 | { 8 | public float moveSpeed; 9 | public float rotateSpeed; 10 | public float burstSpeed; 11 | public GameObject projectile; 12 | 13 | private SimpleControls m_Controls; 14 | private bool m_Charging; 15 | private Vector2 m_Rotation; 16 | 17 | public void Awake() 18 | { 19 | m_Controls = new SimpleControls(); 20 | 21 | m_Controls.gameplay.fire.performed += 22 | ctx => 23 | { 24 | if (ctx.interaction is SlowTapInteraction) 25 | { 26 | StartCoroutine(BurstFire((int)(ctx.duration * burstSpeed))); 27 | } 28 | else 29 | { 30 | Fire(); 31 | } 32 | m_Charging = false; 33 | }; 34 | m_Controls.gameplay.fire.started += 35 | ctx => 36 | { 37 | if (ctx.interaction is SlowTapInteraction) 38 | m_Charging = true; 39 | }; 40 | m_Controls.gameplay.fire.canceled += 41 | ctx => 42 | { 43 | m_Charging = false; 44 | }; 45 | } 46 | 47 | public void OnEnable() 48 | { 49 | m_Controls.Enable(); 50 | } 51 | 52 | public void OnDisable() 53 | { 54 | m_Controls.Disable(); 55 | } 56 | 57 | public void OnGUI() 58 | { 59 | if (m_Charging) 60 | GUI.Label(new Rect(100, 100, 200, 100), "Charging..."); 61 | } 62 | 63 | public void Update() 64 | { 65 | var look = m_Controls.gameplay.look.ReadValue(); 66 | var move = m_Controls.gameplay.move.ReadValue(); 67 | 68 | // Update orientation first, then move. Otherwise move orientation will lag 69 | // behind by one frame. 70 | Look(look); 71 | Move(move); 72 | } 73 | 74 | private void Move(Vector2 direction) 75 | { 76 | if (direction.sqrMagnitude < 0.01) 77 | return; 78 | var scaledMoveSpeed = moveSpeed * Time.deltaTime; 79 | // For simplicity's sake, we just keep movement in a single plane here. Rotate 80 | // direction according to world Y rotation of player. 81 | 82 | var move = Quaternion.Euler(0, transform.eulerAngles.y, 0) * new Vector3(direction.x, 0, direction.y); 83 | transform.position += move * scaledMoveSpeed; 84 | } 85 | 86 | private void Look(Vector2 rotate) 87 | { 88 | if (rotate.sqrMagnitude < 0.01) 89 | return; 90 | var scaledRotateSpeed = rotateSpeed * Time.deltaTime; 91 | m_Rotation.y += rotate.x * scaledRotateSpeed; 92 | m_Rotation.x = Mathf.Clamp(m_Rotation.x - rotate.y * scaledRotateSpeed, -89, 89); 93 | transform.localEulerAngles = m_Rotation; 94 | } 95 | 96 | private IEnumerator BurstFire(int burstAmount) 97 | { 98 | for (var i = 0; i < burstAmount; ++i) 99 | { 100 | Fire(); 101 | yield return new WaitForSeconds(0.1f); 102 | } 103 | } 104 | 105 | private void Fire() 106 | { 107 | var transform = this.transform; 108 | var newProjectile = Instantiate(projectile); 109 | newProjectile.transform.position = transform.position + transform.forward * 0.6f; 110 | newProjectile.transform.rotation = transform.rotation; 111 | const int size = 1; 112 | newProjectile.transform.localScale *= size; 113 | newProjectile.GetComponent().mass = Mathf.Pow(size, 3); 114 | newProjectile.GetComponent().AddForce(transform.forward * 20f, ForceMode.Impulse); 115 | newProjectile.GetComponent().material.color = 116 | new Color(Random.value, Random.value, Random.value, 1.0f); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /QuestSystem.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections.Generic; 3 | using UnityEngine.Events; 4 | 5 | public class QuestSystem : MonoBehaviour 6 | { 7 | public static QuestSystem Instance { get; private set; } 8 | 9 | [Header("Settings")] 10 | [SerializeField] private List availableQuests = new List(); 11 | 12 | // Events 13 | public UnityEvent OnQuestStarted; 14 | public UnityEvent OnQuestCompleted; 15 | public UnityEvent OnQuestFailed; 16 | public UnityEvent OnObjectiveCompleted; 17 | public UnityEvent OnObjectiveUpdated; 18 | 19 | private List activeQuests = new List(); 20 | private List completedQuests = new List(); 21 | private List failedQuests = new List(); 22 | 23 | private void Awake() 24 | { 25 | if (Instance == null) 26 | { 27 | Instance = this; 28 | DontDestroyOnLoad(gameObject); 29 | } 30 | else 31 | { 32 | Destroy(gameObject); 33 | return; 34 | } 35 | 36 | // Initialize events if null 37 | if (OnQuestStarted == null) OnQuestStarted = new UnityEvent(); 38 | if (OnQuestCompleted == null) OnQuestCompleted = new UnityEvent(); 39 | if (OnQuestFailed == null) OnQuestFailed = new UnityEvent(); 40 | if (OnObjectiveCompleted == null) OnObjectiveCompleted = new UnityEvent(); 41 | if (OnObjectiveUpdated == null) OnObjectiveUpdated = new UnityEvent(); 42 | } 43 | 44 | public void StartQuest(string questID) 45 | { 46 | Quest quest = availableQuests.Find(q => q.questID == questID); 47 | 48 | if (quest == null) 49 | { 50 | Debug.LogWarning("Quest with ID " + questID + " not found!"); 51 | return; 52 | } 53 | 54 | if (activeQuests.Contains(quest) || completedQuests.Contains(quest)) 55 | { 56 | Debug.Log("Quest already active or completed!"); 57 | return; 58 | } 59 | 60 | // Check quest requirements 61 | if (!CheckQuestRequirements(quest)) 62 | { 63 | Debug.Log("Quest requirements not met!"); 64 | return; 65 | } 66 | 67 | // Clone the quest to avoid modifying the original 68 | Quest activeQuest = Instantiate(quest); 69 | activeQuest.status = QuestStatus.InProgress; 70 | activeQuest.InitializeObjectives(); 71 | 72 | activeQuests.Add(activeQuest); 73 | OnQuestStarted.Invoke(activeQuest); 74 | 75 | Debug.Log("Started quest: " + activeQuest.questName); 76 | } 77 | 78 | public void CompleteObjective(string questID, string objectiveID, int amount = 1) 79 | { 80 | Quest quest = activeQuests.Find(q => q.questID == questID); 81 | 82 | if (quest == null) 83 | { 84 | Debug.LogWarning("Active quest with ID " + questID + " not found!"); 85 | return; 86 | } 87 | 88 | QuestObjective objective = quest.objectives.Find(o => o.objectiveID == objectiveID); 89 | 90 | if (objective == null) 91 | { 92 | Debug.LogWarning("Objective with ID " + objectiveID + " not found in quest " + questID); 93 | return; 94 | } 95 | 96 | if (objective.isCompleted) 97 | { 98 | return; 99 | } 100 | 101 | objective.currentAmount += amount; 102 | OnObjectiveUpdated.Invoke(objective); 103 | 104 | if (objective.currentAmount >= objective.requiredAmount) 105 | { 106 | objective.isCompleted = true; 107 | OnObjectiveCompleted.Invoke(objective); 108 | 109 | Debug.Log("Completed objective: " + objective.description); 110 | 111 | // Check if all objectives are completed 112 | if (quest.AreAllObjectivesCompleted()) 113 | { 114 | CompleteQuest(quest); 115 | } 116 | } 117 | } 118 | 119 | private void CompleteQuest(Quest quest) 120 | { 121 | quest.status = QuestStatus.Completed; 122 | activeQuests.Remove(quest); 123 | completedQuests.Add(quest); 124 | 125 | // Award quest rewards 126 | GiveQuestRewards(quest); 127 | 128 | OnQuestCompleted.Invoke(quest); 129 | Debug.Log("Completed quest: " + quest.questName); 130 | } 131 | 132 | public void FailQuest(string questID) 133 | { 134 | Quest quest = activeQuests.Find(q => q.questID == questID); 135 | 136 | if (quest == null) 137 | { 138 | Debug.LogWarning("Active quest with ID " + questID + " not found!"); 139 | return; 140 | } 141 | 142 | quest.status = QuestStatus.Failed; 143 | activeQuests.Remove(quest); 144 | failedQuests.Add(quest); 145 | 146 | OnQuestFailed.Invoke(quest); 147 | Debug.Log("Failed quest: " + quest.questName); 148 | } 149 | 150 | private bool CheckQuestRequirements(Quest quest) 151 | { 152 | // Check for required completed quests 153 | foreach (string requiredQuestID in quest.requiredQuests) 154 | { 155 | bool found = false; 156 | 157 | foreach (Quest completedQuest in completedQuests) 158 | { 159 | if (completedQuest.questID == requiredQuestID) 160 | { 161 | found = true; 162 | break; 163 | } 164 | } 165 | 166 | if (!found) 167 | { 168 | return false; 169 | } 170 | } 171 | 172 | // Check for level requirement 173 | if (quest.requiredLevel > 0) 174 | { 175 | // This is where you would check player level 176 | // For demo purposes, always return true 177 | // int playerLevel = GameManager.Instance.GetPlayerLevel(); 178 | // if (playerLevel < quest.requiredLevel) 179 | // { 180 | // return false; 181 | // } 182 | } 183 | 184 | return true; 185 | } 186 | 187 | private void GiveQuestRewards(Quest quest) 188 | { 189 | // This is where you would give the player rewards 190 | // For example: 191 | // if (quest.rewardGold > 0) 192 | // { 193 | // GameManager.Instance.AddPlayerGold(quest.rewardGold); 194 | // } 195 | // 196 | // if (quest.rewardExperience > 0) 197 | // { 198 | // GameManager.Instance.AddPlayerExperience(quest.rewardExperience); 199 | // } 200 | // 201 | // foreach (ItemReward itemReward in quest.rewardItems) 202 | // { 203 | // InventorySystem.Instance.AddItem(itemReward.itemID, itemReward.quantity); 204 | // } 205 | } 206 | 207 | public List GetAllQuests() 208 | { 209 | return availableQuests; 210 | } 211 | 212 | public List GetActiveQuests() 213 | { 214 | return activeQuests; 215 | } 216 | 217 | public List GetCompletedQuests() 218 | { 219 | return completedQuests; 220 | } 221 | 222 | public List GetFailedQuests() 223 | { 224 | return failedQuests; 225 | } 226 | 227 | public Quest GetQuest(string questID) 228 | { 229 | Quest quest = availableQuests.Find(q => q.questID == questID); 230 | 231 | if (quest == null) 232 | { 233 | Debug.LogWarning("Quest with ID " + questID + " not found!"); 234 | } 235 | 236 | return quest; 237 | } 238 | 239 | public QuestStatus GetQuestStatus(string questID) 240 | { 241 | foreach (Quest quest in activeQuests) 242 | { 243 | if (quest.questID == questID) 244 | { 245 | return QuestStatus.InProgress; 246 | } 247 | } 248 | 249 | foreach (Quest quest in completedQuests) 250 | { 251 | if (quest.questID == questID) 252 | { 253 | return QuestStatus.Completed; 254 | } 255 | } 256 | 257 | foreach (Quest quest in failedQuests) 258 | { 259 | if (quest.questID == questID) 260 | { 261 | return QuestStatus.Failed; 262 | } 263 | } 264 | 265 | return QuestStatus.NotStarted; 266 | } 267 | } 268 | 269 | [System.Serializable] 270 | public class Quest 271 | { 272 | public string questID; 273 | public string questName; 274 | [TextArea(3, 5)] 275 | public string description; 276 | public QuestType questType = QuestType.Main; 277 | public QuestStatus status = QuestStatus.NotStarted; 278 | 279 | [Header("Requirements")] 280 | public int requiredLevel; 281 | public List requiredQuests = new List(); 282 | 283 | [Header("Objectives")] 284 | public List objectives = new List(); 285 | 286 | [Header("Rewards")] 287 | public int rewardGold; 288 | public int rewardExperience; 289 | public List rewardItems = new List(); 290 | 291 | [Header("Other")] 292 | public bool isAutoComplete = false; 293 | public bool isTimed = false; 294 | public float timeLimit = 0f; 295 | 296 | public void InitializeObjectives() 297 | { 298 | foreach (QuestObjective objective in objectives) 299 | { 300 | objective.currentAmount = 0; 301 | objective.isCompleted = false; 302 | } 303 | } 304 | 305 | public bool AreAllObjectivesCompleted() 306 | { 307 | foreach (QuestObjective objective in objectives) 308 | { 309 | if (!objective.isCompleted) 310 | { 311 | return false; 312 | } 313 | } 314 | 315 | return true; 316 | } 317 | } 318 | 319 | [System.Serializable] 320 | public class QuestObjective 321 | { 322 | public string objectiveID; 323 | [TextArea(2, 3)] 324 | public string description; 325 | public QuestObjectiveType type = QuestObjectiveType.Collect; 326 | public int requiredAmount = 1; 327 | public int currentAmount = 0; 328 | public bool isCompleted = false; 329 | public bool isOptional = false; 330 | 331 | public float GetProgress() 332 | { 333 | return (float)currentAmount / requiredAmount; 334 | } 335 | } 336 | 337 | [System.Serializable] 338 | public class ItemReward 339 | { 340 | public string itemID; 341 | public int quantity = 1; 342 | } 343 | 344 | public enum QuestType 345 | { 346 | Main, 347 | Side, 348 | Daily, 349 | World, 350 | Repeatable 351 | } 352 | 353 | public enum QuestStatus 354 | { 355 | NotStarted, 356 | InProgress, 357 | Completed, 358 | Failed 359 | } 360 | 361 | public enum QuestObjectiveType 362 | { 363 | Kill, 364 | Collect, 365 | Interact, 366 | Escort, 367 | Talk, 368 | Reach, 369 | Defend, 370 | Craft, 371 | Discover 372 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Unity Tool Scripts 2 | 3 | A collection of useful Unity scripts for common game development tasks. 4 | 5 | ## New Updates (May 2025) 6 | 7 | Added six powerful systems to enhance your Unity projects: 8 | 9 | ### 1. DialogueSystem 10 | - Typed text effect with configurable speed 11 | - Support for character portraits and names 12 | - Event-driven dialogue progression 13 | - Audio support for typing sounds 14 | - Easy to integrate with UI elements 15 | - Handles dialogue sequences with multiple sentences 16 | 17 | ### 2. InventorySystem 18 | - Flexible item management with stacking support 19 | - Events for item addition, removal, and usage 20 | - Support for different item types (weapons, consumables, etc.) 21 | - Easy to integrate with UI through events 22 | - Custom item properties with dictionary-based stats 23 | 24 | ### 3. ObjectPooler 25 | - Efficient object instantiation and recycling 26 | - Reduces garbage collection and improves performance 27 | - Supports multiple object pools with different prefabs 28 | - Expandable pools for dynamic content 29 | - Interface for custom initialization on object spawn 30 | 31 | ### 4. SaveSystem 32 | - Binary serialization for game data 33 | - Optional encryption for secure saves 34 | - Auto-save functionality with configurable intervals 35 | - Interface for objects that need to save/load data 36 | - Easy to use API for saving custom data types 37 | 38 | ### 5. QuestSystem 39 | - Comprehensive quest management 40 | - Support for multiple quest types and objectives 41 | - Quest requirements and prerequisites 42 | - Reward system for quest completion 43 | - Progress tracking for objectives 44 | - Event-driven updates for UI integration 45 | 46 | ### 6. AudioManager 47 | - Centralized audio playback system 48 | - Separate channels for music, SFX, ambience, and UI sounds 49 | - Smooth fade transitions between tracks 50 | - 3D positional audio support 51 | - Volume control with settings persistence 52 | - Audio mixer integration 53 | - Sound collection management 54 | 55 | ## Previous Updates (April 2024) 56 | 57 | Added five utility scripts to enhance game development: 58 | 59 | ### 1. GameManager 60 | - Singleton pattern implementation 61 | - Handles game state management 62 | - Controls game pausing and resuming 63 | - Manages game over state 64 | - Easy to extend with custom game logic 65 | 66 | ### 2. DataManager 67 | - Handles data persistence using PlayerPrefs 68 | - Supports saving and loading different data types (int, float, string) 69 | - Provides methods for data deletion 70 | - Type-safe data loading with generics 71 | - Automatic data saving 72 | 73 | ### 3. CameraController 74 | - Smooth camera following behavior 75 | - Configurable offset and boundaries 76 | - Adjustable smooth speed and rotation speed 77 | - Prevents camera from going out of bounds 78 | - Easy to set up with target object 79 | 80 | ### 4. HealthSystem 81 | - Flexible health management system 82 | - Supports damage and healing 83 | - Includes invulnerability state 84 | - Event-driven system for health changes 85 | - Easy integration with UI elements 86 | - Death handling with custom events 87 | 88 | ### 5. TooltipManager 89 | - Smooth UI tooltip system 90 | - Fade in/out animations 91 | - Configurable delay and offset 92 | - Follows mouse position 93 | - Uses TextMeshPro for better text rendering 94 | - Canvas group for smooth transitions 95 | 96 | ## Setup Instructions 97 | 98 | 1. Create empty GameObjects in your scene for the managers: 99 | - GameManager 100 | - DataManager 101 | - TooltipManager 102 | - DialogueSystem 103 | - InventorySystem 104 | - ObjectPooler 105 | - SaveSystem 106 | - QuestSystem 107 | - AudioManager 108 | 109 | 2. Attach the respective scripts to these GameObjects 110 | 111 | 3. For CameraController: 112 | - Attach to your main camera 113 | - Set the target in the inspector 114 | - Adjust offset and boundaries as needed 115 | 116 | 4. For HealthSystem: 117 | - Attach to any object that needs health management 118 | - Configure max health and other settings in inspector 119 | - Set up event listeners for health changes 120 | 121 | 5. For TooltipManager: 122 | - Create a UI panel with TextMeshPro component 123 | - Assign references in the inspector 124 | - Configure show delay and fade speed 125 | 126 | 6. For DialogueSystem: 127 | - Create UI elements for dialogue panel, name text, and dialogue text 128 | - Assign references in the inspector 129 | - Set up TextMeshPro components 130 | 131 | 7. For ObjectPooler: 132 | - Define pools in the inspector with prefabs, sizes, and tags 133 | - Use the pooling API to spawn and recycle objects 134 | 135 | 8. For SaveSystem: 136 | - Configure save settings like filename and encryption 137 | - Implement ISaveable interface on objects that need saving 138 | 139 | 9. For QuestSystem: 140 | - Define quests in the inspector with objectives and rewards 141 | - Connect UI elements to events for updates 142 | 143 | 10. For AudioManager: 144 | - Create audio sources or let the system create them automatically 145 | - Define sound collections in the inspector 146 | - Create an Audio Mixer with appropriate groups (optional) 147 | - Set up volume sliders in the UI connected to the volume methods 148 | 149 | ## Usage Examples 150 | 151 | ### GameManager 152 | ```csharp 153 | // Pause game 154 | GameManager.Instance.PauseGame(); 155 | 156 | // Resume game 157 | GameManager.Instance.ResumeGame(); 158 | 159 | // Check game state 160 | if (GameManager.Instance.isGamePaused) { 161 | // Handle pause state 162 | } 163 | ``` 164 | 165 | ### DataManager 166 | ```csharp 167 | // Save data 168 | DataManager.Instance.SaveData("PlayerScore", 100); 169 | 170 | // Load data 171 | int score = DataManager.Instance.LoadData("PlayerScore", 0); 172 | 173 | // Delete data 174 | DataManager.Instance.DeleteData("PlayerScore"); 175 | ``` 176 | 177 | ### HealthSystem 178 | ```csharp 179 | // Take damage 180 | healthSystem.TakeDamage(20f); 181 | 182 | // Heal 183 | healthSystem.Heal(10f); 184 | 185 | // Check health 186 | float healthPercent = healthSystem.GetHealthPercentage(); 187 | ``` 188 | 189 | ### TooltipManager 190 | ```csharp 191 | // Show tooltip 192 | TooltipManager.Instance.ShowTooltip("Press E to interact", Input.mousePosition); 193 | 194 | // Hide tooltip 195 | TooltipManager.Instance.HideTooltip(); 196 | ``` 197 | 198 | ### DialogueSystem 199 | ```csharp 200 | // Create dialogue 201 | Dialogue dialogue = new Dialogue(); 202 | dialogue.speakerName = "NPC"; 203 | dialogue.speakerImage = npcSprite; 204 | dialogue.sentences = new string[] { 205 | "Hello there!", 206 | "How can I help you today?", 207 | "Feel free to ask me anything." 208 | }; 209 | 210 | // Start dialogue 211 | DialogueSystem.Instance.StartDialogue(dialogue); 212 | 213 | // Display next sentence (usually connected to button) 214 | DialogueSystem.Instance.DisplayNextSentence(); 215 | ``` 216 | 217 | ### InventorySystem 218 | ```csharp 219 | // Create item 220 | InventoryItem potion = new InventoryItem( 221 | "potion001", 222 | "Health Potion", 223 | "Restores 50 health points", 224 | potionSprite, 225 | 5 226 | ); 227 | potion.isConsumable = true; 228 | 229 | // Add to inventory 230 | InventorySystem.Instance.AddItem(potion); 231 | 232 | // Use item 233 | InventorySystem.Instance.UseItem("potion001"); 234 | 235 | // Check if player has item 236 | if (InventorySystem.Instance.HasItem("potion001", 2)) { 237 | // Player has at least 2 potions 238 | } 239 | ``` 240 | 241 | ### ObjectPooler 242 | ```csharp 243 | // Spawn object from pool 244 | GameObject bullet = ObjectPooler.Instance.SpawnFromPool("Bullet", firePoint.position, firePoint.rotation); 245 | 246 | // Return object to pool when done 247 | ObjectPooler.Instance.ReturnToPool(bullet); 248 | ``` 249 | 250 | ### SaveSystem 251 | ```csharp 252 | // Save game 253 | SaveSystem.Instance.SaveGame(); 254 | 255 | // Load game 256 | SaveSystem.Instance.LoadGame(); 257 | 258 | // Save specific data 259 | SaveSystem.Instance.SaveData("PlayerPosition", transform.position); 260 | 261 | // Load specific data 262 | Vector3 position = SaveSystem.Instance.LoadData("PlayerPosition", Vector3.zero); 263 | ``` 264 | 265 | ### QuestSystem 266 | ```csharp 267 | // Start quest 268 | QuestSystem.Instance.StartQuest("quest001"); 269 | 270 | // Complete objective 271 | QuestSystem.Instance.CompleteObjective("quest001", "objective001", 1); 272 | 273 | // Get quest status 274 | QuestStatus status = QuestSystem.Instance.GetQuestStatus("quest001"); 275 | if (status == QuestStatus.Completed) { 276 | // Quest is completed 277 | } 278 | ``` 279 | 280 | ### AudioManager 281 | ```csharp 282 | // Play background music with fade 283 | AudioManager.Instance.PlayMusic("MainTheme", 2.0f); 284 | 285 | // Play sound effect 286 | AudioManager.Instance.PlaySFX("Jump"); 287 | 288 | // Play 3D sound at position 289 | AudioManager.Instance.PlaySFXAtPosition("Explosion", explosionPosition); 290 | 291 | // Play ambient sound 292 | AudioManager.Instance.PlayAmbience("ForestAmbience"); 293 | 294 | // Adjust volume 295 | AudioManager.Instance.SetMusicVolume(0.5f); 296 | ``` 297 | 298 | ## Requirements 299 | 300 | - Unity 2019.4 or later 301 | - TextMeshPro package (for UI components) 302 | - .NET 4.x or later 303 | 304 | ## License 305 | 306 | This project is licensed under the MIT License - see the LICENSE file for details. 307 | -------------------------------------------------------------------------------- /RaycastDetection.cs: -------------------------------------------------------------------------------- 1 | //Inbora studio (clam all copyrights)2020-22 All scripts are code by Inbora Studio. 2 | //Devloped By Alok Khokhar for more information follow as on instagram @inbora.studio or ower webside. 3 | //https://inborastudio.wixsite.com/inborastudio 4 | 5 | using UnityEngine; 6 | using UnityEngine.UI; 7 | 8 | public class RaycastDetection : MonoBehaviour 9 | { 10 | Ray ray; 11 | RaycastHit raycastHit; 12 | Text textUI; 13 | 14 | void Awake() 15 | { 16 | textUI = GameObject.FindObjectOfType(); 17 | } 18 | 19 | void Update() 20 | { 21 | ray = new Ray(transform.position, transform.forward); 22 | if(Physics.Raycast(ray, out raycastHit)) 23 | { 24 | textUI.text = raycastHit.collider.gameObject.name; 25 | } 26 | else 27 | { 28 | textUI.text = ""; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /SaveSystem.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.IO; 3 | using System.Runtime.Serialization.Formatters.Binary; 4 | using System.Collections.Generic; 5 | using System; 6 | 7 | public class SaveSystem : MonoBehaviour 8 | { 9 | public static SaveSystem Instance { get; private set; } 10 | 11 | [Header("Save Settings")] 12 | [SerializeField] private string saveFileName = "GameSave"; 13 | [SerializeField] private bool useEncryption = false; 14 | [SerializeField] private string encryptionKey = "YourEncryptionKey"; 15 | [SerializeField] private bool useCompression = true; 16 | [SerializeField] private bool autoSave = false; 17 | [SerializeField] private float autoSaveInterval = 300f; // 5 minutes 18 | 19 | private string SavePath => Path.Combine(Application.persistentDataPath, saveFileName + ".sav"); 20 | private float autoSaveTimer = 0f; 21 | private Dictionary saveData = new Dictionary(); 22 | 23 | private void Awake() 24 | { 25 | if (Instance == null) 26 | { 27 | Instance = this; 28 | DontDestroyOnLoad(gameObject); 29 | } 30 | else 31 | { 32 | Destroy(gameObject); 33 | return; 34 | } 35 | 36 | LoadGame(); 37 | } 38 | 39 | private void Update() 40 | { 41 | if (autoSave) 42 | { 43 | autoSaveTimer += Time.deltaTime; 44 | if (autoSaveTimer >= autoSaveInterval) 45 | { 46 | SaveGame(); 47 | autoSaveTimer = 0f; 48 | } 49 | } 50 | } 51 | 52 | public void SaveGame() 53 | { 54 | // Collect data from registered save objects 55 | CollectSaveData(); 56 | 57 | // Create the save data container 58 | SaveData data = new SaveData 59 | { 60 | savedData = saveData, 61 | saveDate = DateTime.Now.ToString() 62 | }; 63 | 64 | try 65 | { 66 | // Create directory if it doesn't exist 67 | Directory.CreateDirectory(Path.GetDirectoryName(SavePath)); 68 | 69 | // Serialize the data 70 | BinaryFormatter formatter = new BinaryFormatter(); 71 | using (FileStream stream = new FileStream(SavePath, FileMode.Create)) 72 | { 73 | byte[] dataToSave = SerializeData(data); 74 | 75 | if (useEncryption) 76 | { 77 | dataToSave = EncryptDecrypt(dataToSave); 78 | } 79 | 80 | stream.Write(dataToSave, 0, dataToSave.Length); 81 | } 82 | 83 | Debug.Log("Game saved successfully to " + SavePath); 84 | } 85 | catch (Exception e) 86 | { 87 | Debug.LogError("Error saving game: " + e.Message); 88 | } 89 | } 90 | 91 | public bool LoadGame() 92 | { 93 | if (!File.Exists(SavePath)) 94 | { 95 | Debug.Log("No save file found at " + SavePath); 96 | return false; 97 | } 98 | 99 | try 100 | { 101 | byte[] dataToLoad; 102 | 103 | using (FileStream stream = new FileStream(SavePath, FileMode.Open)) 104 | { 105 | dataToLoad = new byte[stream.Length]; 106 | stream.Read(dataToLoad, 0, dataToLoad.Length); 107 | } 108 | 109 | if (useEncryption) 110 | { 111 | dataToLoad = EncryptDecrypt(dataToLoad); 112 | } 113 | 114 | SaveData loadedData = DeserializeData(dataToLoad); 115 | 116 | if (loadedData != null) 117 | { 118 | saveData = loadedData.savedData; 119 | Debug.Log("Game loaded successfully from " + SavePath); 120 | return true; 121 | } 122 | } 123 | catch (Exception e) 124 | { 125 | Debug.LogError("Error loading game: " + e.Message); 126 | } 127 | 128 | return false; 129 | } 130 | 131 | public void DeleteSave() 132 | { 133 | if (File.Exists(SavePath)) 134 | { 135 | File.Delete(SavePath); 136 | saveData.Clear(); 137 | Debug.Log("Save file deleted from " + SavePath); 138 | } 139 | } 140 | 141 | public bool HasSaveFile() 142 | { 143 | return File.Exists(SavePath); 144 | } 145 | 146 | // Save specific data 147 | public void SaveData(string key, T data) 148 | { 149 | if (saveData.ContainsKey(key)) 150 | { 151 | saveData[key] = data; 152 | } 153 | else 154 | { 155 | saveData.Add(key, data); 156 | } 157 | } 158 | 159 | // Load specific data 160 | public T LoadData(string key, T defaultValue = default) 161 | { 162 | if (saveData.ContainsKey(key) && saveData[key] is T) 163 | { 164 | return (T)saveData[key]; 165 | } 166 | 167 | return defaultValue; 168 | } 169 | 170 | private void CollectSaveData() 171 | { 172 | // Find all objects that implement ISaveable 173 | ISaveable[] saveables = FindObjectsOfType(true).OfType().ToArray(); 174 | 175 | foreach (ISaveable saveable in saveables) 176 | { 177 | string id = saveable.GetUniqueID(); 178 | object data = saveable.SaveData(); 179 | 180 | if (saveData.ContainsKey(id)) 181 | { 182 | saveData[id] = data; 183 | } 184 | else 185 | { 186 | saveData.Add(id, data); 187 | } 188 | } 189 | } 190 | 191 | private void ApplySaveData() 192 | { 193 | // Find all objects that implement ISaveable 194 | ISaveable[] saveables = FindObjectsOfType(true).OfType().ToArray(); 195 | 196 | foreach (ISaveable saveable in saveables) 197 | { 198 | string id = saveable.GetUniqueID(); 199 | 200 | if (saveData.ContainsKey(id)) 201 | { 202 | saveable.LoadData(saveData[id]); 203 | } 204 | } 205 | } 206 | 207 | private byte[] SerializeData(SaveData data) 208 | { 209 | BinaryFormatter formatter = new BinaryFormatter(); 210 | using (MemoryStream stream = new MemoryStream()) 211 | { 212 | formatter.Serialize(stream, data); 213 | return stream.ToArray(); 214 | } 215 | } 216 | 217 | private SaveData DeserializeData(byte[] data) 218 | { 219 | BinaryFormatter formatter = new BinaryFormatter(); 220 | using (MemoryStream stream = new MemoryStream(data)) 221 | { 222 | return (SaveData)formatter.Deserialize(stream); 223 | } 224 | } 225 | 226 | private byte[] EncryptDecrypt(byte[] data) 227 | { 228 | // Simple XOR encryption 229 | byte[] keyBytes = System.Text.Encoding.UTF8.GetBytes(encryptionKey); 230 | byte[] result = new byte[data.Length]; 231 | 232 | for (int i = 0; i < data.Length; i++) 233 | { 234 | result[i] = (byte)(data[i] ^ keyBytes[i % keyBytes.Length]); 235 | } 236 | 237 | return result; 238 | } 239 | } 240 | 241 | [System.Serializable] 242 | public class SaveData 243 | { 244 | public Dictionary savedData; 245 | public string saveDate; 246 | } 247 | 248 | // Interface for objects that can be saved 249 | public interface ISaveable 250 | { 251 | string GetUniqueID(); 252 | object SaveData(); 253 | void LoadData(object data); 254 | } -------------------------------------------------------------------------------- /Sound_on_Trigger: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | 4 | public class Sound_on_Trigger : MonoBehaviour { 5 | 6 | public AudioClip SoundToPlay; 7 | public float Volume; 8 | AudioSource audio; 9 | public bool alreadyPlayed = false; 10 | void Start() 11 | { 12 | audio = GetComponent(); 13 | } 14 | 15 | void OnTriggerEnter() 16 | { 17 | if (!alreadyPlayed) 18 | { 19 | audio.PlayOneShot(SoundToPlay, Volume); 20 | alreadyPlayed = true; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /TooltipManager.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEngine.UI; 3 | using TMPro; 4 | using System.Collections; 5 | 6 | public class TooltipManager : MonoBehaviour 7 | { 8 | public static TooltipManager Instance { get; private set; } 9 | 10 | [Header("UI References")] 11 | public GameObject tooltipPanel; 12 | public TextMeshProUGUI tooltipText; 13 | public RectTransform tooltipRect; 14 | 15 | [Header("Settings")] 16 | public float showDelay = 0.5f; 17 | public float fadeSpeed = 0.2f; 18 | public Vector2 offset = new Vector2(10f, 10f); 19 | 20 | private CanvasGroup canvasGroup; 21 | private Coroutine showCoroutine; 22 | 23 | private void Awake() 24 | { 25 | if (Instance == null) 26 | { 27 | Instance = this; 28 | DontDestroyOnLoad(gameObject); 29 | } 30 | else 31 | { 32 | Destroy(gameObject); 33 | } 34 | 35 | canvasGroup = tooltipPanel.GetComponent(); 36 | if (canvasGroup == null) 37 | canvasGroup = tooltipPanel.AddComponent(); 38 | 39 | HideTooltip(); 40 | } 41 | 42 | public void ShowTooltip(string text, Vector2 position) 43 | { 44 | if (showCoroutine != null) 45 | StopCoroutine(showCoroutine); 46 | 47 | showCoroutine = StartCoroutine(ShowTooltipCoroutine(text, position)); 48 | } 49 | 50 | private IEnumerator ShowTooltipCoroutine(string text, Vector2 position) 51 | { 52 | yield return new WaitForSeconds(showDelay); 53 | 54 | tooltipText.text = text; 55 | tooltipPanel.SetActive(true); 56 | 57 | // Position the tooltip 58 | Vector2 screenPoint = position + offset; 59 | tooltipRect.position = screenPoint; 60 | 61 | // Fade in 62 | float alpha = 0; 63 | while (alpha < 1) 64 | { 65 | alpha += Time.deltaTime / fadeSpeed; 66 | canvasGroup.alpha = alpha; 67 | yield return null; 68 | } 69 | } 70 | 71 | public void HideTooltip() 72 | { 73 | if (showCoroutine != null) 74 | { 75 | StopCoroutine(showCoroutine); 76 | showCoroutine = null; 77 | } 78 | 79 | StartCoroutine(HideTooltipCoroutine()); 80 | } 81 | 82 | private IEnumerator HideTooltipCoroutine() 83 | { 84 | float alpha = canvasGroup.alpha; 85 | while (alpha > 0) 86 | { 87 | alpha -= Time.deltaTime / fadeSpeed; 88 | canvasGroup.alpha = alpha; 89 | yield return null; 90 | } 91 | 92 | tooltipPanel.SetActive(false); 93 | } 94 | 95 | public void UpdatePosition(Vector2 position) 96 | { 97 | if (tooltipPanel.activeSelf) 98 | { 99 | tooltipRect.position = position + offset; 100 | } 101 | } 102 | } -------------------------------------------------------------------------------- /UIresize.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | public class UIresize : MonoBehaviour { 6 | 7 | RectTransform rectTransform; 8 | Rect safeArea; 9 | Vector2 minAnchor; 10 | Vector2 maxAnchor; 11 | 12 | private void Awake () { 13 | rectTransform = GetComponent (); 14 | safeArea = Screen.safeArea; 15 | minAnchor = safeArea.position; 16 | maxAnchor = minAnchor + safeArea.size; 17 | 18 | minAnchor.x /= Screen.width; 19 | minAnchor.y /= Screen.height; 20 | maxAnchor.x /= Screen.width; 21 | maxAnchor.y /= Screen.height; 22 | 23 | rectTransform.anchorMin = minAnchor; 24 | rectTransform.anchorMax = maxAnchor; 25 | 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /objectRotate.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using UnityEngine; 5 | 6 | public class objectRotate : MonoBehaviour 7 | { 8 | [Range(0, 360)] [SerializeField] private float rotateSpeed = 360; 9 | private Vector3 _rotate; 10 | 11 | void Start() 12 | { 13 | _rotate = Vector3.forward * rotateSpeed; 14 | } 15 | 16 | private void Update() 17 | { 18 | transform.Rotate(_rotate * Time.smoothDeltaTime); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /openurl.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | public class openurl : MonoBehaviour 6 | { 7 | public string Url; 8 | 9 | 10 | public void Open() 11 | { 12 | Application.OpenURL(Url); 13 | } 14 | 15 | } 16 | 17 | 18 | -------------------------------------------------------------------------------- /popup.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | public class popup : MonoBehaviour 6 | { 7 | public GameObject GameObject; 8 | bool active = true; 9 | 10 | public void OpenPlanl() 11 | 12 | { 13 | if (active == false) 14 | { 15 | gameObject.transform.gameObject.SetActive(false); 16 | active = false; 17 | } 18 | else 19 | { 20 | gameObject.transform.gameObject.SetActive(true); 21 | active = true ; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /sound_volume_slider.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEngine.UI; 5 | 6 | public class sound_volume_slider : MonoBehaviour 7 | { 8 | [SerializeField] Slider volumeSlider; 9 | void Start() 10 | { 11 | if(!PlayerPrefs.HasKey("musicVolume")) 12 | { 13 | PlayerPrefs.SetFloat("musicVolume", 1); 14 | Load(); 15 | } 16 | 17 | 18 | else 19 | { 20 | Load(); 21 | } 22 | } 23 | 24 | public void ChangeVolume() 25 | { 26 | AudioListener.volume = volumeSlider.value; 27 | save(); 28 | } 29 | 30 | private void Load() 31 | { 32 | volumeSlider.value = PlayerPrefs.GetFloat("musicVolume"); 33 | } 34 | 35 | private void save() 36 | { 37 | PlayerPrefs.SetFloat("musicVolume", volumeSlider.value); 38 | } 39 | } 40 | --------------------------------------------------------------------------------