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,187 @@
/*
A simple little editor extension to copy and paste all components
Help from http://answers.unity3d.com/questions/541045/copy-all-components-from-one-character-to-another.html
license: WTFPL (http://www.wtfpl.net/)
author: aeroson
advise: ChessMax
editor: frekons
*/
#if UNITY_EDITOR
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
public class CopyMultipleComponents : EditorWindow
{
// Use ScriptableObject to store data between editor sessions
private class ComponentDataContainer : ScriptableObject
{
public List<string> componentData = new List<string>();
public List<string> componentTypeNames = new List<string>();
}
private static ComponentDataContainer dataContainer;
[MenuItem("Tools/Component Utilities/Copy All Components")]
static void Copy()
{
if (Selection.activeGameObject == null)
{
Debug.LogError("No GameObject selected for copying!");
return;
}
// Create or get the data container
if (dataContainer == null)
dataContainer = ScriptableObject.CreateInstance<ComponentDataContainer>();
dataContainer.componentData.Clear();
dataContainer.componentTypeNames.Clear();
Component[] components = Selection.activeGameObject.GetComponents<Component>();
foreach (Component component in components)
{
if (component == null)
continue;
// Skip Transform component as it often causes issues
if (component is Transform)
continue;
// Store component data as JSON
string json = EditorJsonUtility.ToJson(component);
dataContainer.componentData.Add(json);
dataContainer.componentTypeNames.Add(component.GetType().AssemblyQualifiedName);
}
if (dataContainer.componentData.Count > 0)
{
Debug.Log($"Copied {dataContainer.componentData.Count} components from {Selection.activeGameObject.name}");
}
else
{
Debug.LogWarning("No components found to copy!");
}
}
[MenuItem("Tools/Component Utilities/Paste All Components")]
static void Paste()
{
if (dataContainer == null || dataContainer.componentData.Count == 0)
{
Debug.LogError("Nothing is copied! Use 'Copy All Components' first.");
return;
}
foreach (GameObject targetGameObject in Selection.gameObjects)
{
if (!targetGameObject)
continue;
Undo.RegisterCompleteObjectUndo(targetGameObject, targetGameObject.name + ": Paste All Components");
int successCount = 0;
int failCount = 0;
for (int i = 0; i < dataContainer.componentTypeNames.Count; i++)
{
string typeString = dataContainer.componentTypeNames[i];
string jsonData = dataContainer.componentData[i];
System.Type componentType = System.Type.GetType(typeString);
if (componentType == null)
{
Debug.LogError($"Could not find type: {typeString}");
failCount++;
continue;
}
// Check if component already exists
Component targetComponent = targetGameObject.GetComponent(componentType);
if (targetComponent == null)
{
// Add component if it doesn't exist
targetComponent = Undo.AddComponent(targetGameObject, componentType);
}
if (targetComponent != null)
{
// Apply the JSON data to the component
EditorJsonUtility.FromJsonOverwrite(jsonData, targetComponent);
successCount++;
}
else
{
Debug.LogError($"Failed to add component: {componentType}");
failCount++;
}
}
Debug.Log($"Pasted to {targetGameObject.name}: {successCount} components successful, {failCount} failed");
}
}
[MenuItem("Tools/Component Utilities/Delete All Components")]
static void DeleteAllComponents()
{
if (Selection.gameObjects.Length == 0)
{
Debug.LogError("No GameObjects selected for component deletion!");
return;
}
foreach (GameObject targetGameObject in Selection.gameObjects)
{
if (!targetGameObject)
continue;
Undo.RegisterCompleteObjectUndo(targetGameObject, targetGameObject.name + ": Delete All Components");
Component[] components = targetGameObject.GetComponents<Component>();
int deletedCount = 0;
// Start from the end to avoid index issues when destroying components
for (int i = components.Length - 1; i >= 0; i--)
{
Component component = components[i];
// Skip null components
if (component == null)
continue;
// Skip Transform component as it's required
if (component is Transform)
continue;
// Destroy the component with Undo support
Undo.DestroyObjectImmediate(component);
deletedCount++;
}
Debug.Log($"Deleted {deletedCount} components from {targetGameObject.name}");
}
}
// Add menu items without keyboard shortcuts
[MenuItem("GameObject/Component Utilities/Copy All Components")]
static void CopyFromGameObjectMenu()
{
Copy();
}
[MenuItem("GameObject/Component Utilities/Paste All Components")]
static void PasteFromGameObjectMenu()
{
Paste();
}
[MenuItem("GameObject/Component Utilities/Delete All Components")]
static void DeleteAllComponentsFromGameObjectMenu()
{
DeleteAllComponents();
}
}
#endif

