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();
}
}