157 lines
4.9 KiB
C#
157 lines
4.9 KiB
C#
using UnityEngine;
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
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<Player>();
|
|
if (player != null)
|
|
{
|
|
_playerTransform = player.transform;
|
|
_inventory = player.GetComponent<Inventory>();
|
|
}
|
|
|
|
_audioSource = gameObject.AddComponent<AudioSource>();
|
|
_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);
|
|
}
|
|
}
|
|
}
|