Bullet Spread
For bullet firing I used Raycasts. Before I call the 'Physics.Raycast' function I calculate the 'startPosition' and 'direction' for the raycast. The 'startPosition' is the cameras position and the 'direction' is the front face of the camera added with the offset angle. The angle depends on the current 'burst count' - the amount of bullets fired in that 'burst'. It takes the value from a 'm_SpreadAngles' list which contains a realistic recoil pattern.
Vector2 spread = m_SpreadAngles[Mathf.Min(m_BurstCount, (m_SpreadAngles.Length - 1))];
Transform camera = Camera.main.transform;
Vector3 startPosition = camera.position;
Vector3 direction = camera.forward;
Vector3 offset = new Vector3(Mathf.Tan(spread.x), Mathf.Tan(spread.y), 0);
direction += camera.InverseTransformDirection(offset);
direction.Normalize();
RaycastHit hit;
if (Physics.Raycast(startPosition, direction, out hit, m_Range))
{
//Hit
}