View File

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

View File

@@ -0,0 +1,175 @@
using UnityEngine;
using System.Collections.Generic;
using UnityEngine.InputSystem;
[CreateAssetMenu(fileName = "Device Display Configurator", menuName = "Scriptable Objects/Device Display Configurator", order = 1)]
public class DeviceDisplayConfigurator : ScriptableObject
{
[System.Serializable]
public struct DeviceSet
{
public string deviceRawPath;
public DeviceDisplaySettings deviceDisplaySettings;
}
[System.Serializable]
public struct DisconnectedSettings
{
public string disconnectedDisplayName;
public Color disconnectedDisplayColor;
}
public List<DeviceSet> listDeviceSets = new List<DeviceSet>();
public DisconnectedSettings disconnectedDeviceSettings;
private Color fallbackDisplayColor = Color.white;
public string GetDeviceName(PlayerInput playerInput)
{
string currentDeviceRawPath = playerInput.devices[0].ToString();
string newDisplayName = null;
for(int i = 0; i < listDeviceSets.Count; i++)
{
if(listDeviceSets[i].deviceRawPath == currentDeviceRawPath)
{
newDisplayName = listDeviceSets[i].deviceDisplaySettings.deviceDisplayName;
}
}
if(newDisplayName == null)
{
newDisplayName = currentDeviceRawPath;
}
return newDisplayName;
}
public Color GetDeviceColor(PlayerInput playerInput)
{
string currentDeviceRawPath = playerInput.devices[0].ToString();
Color newDisplayColor = fallbackDisplayColor;
for(int i = 0; i < listDeviceSets.Count; i++)
{
if(listDeviceSets[i].deviceRawPath == currentDeviceRawPath)
{
newDisplayColor = listDeviceSets[i].deviceDisplaySettings.deviceDisplayColor;
}
}
return newDisplayColor;
}
public Sprite GetDeviceBindingIcon(PlayerInput playerInput, string playerInputDeviceInputBinding)
{
string currentDeviceRawPath = playerInput.devices[0].ToString();
Sprite displaySpriteIcon = null;
for(int i = 0; i < listDeviceSets.Count; i++)
{
if(listDeviceSets[i].deviceRawPath == currentDeviceRawPath)
{
if(listDeviceSets[i].deviceDisplaySettings.deviceHasContextIcons != null)
{
displaySpriteIcon = FilterForDeviceInputBinding(listDeviceSets[i], playerInputDeviceInputBinding);
}
}
}
return displaySpriteIcon;
}
Sprite FilterForDeviceInputBinding(DeviceSet targetDeviceSet, string inputBinding)
{
Sprite spriteIcon = null;
switch(inputBinding)
{
case "Button North":
spriteIcon = targetDeviceSet.deviceDisplaySettings.buttonNorthIcon;
break;
case "Button South":
spriteIcon = targetDeviceSet.deviceDisplaySettings.buttonSouthIcon;
break;
case "Button West":
spriteIcon = targetDeviceSet.deviceDisplaySettings.buttonWestIcon;
break;
case "Button East":
spriteIcon = targetDeviceSet.deviceDisplaySettings.buttonEastIcon;
break;
case "Right Shoulder":
spriteIcon = targetDeviceSet.deviceDisplaySettings.triggerRightFrontIcon;
break;
case "Right Trigger":
spriteIcon = targetDeviceSet.deviceDisplaySettings.triggerRightBackIcon;
break;
case "rightTriggerButton":
spriteIcon = targetDeviceSet.deviceDisplaySettings.triggerRightBackIcon;
break;
case "Left Shoulder":
spriteIcon = targetDeviceSet.deviceDisplaySettings.triggerLeftFrontIcon;
break;
case "Left Trigger":
spriteIcon = targetDeviceSet.deviceDisplaySettings.triggerLeftBackIcon;
break;
case "leftTriggerButton":
spriteIcon = targetDeviceSet.deviceDisplaySettings.triggerLeftBackIcon;
break;
default:
for(int i = 0; i < targetDeviceSet.deviceDisplaySettings.customContextIcons.Count; i++)
{
if(targetDeviceSet.deviceDisplaySettings.customContextIcons[i].customInputContextString == inputBinding)
{
if(targetDeviceSet.deviceDisplaySettings.customContextIcons[i].customInputContextIcon != null)
{
spriteIcon = targetDeviceSet.deviceDisplaySettings.customContextIcons[i].customInputContextIcon;
}
}
}
break;
}
return spriteIcon;
}
public string GetDisconnectedName()
{
return disconnectedDeviceSettings.disconnectedDisplayName;
}
public Color GetDisconnectedColor()
{
return disconnectedDeviceSettings.disconnectedDisplayColor;
}
}

