Part of these game systems:
Pickup / Collectible
Collectible item with bobbing animation, rotation, magnet pull, and event callbacks for coins, health, ammo, etc.
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
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;
}
}
}