You are indeed correct - Serbo-Croatian is (linguistically) a single language. The problem is that applying ethnic labels to this language creates all sorts of problems because it is spoken by multiple ethnicities who all want to be included name! Let me offer a bit of an explanation:
Linguistically speaking, there are indeed three languages spoken in Croatia/Bosnia/Serbia/Montenegro: Kajkavian, Chakavian and Shtokavian (their names come from their respective words for "what"). Kajkavian and Chakavian are spoken in
North and
West Croatia respectively and are spoken only by Croats so there is no issue there, but Shtokavian is the language of the rest of the area and includes all ethnicities. (In Croatia, Kajkavian, Chakavian and Shtokavian are called "the three dialects of the Croatian language" whilst in reality they should be called "the three languages of the Croat people".) Shtokavian consists of
many dialects and its standard form is based on the yellow one which is, interestingly, not native to either Belgrade, Sarajevo, Podgorica or indeed Zagreb (which is actually in the Kajkavian area). This standardised form of Shtokavian is what we know as Serbo-Croatian.
During the first Yugoslavia (1918-1945), the country actually had a single official language: "Serbo-Croato-Slovenian" which only existed in the mind of whoever came up with this name (Macedonian was considered a dialect of Bulgarian at the time). In the second Yugoslavia (1945-1991) there were different "levels" of linguistic autonomy. The country as a whole had three official languages: Slovenian, Serbo-Croatian and Macedonian. These were used on passports, banknotes, and other official stuff.
Each of the constituent republics, in turn, had a single official language: Slovenia had Slovenian, Croatia, B&H, Serbia, Montenegro had Serbo-Croatian, and Macedonia had Macedonian. The lowest level were regional autonomies which included bilingual ares like Hungarian in Vojvodina and NE Slovenia, Italian along the northern coast, Albanian in Kosovo and Montenegro. These languages were fully co-official and very visible in their little pockets but any sign of them disappeared completely once you left the area (a situation which persists to this day)
This "Serbo-Croatian" language had two "variants" even in those times. They were called Eastern and Western and corresponded to today's Serbian and Croatian, including different scripts and the most famous e/(i)je distinction. After the breakup, nationalistic tendencies went berserk and linguistic purism was rampant in Croatia and Bosnia, trying to alienate their "standard" as far as possible from Serbian.
Well, it seems that my explanation has become an essay ... Sorry!