View File

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

View File

@@ -0,0 +1,34 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public struct CustomInputContextIcon
{
public string customInputContextString;
public Sprite customInputContextIcon;
}
[CreateAssetMenu(fileName = "Device Display Settings", menuName = "Scriptable Objects/Device Display Settings", order = 1)]
public class DeviceDisplaySettings : ScriptableObject
{
public string deviceDisplayName;
public Color deviceDisplayColor;
public bool deviceHasContextIcons;
public Sprite buttonNorthIcon;
public Sprite buttonSouthIcon;
public Sprite buttonWestIcon;
public Sprite buttonEastIcon;
public Sprite triggerRightFrontIcon;
public Sprite triggerRightBackIcon;
public Sprite triggerLeftFrontIcon;
public Sprite triggerLeftBackIcon;
public List<CustomInputContextIcon> customContextIcons = new List<CustomInputContextIcon>();
}

View File

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

View File

@@ -0,0 +1,18 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FileRenameEditor : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}

View File

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

View File

@@ -0,0 +1,43 @@
using UnityEngine;
using System.IO;
public class FileRenamer : MonoBehaviour
{
// Set the folder path where your .cas files are located
string folderPath = "C:/Users/mbiha/Downloads/Final Game-Play Animations/Cat - Game/CatFootwork - Finalised";
void Start()
{
RenameFiles();
}
void RenameFiles()
{
// Get all .cas files in the folder
string[] files = Directory.GetFiles(folderPath, "*.casc");
foreach (string filePath in files)
{
// Extract the filename without extension
string fileName = Path.GetFileNameWithoutExtension(filePath);
print(fileName);
// Split the filename by '-'
string[] parts = fileName.Split('-');
// Extract the animation name from the second part
string[] nameParts = parts[0].Split('.');
string animationName = nameParts[1];
// Construct the new file name
string newFileName = animationName + ".casc";
// Construct the new file path
string newFilePath = Path.Combine(folderPath, newFileName);
// Rename the file
File.Move(filePath, newFilePath);
Debug.Log("File renamed from " + filePath + " to " + newFilePath);
}
}
}

View File

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

View File

@@ -0,0 +1,62 @@
using System;
using UnityEngine;
#if ENABLE_INPUT_SYSTEM
using UnityEngine.InputSystem;
#endif
/// <summary>
/// Small helper to safely enable Input System artifacts without letting InputSystem exceptions crash initialization.
/// Use InputSafety.SafeEnable(action) instead of action.Enable() when running on devices that may have many bindings.
/// </summary>
public static class InputSafety
{
#if ENABLE_INPUT_SYSTEM
public static void SafeEnable(this InputAction action)
{
if (action == null) return;
try
{
if (!action.enabled) action.Enable();
}
catch (Exception ex)
{
Debug.LogError($"[InputSafety] Failed to enable InputAction '{action.name}': {ex}");
}
}
public static void SafeEnable(this InputActionReference actionRef)
{
if (actionRef == null || actionRef.action == null) return;
SafeEnable(actionRef.action);
}
public static void SafeEnable(this InputActionMap map)
{
if (map == null) return;
try
{
map.Enable();
}
catch (Exception ex)
{
Debug.LogError($"[InputSafety] Failed to enable InputActionMap '{map.name}': {ex}");
}
}
public static void SafeEnable(this InputActionAsset asset)
{
if (asset == null) return;
try
{
asset.Enable();
}
catch (Exception ex)
{
Debug.LogError($"[InputSafety] Failed to enable InputActionAsset '{asset.name}': {ex}");
}
}
#else
// If Input System isn't enabled, provide no-op overloads so call sites don't need conditional compilation.
public static void SafeEnable(this object _) { }
#endif
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 38432e564134fa9ed83649ee9056b4d2

View File

@@ -0,0 +1,74 @@
using System;
using System.IO;
using System.Security.Cryptography;
using UnityEngine;
public static class SecurePlayerPrefs
{
private static readonly byte[] salt = new byte[] { 0x13, 0x24, 0x37, 0x48, 0x59, 0x6A, 0x7B, 0x8C };
private static readonly byte[] key = new byte[] { 0x6D, 0x5B, 0x35, 0x81, 0x49, 0x93, 0xD8, 0x10, 0x52, 0x7E, 0x2B, 0x19, 0x4C, 0xFA, 0x67, 0x8A };
public static void SetString(string key, string value)
{
byte[] encrypted = EncryptStringToBytes(value);
string encoded = Convert.ToBase64String(encrypted);
PlayerPrefs.SetString(key, encoded);
}
public static string GetString(string key, string defaultValue = "")
{
string encoded = PlayerPrefs.GetString(key, defaultValue);
byte[] encrypted = Convert.FromBase64String(encoded);
string value = DecryptStringFromBytes(encrypted);
return value;
}
private static byte[] EncryptStringToBytes(string plainText)
{
byte[] encrypted;
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = key;
aesAlg.IV = salt;
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
return encrypted;
}
private static string DecryptStringFromBytes(byte[] cipherText)
{
string plaintext = null;
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = key;
aesAlg.IV = salt;
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
using (MemoryStream msDecrypt = new MemoryStream(cipherText))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
plaintext = srDecrypt.ReadToEnd();
}
}
}
}
return plaintext;
}
}

