diff --git a/.vsconfig b/.vsconfig new file mode 100644 index 00000000..f019fd0a --- /dev/null +++ b/.vsconfig @@ -0,0 +1,6 @@ +{ + "version": "1.0", + "components": [ + "Microsoft.VisualStudio.Workload.ManagedGame" + ] +} diff --git a/Assets/Game/Test.meta b/Assets/Game/Test.meta new file mode 100644 index 00000000..d1fec65f --- /dev/null +++ b/Assets/Game/Test.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9aed44429792668429343756e69073b5 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Game/Test/Materials.meta b/Assets/Game/Test/Materials.meta new file mode 100644 index 00000000..059d6171 --- /dev/null +++ b/Assets/Game/Test/Materials.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 570a115f5fb663e479ec22a4ffbe73bd +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Game/Test/Scripts.meta b/Assets/Game/Test/Scripts.meta new file mode 100644 index 00000000..68170518 --- /dev/null +++ b/Assets/Game/Test/Scripts.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4863615a0de796040b44022d21ba5147 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Game/Test/Scripts/AntManScaleController.cs b/Assets/Game/Test/Scripts/AntManScaleController.cs new file mode 100644 index 00000000..8df03b3e --- /dev/null +++ b/Assets/Game/Test/Scripts/AntManScaleController.cs @@ -0,0 +1,194 @@ +using System; +using System.Collections; +using UnityEngine; + +public class AntManScaleController : MonoBehaviour +{ + private enum ScaleMode + { + Absolute, + RelativeToInitial + } + + [Header("Input")] + [SerializeField] private bool readToggleInput = true; + [SerializeField] private KeyCode toggleKey = KeyCode.Space; + + [Header("Objetivo de Escala")] + [SerializeField] private Transform scaleTarget; + [SerializeField] private bool keepPivotWorldPosition = true; + [SerializeField] private Transform pivotReference; + + [Header("Escalas")] + [SerializeField] private ScaleMode scaleMode = ScaleMode.RelativeToInitial; + [SerializeField] private Vector3 smallScale = Vector3.one; + [SerializeField] private Vector3 largeScale = new Vector3(20f, 20f, 20f); + [SerializeField] [Min(0.001f)] private float smallScaleMultiplier = 0.2f; + [SerializeField] [Min(0.001f)] private float largeScaleMultiplier = 1f; + [SerializeField] private bool startLarge; + + [Header("Transicion")] + [SerializeField] [Min(0.01f)] private float transitionDuration = 0.45f; + [SerializeField] private AnimationCurve transitionCurve = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f); + + [Header("Debug")] + [SerializeField] private bool showStateLogs; + + public event Action TransitionStarted; + public event Action TransitionCompleted; + + public bool IsTransitioning => _transitionRoutine != null; + public bool IsLarge => _isLarge; + public Transform ScaleTarget => scaleTarget; + + private bool _isLarge; + private bool _hasQueuedToggle; + private Coroutine _transitionRoutine; + private Vector3 _initialScale; + + private void Awake() + { + if (scaleTarget == null) + { + scaleTarget = transform; + } + + if (pivotReference == null) + { + pivotReference = scaleTarget; + } + + _initialScale = scaleTarget.localScale; + + _isLarge = startLarge; + ApplyScale(_isLarge ? GetLargeScale() : GetSmallScale()); + } + + private void Update() + { + if (!readToggleInput) + { + return; + } + + if (Input.GetKeyDown(toggleKey)) + { + RequestToggle(); + } + } + + public void SetReadToggleInputState(bool state) + { + readToggleInput = state; + } + + public Vector3 GetCurrentScale() + { + if (scaleTarget == null) + { + return transform.localScale; + } + + return scaleTarget.localScale; + } + + public void RequestToggle() + { + if (IsTransitioning) + { + _hasQueuedToggle = !_hasQueuedToggle; + if (showStateLogs) + { + Debug.Log($"[AntManScaleController] Toggle en cola: {_hasQueuedToggle}", this); + } + return; + } + + StartScaleTransition(); + } + + private void StartScaleTransition() + { + Vector3 from = scaleTarget.localScale; + _isLarge = !_isLarge; + Vector3 to = _isLarge ? GetLargeScale() : GetSmallScale(); + + _transitionRoutine = StartCoroutine(TransitionRoutine(from, to)); + } + + private IEnumerator TransitionRoutine(Vector3 from, Vector3 to) + { + if (showStateLogs) + { + Debug.Log($"[AntManScaleController] Transicion {from} -> {to}", this); + } + + TransitionStarted?.Invoke(from, to); + + float elapsed = 0f; + while (elapsed < transitionDuration) + { + elapsed += Time.deltaTime; + float t = Mathf.Clamp01(elapsed / transitionDuration); + float eased = transitionCurve.Evaluate(t); + ApplyScale(Vector3.LerpUnclamped(from, to, eased)); + yield return null; + } + + ApplyScale(to); + TransitionCompleted?.Invoke(to); + + if (showStateLogs) + { + Debug.Log($"[AntManScaleController] Escala final: {to}", this); + } + + _transitionRoutine = null; + + if (_hasQueuedToggle) + { + _hasQueuedToggle = false; + StartScaleTransition(); + } + } + + private void ApplyScale(Vector3 newScale) + { + if (scaleTarget == null) + { + return; + } + + if (!keepPivotWorldPosition || pivotReference == null) + { + scaleTarget.localScale = newScale; + return; + } + + Vector3 pivotPositionBefore = pivotReference.position; + scaleTarget.localScale = newScale; + Vector3 pivotPositionAfter = pivotReference.position; + Vector3 delta = pivotPositionBefore - pivotPositionAfter; + scaleTarget.position += delta; + } + + private Vector3 GetSmallScale() + { + if (scaleMode == ScaleMode.RelativeToInitial) + { + return _initialScale * smallScaleMultiplier; + } + + return smallScale; + } + + private Vector3 GetLargeScale() + { + if (scaleMode == ScaleMode.RelativeToInitial) + { + return _initialScale * largeScaleMultiplier; + } + + return largeScale; + } +} diff --git a/Assets/Game/Test/Scripts/AntManScaleController.cs.meta b/Assets/Game/Test/Scripts/AntManScaleController.cs.meta new file mode 100644 index 00000000..30b23c47 --- /dev/null +++ b/Assets/Game/Test/Scripts/AntManScaleController.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: cd4a72fbc89e96841b4c2b9bdb1b1868 \ No newline at end of file diff --git a/Assets/Game/Test/Scripts/AntManTestSceneBootstrap.cs b/Assets/Game/Test/Scripts/AntManTestSceneBootstrap.cs new file mode 100644 index 00000000..25c78fbb --- /dev/null +++ b/Assets/Game/Test/Scripts/AntManTestSceneBootstrap.cs @@ -0,0 +1,70 @@ +using UnityEngine; + +public class AntManTestSceneBootstrap : MonoBehaviour +{ + [Header("Escena")] + [SerializeField] private string cubeName = "AntManCube"; + [SerializeField] private string lightName = "Directional Light"; + [SerializeField] private string cameraName = "Main Camera"; + + [ContextMenu("Build Test Scene")] + public void BuildTestScene() + { + GameObject cube = FindOrCreateCube(); + FindOrCreateLight(); + FindOrCreateCamera(cube.transform.position); + } + + private GameObject FindOrCreateCube() + { + GameObject cube = GameObject.Find(cubeName); + if (cube == null) + { + cube = GameObject.CreatePrimitive(PrimitiveType.Cube); + cube.name = cubeName; + cube.transform.position = Vector3.zero; + } + + if (cube.GetComponent() == null) + { + cube.AddComponent(); + } + + if (cube.GetComponent() == null) + { + cube.AddComponent(); + } + + return cube; + } + + private void FindOrCreateLight() + { + if (GameObject.Find(lightName) != null) + { + return; + } + + GameObject lightObject = new GameObject(lightName); + Light lightComponent = lightObject.AddComponent(); + lightComponent.type = LightType.Directional; + lightComponent.intensity = 1.1f; + + lightObject.transform.rotation = Quaternion.Euler(50f, -30f, 0f); + } + + private void FindOrCreateCamera(Vector3 targetPosition) + { + GameObject cameraObject = GameObject.Find(cameraName); + if (cameraObject == null) + { + cameraObject = new GameObject(cameraName); + cameraObject.tag = "MainCamera"; + cameraObject.AddComponent(); + cameraObject.AddComponent(); + } + + cameraObject.transform.position = targetPosition + new Vector3(0f, 7f, -18f); + cameraObject.transform.LookAt(targetPosition); + } +} diff --git a/Assets/Game/Test/Scripts/AntManTestSceneBootstrap.cs.meta b/Assets/Game/Test/Scripts/AntManTestSceneBootstrap.cs.meta new file mode 100644 index 00000000..6a105152 --- /dev/null +++ b/Assets/Game/Test/Scripts/AntManTestSceneBootstrap.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 4163624d80de5a348970d71a64d6ccac \ No newline at end of file diff --git a/Assets/Game/Test/Scripts/GKTInventoryScaleToggle.cs b/Assets/Game/Test/Scripts/GKTInventoryScaleToggle.cs new file mode 100644 index 00000000..af8bb03a --- /dev/null +++ b/Assets/Game/Test/Scripts/GKTInventoryScaleToggle.cs @@ -0,0 +1,177 @@ +using UnityEngine; + +public class GKTInventoryScaleToggle : MonoBehaviour +{ + [Header("Input")] + [SerializeField] private KeyCode toggleKey = KeyCode.L; + [SerializeField] private bool disableDirectInputOnScaleController = true; + [SerializeField] private bool allowCtrlLBypass = true; + + [Header("Objeto Requerido (X)")] + [SerializeField] private string requiredInventoryObjectName = ""; + [SerializeField] private bool requireObjectConfiguredInInventoryList = true; + + [Header("Referencias")] + [SerializeField] private AntManScaleController scaleController; + [SerializeField] private playerComponentsManager mainPlayerComponentsManager; + [SerializeField] private inventoryManager mainInventoryManager; + + [Header("Debug")] + [SerializeField] private bool showLogs = true; + + private void Awake() + { + ResolveReferences(); + + if (scaleController != null && disableDirectInputOnScaleController) + { + scaleController.SetReadToggleInputState(false); + } + } + + private void Update() + { + if (Input.GetKeyDown(toggleKey)) + { + bool bypassInventoryCheck = allowCtrlLBypass && IsControlPressed(); + TryToggleScale(bypassInventoryCheck); + } + } + + public void TryToggleScale(bool bypassInventoryCheck = false) + { + ResolveReferences(); + + if (scaleController == null) + { + if (showLogs) + { + Debug.LogWarning("[GKTInventoryScaleToggle] Falta AntManScaleController en este personaje.", this); + } + return; + } + + if (bypassInventoryCheck) + { + scaleController.RequestToggle(); + + if (showLogs) + { + Debug.Log("[GKTInventoryScaleToggle] Ctrl+L bypass activo. Se omite verificacion de objeto X.", this); + } + return; + } + + if (mainInventoryManager == null) + { + if (showLogs) + { + Debug.LogWarning("[GKTInventoryScaleToggle] No se encontro inventoryManager en el personaje.", this); + } + return; + } + + if (string.IsNullOrWhiteSpace(requiredInventoryObjectName)) + { + if (showLogs) + { + Debug.LogWarning("[GKTInventoryScaleToggle] El objeto X aun no esta asignado. Completa Required Inventory Object Name.", this); + } + return; + } + + if (requireObjectConfiguredInInventoryList && !mainInventoryManager.existInventoryInfoFromName(requiredInventoryObjectName)) + { + if (showLogs) + { + Debug.LogWarning( + "[GKTInventoryScaleToggle] El objeto X no existe en el Inventory List Manager: " + requiredInventoryObjectName, + this + ); + } + return; + } + + int amount = mainInventoryManager.getInventoryObjectAmountByName(requiredInventoryObjectName); + bool hasObject = amount > 0; + + if (!hasObject) + { + if (showLogs) + { + Debug.Log("[GKTInventoryScaleToggle] No puedes cambiar escala. Falta objeto X en inventario: " + requiredInventoryObjectName, this); + } + return; + } + + scaleController.RequestToggle(); + + if (showLogs) + { + Debug.Log("[GKTInventoryScaleToggle] Escala alternada. Objeto X verificado: " + requiredInventoryObjectName + " x" + amount, this); + } + } + + public void SetRequiredInventoryObjectName(string newObjectName) + { + requiredInventoryObjectName = newObjectName; + } + + private static bool IsControlPressed() + { + return Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl); + } + + private void ResolveReferences() + { + if (scaleController == null) + { + scaleController = GetComponent(); + + if (scaleController == null) + { + scaleController = GetComponentInParent(true); + } + + if (scaleController == null) + { + scaleController = GetComponentInChildren(true); + } + } + + if (mainPlayerComponentsManager == null) + { + mainPlayerComponentsManager = GetComponent(); + + if (mainPlayerComponentsManager == null) + { + mainPlayerComponentsManager = GetComponentInParent(true); + } + + if (mainPlayerComponentsManager == null) + { + mainPlayerComponentsManager = GetComponentInChildren(true); + } + } + + if (mainInventoryManager == null && mainPlayerComponentsManager != null) + { + mainInventoryManager = mainPlayerComponentsManager.getInventoryManager(); + } + + if (mainInventoryManager == null) + { + mainInventoryManager = GetComponent(); + + if (mainInventoryManager == null) + { + mainInventoryManager = GetComponentInParent(true); + } + + if (mainInventoryManager == null) + { + mainInventoryManager = GetComponentInChildren(true); + } + } + } +} diff --git a/Assets/Game/Test/Scripts/GKTInventoryScaleToggle.cs.meta b/Assets/Game/Test/Scripts/GKTInventoryScaleToggle.cs.meta new file mode 100644 index 00000000..04e35f03 --- /dev/null +++ b/Assets/Game/Test/Scripts/GKTInventoryScaleToggle.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 5104cfed39c5e904ea25c70040dd6de2 \ No newline at end of file diff --git a/Assets/Game/Test/Scripts/GhostTrailEmitter.cs b/Assets/Game/Test/Scripts/GhostTrailEmitter.cs new file mode 100644 index 00000000..066fce63 --- /dev/null +++ b/Assets/Game/Test/Scripts/GhostTrailEmitter.cs @@ -0,0 +1,238 @@ +using System.Collections.Generic; +using UnityEngine; + +public class GhostTrailEmitter : MonoBehaviour +{ + [Header("Referencias")] + [SerializeField] private AntManScaleController scaleController; + [SerializeField] private Material ghostMaterial; + [SerializeField] private Transform ghostSourceTransform; + [SerializeField] private MeshFilter sourceMeshFilter; + [SerializeField] private MeshRenderer sourceMeshRenderer; + [SerializeField] private SkinnedMeshRenderer sourceSkinnedMeshRenderer; + [SerializeField] private bool useSkinnedMeshBake = true; + [SerializeField] private bool useScaleControllerScaleOnSkinnedGhost = true; + + [Header("Spawn")] + [SerializeField] [Min(0.01f)] private float spawnInterval = 0.05f; + [SerializeField] [Min(1)] private int maxActiveGhosts = 32; + + [Header("Fade")] + [SerializeField] [Min(0.01f)] private float ghostLifetime = 0.35f; + [SerializeField] [Range(0f, 1f)] private float startAlpha = 0.45f; + [SerializeField] [Range(0f, 1f)] private float endAlpha = 0f; + + [Header("Debug")] + [SerializeField] private bool showGhostCountLogs; + + private readonly List _activeGhosts = new List(); + + private Material _fallbackMaterial; + private bool _isEmitting; + private float _spawnTimer; + + private void Awake() + { + if (scaleController == null) + { + scaleController = GetComponent(); + } + + ResolveRenderSources(); + + if (ghostMaterial == null) + { + _fallbackMaterial = GetFallbackMaterial(); + } + } + + private void OnEnable() + { + if (scaleController != null) + { + scaleController.TransitionStarted += HandleTransitionStarted; + scaleController.TransitionCompleted += HandleTransitionCompleted; + } + } + + private void OnDisable() + { + if (scaleController != null) + { + scaleController.TransitionStarted -= HandleTransitionStarted; + scaleController.TransitionCompleted -= HandleTransitionCompleted; + } + } + + private void LateUpdate() + { + if (!_isEmitting) + { + return; + } + + _spawnTimer += Time.deltaTime; + while (_spawnTimer >= spawnInterval) + { + _spawnTimer -= spawnInterval; + SpawnGhost(); + } + } + + private void HandleTransitionStarted(Vector3 from, Vector3 to) + { + _isEmitting = true; + _spawnTimer = 0f; + SpawnGhost(); + } + + private void HandleTransitionCompleted(Vector3 scale) + { + _isEmitting = false; + } + + private void SpawnGhost() + { + CleanupNullGhosts(); + EnforceGhostLimit(); + + if (!TryGetGhostRenderData(out Mesh meshToUse, out Material materialToUse, out Transform sourceTransform, out bool ownsMesh, out bool fromSkinnedMesh)) + { + return; + } + + GameObject ghostObject = new GameObject("GhostTrail"); + ghostObject.transform.SetPositionAndRotation(sourceTransform.position, sourceTransform.rotation); + ghostObject.transform.localScale = GetGhostScale(sourceTransform, fromSkinnedMesh); + + GhostTrailGhost ghost = ghostObject.AddComponent(); + ghost.Initialize( + meshToUse, + materialToUse, + ghostLifetime, + startAlpha, + endAlpha, + this, + ownsMesh + ); + + _activeGhosts.Add(ghost); + + if (showGhostCountLogs) + { + Debug.Log($"[GhostTrailEmitter] Ghosts activos: {_activeGhosts.Count}", this); + } + } + + public void NotifyGhostDestroyed(GhostTrailGhost ghost) + { + _activeGhosts.Remove(ghost); + } + + private void CleanupNullGhosts() + { + for (int i = _activeGhosts.Count - 1; i >= 0; i--) + { + if (_activeGhosts[i] == null) + { + _activeGhosts.RemoveAt(i); + } + } + } + + private void EnforceGhostLimit() + { + while (_activeGhosts.Count >= maxActiveGhosts) + { + GhostTrailGhost oldestGhost = _activeGhosts[0]; + _activeGhosts.RemoveAt(0); + + if (oldestGhost != null) + { + Destroy(oldestGhost.gameObject); + } + } + } + + private void ResolveRenderSources() + { + if (ghostSourceTransform == null) + { + ghostSourceTransform = transform; + } + + if (sourceSkinnedMeshRenderer == null) + { + sourceSkinnedMeshRenderer = ghostSourceTransform.GetComponentInChildren(true); + } + + if (sourceMeshFilter == null) + { + sourceMeshFilter = ghostSourceTransform.GetComponentInChildren(true); + } + + if (sourceMeshRenderer == null) + { + sourceMeshRenderer = ghostSourceTransform.GetComponentInChildren(true); + } + } + + private Material GetFallbackMaterial() + { + if (sourceSkinnedMeshRenderer != null) + { + return sourceSkinnedMeshRenderer.sharedMaterial; + } + + if (sourceMeshRenderer != null) + { + return sourceMeshRenderer.sharedMaterial; + } + + return null; + } + + private bool TryGetGhostRenderData(out Mesh mesh, out Material material, out Transform sourceTransform, out bool ownsMesh, out bool fromSkinnedMesh) + { + ResolveRenderSources(); + + sourceTransform = ghostSourceTransform != null ? ghostSourceTransform : transform; + material = ghostMaterial != null ? ghostMaterial : (_fallbackMaterial != null ? _fallbackMaterial : GetFallbackMaterial()); + + mesh = null; + ownsMesh = false; + fromSkinnedMesh = false; + + if (useSkinnedMeshBake && sourceSkinnedMeshRenderer != null) + { + Mesh bakedMesh = new Mesh(); + sourceSkinnedMeshRenderer.BakeMesh(bakedMesh); + + mesh = bakedMesh; + ownsMesh = true; + fromSkinnedMesh = true; + sourceTransform = sourceSkinnedMeshRenderer.transform; + } + else if (sourceMeshFilter != null) + { + mesh = sourceMeshFilter.sharedMesh; + + if (sourceMeshFilter.transform != null) + { + sourceTransform = sourceMeshFilter.transform; + } + } + + return mesh != null && material != null; + } + + private Vector3 GetGhostScale(Transform sourceTransform, bool fromSkinnedMesh) + { + if (fromSkinnedMesh && useScaleControllerScaleOnSkinnedGhost && scaleController != null) + { + return scaleController.GetCurrentScale(); + } + + return sourceTransform.lossyScale; + } +} diff --git a/Assets/Game/Test/Scripts/GhostTrailEmitter.cs.meta b/Assets/Game/Test/Scripts/GhostTrailEmitter.cs.meta new file mode 100644 index 00000000..237ac8e5 --- /dev/null +++ b/Assets/Game/Test/Scripts/GhostTrailEmitter.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: cee3ef18b23f7654f8d9cfc52fb4c7b6 \ No newline at end of file diff --git a/Assets/Game/Test/Scripts/GhostTrailGhost.cs b/Assets/Game/Test/Scripts/GhostTrailGhost.cs new file mode 100644 index 00000000..e1137622 --- /dev/null +++ b/Assets/Game/Test/Scripts/GhostTrailGhost.cs @@ -0,0 +1,129 @@ +using UnityEngine; +using UnityEngine.Rendering; + +[RequireComponent(typeof(MeshFilter))] +[RequireComponent(typeof(MeshRenderer))] +public class GhostTrailGhost : MonoBehaviour +{ + private static readonly int BaseColorId = Shader.PropertyToID("_BaseColor"); + private static readonly int ColorId = Shader.PropertyToID("_Color"); + + private MeshRenderer _meshRenderer; + private GhostTrailEmitter _owner; + private Material _runtimeMaterial; + private Mesh _runtimeMesh; + private bool _ownsRuntimeMesh; + + private float _lifeElapsed; + private float _lifetime; + private float _startAlpha; + private float _endAlpha; + private Color _baseColor; + private bool _usesBaseColor; + + public void Initialize( + Mesh mesh, + Material templateMaterial, + float lifetime, + float startAlpha, + float endAlpha, + GhostTrailEmitter owner, + bool ownsRuntimeMesh = false) + { + _owner = owner; + _lifetime = Mathf.Max(0.01f, lifetime); + _startAlpha = Mathf.Clamp01(startAlpha); + _endAlpha = Mathf.Clamp01(endAlpha); + _runtimeMesh = mesh; + _ownsRuntimeMesh = ownsRuntimeMesh; + + MeshFilter meshFilter = GetComponent(); + _meshRenderer = GetComponent(); + + meshFilter.sharedMesh = _runtimeMesh; + + _runtimeMaterial = new Material(templateMaterial); + ConfigureTransparentMaterial(_runtimeMaterial); + + _usesBaseColor = _runtimeMaterial.HasProperty(BaseColorId); + if (_usesBaseColor) + { + _baseColor = _runtimeMaterial.GetColor(BaseColorId); + } + else if (_runtimeMaterial.HasProperty(ColorId)) + { + _baseColor = _runtimeMaterial.GetColor(ColorId); + } + else + { + _baseColor = Color.white; + } + + _meshRenderer.sharedMaterial = _runtimeMaterial; + ApplyAlpha(_startAlpha); + } + + private void Update() + { + _lifeElapsed += Time.deltaTime; + float t = Mathf.Clamp01(_lifeElapsed / _lifetime); + float alpha = Mathf.Lerp(_startAlpha, _endAlpha, t); + + ApplyAlpha(alpha); + + if (_lifeElapsed >= _lifetime) + { + Destroy(gameObject); + } + } + + private void OnDestroy() + { + if (_owner != null) + { + _owner.NotifyGhostDestroyed(this); + } + + if (_runtimeMaterial != null) + { + Destroy(_runtimeMaterial); + } + + if (_ownsRuntimeMesh && _runtimeMesh != null) + { + Destroy(_runtimeMesh); + } + } + + private void ApplyAlpha(float alpha) + { + Color color = _baseColor; + color.a = alpha; + + if (_usesBaseColor) + { + _runtimeMaterial.SetColor(BaseColorId, color); + return; + } + + if (_runtimeMaterial.HasProperty(ColorId)) + { + _runtimeMaterial.SetColor(ColorId, color); + } + } + + private static void ConfigureTransparentMaterial(Material material) + { + if (material.HasProperty("_Surface")) material.SetFloat("_Surface", 1f); + if (material.HasProperty("_Blend")) material.SetFloat("_Blend", 0f); + if (material.HasProperty("_AlphaClip")) material.SetFloat("_AlphaClip", 0f); + if (material.HasProperty("_SrcBlend")) material.SetFloat("_SrcBlend", (float)BlendMode.SrcAlpha); + if (material.HasProperty("_DstBlend")) material.SetFloat("_DstBlend", (float)BlendMode.OneMinusSrcAlpha); + if (material.HasProperty("_ZWrite")) material.SetFloat("_ZWrite", 0f); + + material.DisableKeyword("_ALPHATEST_ON"); + material.EnableKeyword("_ALPHABLEND_ON"); + material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); + material.renderQueue = (int)RenderQueue.Transparent; + } +} diff --git a/Assets/Game/Test/Scripts/GhostTrailGhost.cs.meta b/Assets/Game/Test/Scripts/GhostTrailGhost.cs.meta new file mode 100644 index 00000000..32638ba8 --- /dev/null +++ b/Assets/Game/Test/Scripts/GhostTrailGhost.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: b153d4f8b1c912040b2b8846f2297bef \ No newline at end of file diff --git a/Assets/Game/Test/prefabs.meta b/Assets/Game/Test/prefabs.meta new file mode 100644 index 00000000..3305ffb0 --- /dev/null +++ b/Assets/Game/Test/prefabs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5d1e7c4c92a0e6f4093087ae4a1f242c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Game/Test/prefabs/TestBootstrap.prefab b/Assets/Game/Test/prefabs/TestBootstrap.prefab new file mode 100644 index 00000000..d8dfa3b1 --- /dev/null +++ b/Assets/Game/Test/prefabs/TestBootstrap.prefab @@ -0,0 +1,226 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &44952910285008919 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 9118360090871585950} + - component: {fileID: 8880584933951423306} + m_Layer: 0 + m_Name: TestBootstrap + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &9118360090871585950 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 44952910285008919} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 1, y: 0.7, z: 1} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 7651202162512056264} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &8880584933951423306 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 44952910285008919} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4163624d80de5a348970d71a64d6ccac, type: 3} + m_Name: + m_EditorClassIdentifier: Assembly-CSharp::AntManTestSceneBootstrap + cubeName: AntManCube + lightName: Directional Light + cameraName: Main Camera +--- !u!1 &1774077560825409157 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7651202162512056264} + - component: {fileID: 6312477819915511825} + - component: {fileID: 4762139279569766132} + - component: {fileID: 2722219843092133903} + - component: {fileID: 5387860907141725752} + - component: {fileID: 8257900114901134586} + m_Layer: 0 + m_Name: AntManCube + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &7651202162512056264 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1774077560825409157} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -0.5, y: -0.35, z: -0.5} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 9118360090871585950} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &6312477819915511825 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1774077560825409157} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &4762139279569766132 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1774077560825409157} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 + m_ForceMeshLod: -1 + m_MeshLodSelectionBias: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_GlobalIlluminationMeshLod: 0 + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_MaskInteraction: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!65 &2722219843092133903 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1774077560825409157} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!114 &5387860907141725752 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1774077560825409157} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: cd4a72fbc89e96841b4c2b9bdb1b1868, type: 3} + m_Name: + m_EditorClassIdentifier: Assembly-CSharp::AntManScaleController + toggleKey: 32 + smallScale: {x: 0.2, y: 0.2, z: 0.2} + largeScale: {x: 1, y: 1, z: 1} + startLarge: 0 + transitionDuration: 0.45 + transitionCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + showStateLogs: 0 +--- !u!114 &8257900114901134586 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1774077560825409157} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: cee3ef18b23f7654f8d9cfc52fb4c7b6, type: 3} + m_Name: + m_EditorClassIdentifier: Assembly-CSharp::GhostTrailEmitter + scaleController: {fileID: 5387860907141725752} + ghostMaterial: {fileID: 0} + spawnInterval: 0.05 + maxActiveGhosts: 32 + ghostLifetime: 0.35 + startAlpha: 0.45 + endAlpha: 0 + showGhostCountLogs: 0 diff --git a/Assets/Game/Test/prefabs/TestBootstrap.prefab.meta b/Assets/Game/Test/prefabs/TestBootstrap.prefab.meta new file mode 100644 index 00000000..da3a8bc5 --- /dev/null +++ b/Assets/Game/Test/prefabs/TestBootstrap.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: efec9115045e1914da81e3ece87a5361 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes/AntManScaleTest.unity b/Assets/Scenes/AntManScaleTest.unity new file mode 100644 index 00000000..bfb10945 --- /dev/null +++ b/Assets/Scenes/AntManScaleTest.unity @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:821b492ea0efb23b377ea8dc56fef9c800949ca4874aa55e58eabef5d82e0239 +size 12869 diff --git a/Assets/Scenes/AntManScaleTest.unity.meta b/Assets/Scenes/AntManScaleTest.unity.meta new file mode 100644 index 00000000..c946fcaa --- /dev/null +++ b/Assets/Scenes/AntManScaleTest.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 4ba5b445a9d39dc418c0570957d961d1 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes/SampleScene.unity b/Assets/Scenes/SampleScene.unity index 570358a5..085406f1 100644 --- a/Assets/Scenes/SampleScene.unity +++ b/Assets/Scenes/SampleScene.unity @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e2e2ba4c3e81e5a0614568e37712497dff43ad0c82ea50aa0ffd84a962796768 -size 43402298 +oid sha256:6c78b30f04395b661117cda55d07f644824651c319ce0262450d07db870f4ac4 +size 43409826