using UnityEngine; /// /// Attach to any pickup object. Spins + bobs like MGS rations. /// Assign an ItemDefinition asset for full weapon/equip support, /// or just fill itemName for a simple non-weapon pickup. /// public class PickupItem : MonoBehaviour { [Header("Item")] [Tooltip("Preferred: drag an ItemDefinition ScriptableObject here.")] public ItemDefinition definition; [Tooltip("Fallback name if no ItemDefinition is set.")] public string itemName = "Item"; public Sprite itemIcon; [Header("Spin & Bob")] public float spinSpeed = 120f; public float bobHeight = 0.18f; public float bobSpeed = 2.2f; [Header("Pickup")] public float pickupRadius = 2.0f; public KeyCode pickupKey = KeyCode.E; [Header("FX")] public GameObject pickupParticlesPrefab; public AudioClip pickupSound; // ───────────────────────────────────────── private Vector3 _startPos; private Transform _playerTransform; private Inventory _inventory; private AudioSource _audioSource; private bool _collected = false; // Prompt display private bool _inRange = false; void Start() { _startPos = transform.position; Player player = FindObjectOfType(); if (player != null) { _playerTransform = player.transform; _inventory = player.GetComponent(); } _audioSource = gameObject.AddComponent(); _audioSource.spatialBlend = 1f; _audioSource.playOnAwake = false; // If we have a definition, use its name/icon if (definition != null) { itemName = definition.itemName; itemIcon = definition.icon; } } void Update() { if (_collected) return; // ── Spin ────────────────────────────── transform.Rotate(Vector3.up, spinSpeed * Time.deltaTime, Space.World); // ── Bob ─────────────────────────────── float newY = _startPos.y + Mathf.Sin(Time.time * bobSpeed * Mathf.PI * 2f) * bobHeight; transform.position = new Vector3(transform.position.x, newY, transform.position.z); // ── Pickup check ───────────────────── if (_playerTransform == null) return; float dist = Vector3.Distance(transform.position, _playerTransform.position); _inRange = dist <= pickupRadius; if (_inRange && Input.GetKeyDown(pickupKey)) Collect(); } void OnGUI() { if (_collected || !_inRange) return; // World-to-screen prompt Vector3 screenPos = Camera.main != null ? Camera.main.WorldToScreenPoint(_startPos + Vector3.up * (bobHeight + 0.4f)) : Vector3.zero; if (screenPos.z < 0) return; // behind camera float sx = screenPos.x; float sy = Screen.height - screenPos.y; // flip y string label = definition != null ? definition.itemName : itemName; bool isWeapon = definition != null && definition.type == ItemDefinition.ItemType.Weapon; string prompt = $"[{pickupKey}] Pick up {label}"; GUIStyle bg = new GUIStyle(GUI.skin.box); bg.fontSize = 12; bg.fontStyle = FontStyle.Bold; bg.normal.textColor = isWeapon ? new Color(1f, 0.85f, 0.2f) : Color.white; Vector2 size = bg.CalcSize(new GUIContent(prompt)); Rect bgRect = new Rect(sx - size.x * 0.5f - 6f, sy - size.y - 4f, size.x + 12f, size.y + 6f); // Dark backing box Color prev = GUI.color; GUI.color = new Color(0, 0, 0, 0.65f); GUI.DrawTexture(bgRect, Texture2D.whiteTexture); GUI.color = prev; GUI.Label(bgRect, " " + prompt + " ", bg); } void OnDrawGizmosSelected() { Gizmos.color = Color.yellow; Gizmos.DrawWireSphere(transform.position, pickupRadius); } void Collect() { _collected = true; _inRange = false; if (_inventory != null) { if (definition != null) _inventory.AddItem(definition, autoEquip: true); else _inventory.AddItem(itemName, itemIcon); } else { Debug.LogWarning("PickupItem: No Inventory found on player!"); } if (pickupParticlesPrefab != null) Instantiate(pickupParticlesPrefab, transform.position, Quaternion.identity); if (pickupSound != null) { _audioSource.PlayOneShot(pickupSound); Destroy(gameObject, pickupSound.length); } else { Destroy(gameObject); } } }