Source file unity-csharp/arcade-classics/space-invaders/PlayerShip.cs from the GDnD code examples. Download raw file

// GDnD wiki example
// Demonstrates: horizontal input, a fire-rate cooldown timer, pooled shooting, and taking a hit
// Related pages: [[overview-arcade-classics-as-learning-projects]], [[unity-input]], [[object-pool-pattern]]
 
using UnityEngine;
 
// The player ship. Movement reuses the clamp pattern from earlier steps; the new
// idea is a cooldown timer that limits fire rate independently of frame rate.
public class PlayerShip : MonoBehaviour, IHittable
{
    [SerializeField] private float speed = 9f;
    [SerializeField] private string horizontalAxis = "Horizontal";
 
    [Header("Firing")]
    [SerializeField] private ProjectilePool bulletPool;
    [SerializeField] private float bulletSpeed = 12f;
    [SerializeField] private float fireCooldown = 0.4f;
    [Tooltip("Layer the player's bullets damage (the invaders).")]
    [SerializeField] private LayerMask invaderMask;
 
    private SpaceInvadersGame game;
    private float cooldownTimer;
    private float halfWidth;
    private float halfSize;
    private Camera cachedCamera;
 
    private void Awake()
    {
        cachedCamera = Camera.main;
        halfSize = GetComponent<SpriteRenderer>().bounds.extents.x;
    }
 
    public void Bind(SpaceInvadersGame owner)
    {
        game = owner;
    }
 
    private void Update()
    {
        Move();
        TickFire();
    }
 
    private void Move()
    {
        float input = Input.GetAxisRaw(horizontalAxis);
        Vector3 position = transform.position;
        position.x += input * speed * Time.deltaTime;
 
        halfWidth = cachedCamera.orthographicSize * cachedCamera.aspect - halfSize;
        position.x = Mathf.Clamp(position.x, -halfWidth, halfWidth);
        transform.position = position;
    }
 
    private void TickFire()
    {
        cooldownTimer -= Time.deltaTime;
        if (cooldownTimer > 0f || !Input.GetKey(KeyCode.Space) || bulletPool == null)
        {
            return;
        }
 
        cooldownTimer = fireCooldown;
        bulletPool.Get().Launch(transform.position + Vector3.up * 0.5f, +1f, bulletSpeed, invaderMask);
    }
 
    public void Hit()
    {
        game?.OnPlayerHit();
    }
}