View File

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

View File

@@ -0,0 +1,91 @@
using UnityEngine;
/// <summary>
/// Be aware this will not prevent a non singleton constructor
/// such as `T myT = new T();`
/// To prevent that, add `protected T () {}` to your singleton class.
/// </summary>
public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
private static T _instance;
private static object _lock = new object();
public static T Instance
{
get
{
if (applicationIsQuitting)
{
Debug.LogWarning("[Singleton] Instance '" + typeof(T) +
"' already destroyed on application quit." +
" Won't create again - returning null.");
return null;
}
lock (_lock)
{
if (_instance == null)
{
_instance = (T)FindObjectOfType(typeof(T));
if (FindObjectsOfType(typeof(T)).Length > 1)
{
Debug.LogError("[Singleton] Something went really wrong " +
" - there should never be more than 1 singleton!" +
" Reopening the scene might fix it.");
return _instance;
}
if (_instance == null)
{
GameObject singleton = new GameObject();
_instance = singleton.AddComponent<T>();
singleton.name = "(singleton) " + typeof(T).ToString();
Debug.Log("[Singleton] An instance of " + typeof(T) +
" is needed in the scene, so '" + singleton +
"' was created.");
}
else
{
//Debug.Log("[Singleton] Using instance already created: " + _instance.gameObject.name);
}
}
return _instance;
}
}
}
private static bool IsDontDestroyOnLoad()
{
if (_instance == null)
{
return false;
}
// Object exists independent of Scene lifecycle, assume that means it has DontDestroyOnLoad set
if ((_instance.gameObject.hideFlags & HideFlags.DontSave) == HideFlags.DontSave)
{
return true;
}
return false;
}
private static bool applicationIsQuitting = false;
/// <summary>
/// When Unity quits, it destroys objects in a random order.
/// In principle, a Singleton is only destroyed when application quits.
/// If any script calls Instance after it have been destroyed,
/// it will create a buggy ghost object that will stay on the Editor scene
/// even after stopping playing the Application. Really bad!
/// So, this was made to be sure we're not creating that buggy ghost object.
/// </summary>
public void OnDestroy()
{
if (IsDontDestroyOnLoad())
{
applicationIsQuitting = true;
}
}
}

View File

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

View File

@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using UnityEngine;
public class UnityMainThreadDispatcher : MonoBehaviour
{
private static readonly Queue<Action> executionQueue = new Queue<Action>();
private static UnityMainThreadDispatcher instance = null;
public static UnityMainThreadDispatcher Instance()
{
if (instance == null)
{
var obj = new GameObject("UnityMainThreadDispatcher");
instance = obj.AddComponent<UnityMainThreadDispatcher>();
DontDestroyOnLoad(obj);
}
return instance;
}
public void Enqueue(Action action)
{
lock (executionQueue)
{
executionQueue.Enqueue(action);
}
}
private void Update()
{
lock (executionQueue)
{
while (executionQueue.Count > 0)
{
executionQueue.Dequeue().Invoke();
}
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 29014c96e46e31947a2fe929c84c3bbe