Part of these game systems:
beginner Inventory

Pickup / Collectible

Collectible item with bobbing animation, rotation, magnet pull, and event callbacks for coins, health, ammo, etc.

Unity 2022.3+ · 2.0 KB · Collectible.cs

How to Use

1

Attach Collectible to any pickup object

2

Add a Trigger Collider (Box, Sphere, or Circle for 2D)

3

Tag your player as 'Player'

4

Set item ID ('coin', 'health', 'ammo') and value

5

Hook OnCollected event to your score/inventory system

6

Enable magnet for auto-attract towards player

7

Works with both 3D (OnTriggerEnter) and 2D (OnTriggerEnter2D)

Source Code

Collectible.cs
C#
using UnityEngine;
using UnityEngine.Events;

/// <summary>
/// Collectible item with bob/rotate animation and magnet attraction.
/// Use for coins, health pickups, ammo, keys, etc.
/// </summary>
public class Collectible : MonoBehaviour
{
    [Header("Animation")]
    [SerializeField] private float bobHeight = 0.2f;
    [SerializeField] private float bobSpeed = 2f;
    [SerializeField] private float rotateSpeed = 90f;

    [Header("Collection")]
    [SerializeField] private string playerTag = "Player";
    [SerializeField] private bool destroyOnCollect = true;

    [Header("Magnet")]
    [SerializeField] private bool enableMagnet = false;
    [SerializeField] private float magnetRange = 3f;
    [SerializeField] private float magnetSpeed = 8f;

    [Header("Value")]
    [SerializeField] private int value = 1;
    [SerializeField] private string itemId = "coin";

    [Header("Events")]
    public UnityEvent<Collectible> OnCollected;

    private Vector3 startPosition;
    private Transform magnetTarget;
    private bool isCollected;

    /// <summary>Item ID for identification.</summary>
    public string ItemId => itemId;

    /// <summary>Value of this collectible.</summary>
    public int Value => value;

    private void Start()
    {
        startPosition = transform.position;
    }

    private void Update()
    {
        if (isCollected) return;

        // Bob animation
        float newY = startPosition.y + Mathf.Sin(Time.time * bobSpeed) * bobHeight;
        transform.position = new Vector3(transform.position.x, newY, transform.position.z);

        // Rotate
        transform.Rotate(Vector3.up, rotateSpeed * Time.deltaTime);

        // Magnet attraction
        if (enableMagnet && magnetTarget != null)
        {
            float dist = Vector3.Distance(transform.position, magnetTarget.position);
            if (dist < magnetRange)
            {
                Vector3 dir = (magnetTarget.position - transform.position).normalized;
                float speed = magnetSpeed * (1f - dist / magnetRange);
                startPosition += dir * speed * Time.deltaTime;
            }
        }
    }

    private void OnTriggerEnter(Collider other)
    {
        if (isCollected) return;

        if (other.CompareTag(playerTag))
        {
            Collect(other.gameObject);
        }
    }

    private void OnTriggerEnter2D(Collider2D other)
    {
        if (isCollected) return;

        if (other.CompareTag(playerTag))
        {
            Collect(other.gameObject);
        }
    }

    /// <summary>
    /// Collect this item. Called automatically on trigger or manually.
    /// </summary>
    public void Collect(GameObject collector)
    {
        if (isCollected) return;
        isCollected = true;

        OnCollected?.Invoke(this);

        if (destroyOnCollect)
            Destroy(gameObject);
    }

    private void OnEnable()
    {
        // Find player for magnet
        if (enableMagnet)
        {
            GameObject player = GameObject.FindGameObjectWithTag(playerTag);
            if (player != null) magnetTarget = player.transform;
        }
    }
}