Yes, and it is wonderful.
I used the \$\LaTeX\$ class dndbook available here for several projects, available also on overleaf. I employed it for RPG books and adventure/campaign booklets.
I have a little bit of experience with LaTeX due to my work, and I find it intuitive and easy. This is not the same for people used to using Word or other similar horrors... I mean, typesetting software.
This is just an example of what you can do: this is a page of a chapter of a book. If you look at the documentation, there are pre-made commands for feats, spells, monster stat blocks and others. I think it is a very good class for \$\LaTeX\$.

A not-so-wonderful Character Sheet
For the character sheet, I saw this class, but I do not have any experience with it.
I manage to create a very rough and bad-looking char sheet, using the package eforms, trying to make it a little bit more appealing with tikz (for the skill proficiencies). The code is below the screenshot.

This document allows to
- set the ability scores
- set the proficiency bonus
- set the skill in which the character is proficient
It computes automatically the ability modifiers, and updates the skill modifiers, the AC and the max HPs. The appearance is terrible, but with some work with tikz I believe that one can obtain some interesting result.
\documentclass{article}
\usepackage{eforms}
\usepackage{tikz}
\newcommand{\mycircle}[1]{
\begin{tikzpicture}
\draw[fill=none] (0,0) circle (6.5pt);
\node at (0,0) {#1};
\end{tikzpicture}
}
\begin{document}
\section*{Plain Character Sheet}
\medskip
\begin{minipage}{0.5\textwidth}
\TextField[
name=PB,
readonly=false,
width=0.3\linewidth,
value={2},
bordercolor={0.5 0 0.5}
]{Proficiency Bonus}
\medskip
\begin{tabular}{cccc}
\TextField[
name=AC,
width=0.8cm,
height=0.8cm,
readonly=true,
value=AC,
bordercolor={1 1 1}]{}&
\TextField[
name=ACvalue,
width=0.8cm,
height=0.8cm,
readonly=true,
value=10,
bordercolor={0 0 1},
]{}&
\TextField[
name=HPs,
width=1.2cm,
height=0.8cm,
readonly=true,
value=maxHPs,
bordercolor={1 1 1}]{}&
\TextField[
name=HPsValue,
width=0.8cm,
height=0.8cm,
readonly=false,
value=8,
bordercolor={0 0 1},
]{}\\
\end{tabular}
\subsection*{Ability Scores}
\begin{tabular}{ccc}
\TextField[
name=str,
width=0.8cm,
height=0.8cm,
readonly=true,
value=STR,
bordercolor={1 1 1}
]{} & \TextField[
name=STR,
width=0.8cm,
height=0.8cm,
readonly=false,
value={10},
calculate={var A = this.getField("STR").value; var B = (parseInt(A)-10)/2 ; this.getField("STRBonus").value=Math.floor(B);},
]{} & \TextField[
name=STRBonus,
width=0.8cm,
height=0.8cm,
readonly=true,
value={0}
]{}\\
\TextField[
name=dex,
width=0.8cm,
height=0.8cm,
readonly=true,
value=DEX,
bordercolor={1 1 1}
]{}&
\TextField[
name=DEX,
width=0.8cm,
height=0.8cm,
readonly=false,
value={10},
calculate={var A = this.getField("DEX").value; var B = (parseInt(A)-10)/2 ; this.getField("DEXBonus").value=Math.floor(B); this.getField("ACvalue").value=10+Math.floor(B);},
]{}&
\TextField[
name=DEXBonus,
width=0.8cm,
height=0.8cm,
readonly=true,
value={0}
]{}\\
\TextField[
name=con,
width=0.8cm,
height=0.8cm,
readonly=true,
value=CON,
bordercolor={1 1 1}
]{}&
\TextField[
name=CON,
width=0.8cm,
height=0.8cm,
readonly=false,
value={10},
calculate={var A = this.getField("CON").value; var B = (parseInt(A)-10)/2 ; this.getField("CONBonus").value=Math.floor(B);this.getField("HPsValue").value=8+Math.floor(B);},
]{}&
\TextField[
name=CONBonus,
width=0.8cm,
height=0.8cm,
readonly=true,
value={0}
]{}\\
\TextField[
name=int,
width=0.8cm,
height=0.8cm,
readonly=true,
value=INT,
bordercolor={1 1 1}
]{}&
\TextField[
name=INT,
width=0.8cm,
height=0.8cm,
readonly=false,
value={10},
calculate={var A = this.getField("INT").value; var B = (parseInt(A)-10)/2 ; this.getField("INTBonus").value=Math.floor(B);},
]{}&
\TextField[
name=INTBonus,
width=0.8cm,
height=0.8cm,
readonly=true,
value={0}
]{}\\
\TextField[
name=wis,
width=0.8cm,
height=0.8cm,
readonly=true,
value=WIS,
bordercolor={1 1 1}
]{}&
\TextField[
name=WIS,
width=0.8cm,
height=0.8cm,
readonly=false,
value={10},
calculate={var A = this.getField("WIS").value; var B = (parseInt(A)-10)/2 ; this.getField("WISBonus").value=Math.floor(B);},
]{}&
\TextField[
name=WISBonus,
width=0.8cm,
height=0.8cm,
readonly=true,
value={0}
]{}\\
\TextField[
name=cha,
width=0.8cm,
height=0.8cm,
readonly=true,
value=CHA,
bordercolor={1 1 1}
]{}&
\TextField[
name=CHA,
width=0.8cm,
height=0.8cm,
readonly=false,
value={10},
calculate={var A = this.getField("CHA").value; var B = (parseInt(A)-10)/2 ; this.getField("CHABonus").value=Math.floor(B);},
]{}&
\TextField[
name=CHABonus,
width=0.8cm,
height=0.8cm,
readonly=true,
value={0}
]{}
\end{tabular}
\end{minipage}\begin{minipage}{0.5\textwidth}
\begin{tabular}{lll}
\mycircle{\CheckBox[
name=AcroPB,
value=Off,
width=7pt,
height=7pt,
checkboxsymbol=l,
bordercolor={1 1 1}
]{}}& Acrobatics & \TextField[
name=AcroBonus,
readonly=true,
value={0},
calculate={var A = this.getField("DEXBonus").value; var B= 0; if (this.getField("AcroPB").value === "Yes"){B = this.getField("PB").value;} this.getField("AcroBonus").value=A+B;},
]{}\\
\mycircle{\CheckBox[name=AnHPB,value=Off,width=7pt,
height=7pt,
checkboxsymbol=l,
bordercolor={1 1 1}]{}} & Animal Handling &
\TextField[
name=AnHBonus,
readonly=true,
value={0},
calculate={var A=this.getField("WISBonus").value;
var B=0;
if(this.getField("AnHPB").value==="Yes"){B=this.getField("PB").value;}
event.value = Number(A)+Number(B);}
]{} \\
\mycircle{\CheckBox[name=ArcPB,value=Off,width=7pt,
height=7pt,
checkboxsymbol=l,
bordercolor={1 1 1}]{}} & Arcana &
\TextField[
name=ArcBonus,
readonly=true,
value={0},
calculate={var A=this.getField("INTBonus").value;
var B=0;
if(this.getField("ArcPB").value==="Yes"){B=this.getField("PB").value;}
event.value = Number(A)+Number(B);}
]{} \\
\mycircle{\CheckBox[
name=AthlPB,
value=Off,width=7pt,
height=7pt,
checkboxsymbol=l,
bordercolor={1 1 1}
]{}}& Athletics&
\TextField[
name=AthlBonus,
readonly=true,
value={0},
calculate={var A = this.getField("STRBonus").value; var B= 0; if (this.getField("AthlPB").value === "Yes"){B = this.getField("PB").value;} this.getField("AthlBonus").value=A+B;}
]{}\\
\mycircle{\CheckBox[name=DecPB,value=Off,width=7pt,
height=7pt,
checkboxsymbol=l,
bordercolor={1 1 1}]{}} & Deception &
\TextField[
name=DecBonus,
readonly=true,
value={0},
calculate={var A=this.getField("CHABonus").value;
var B=0;
if(this.getField("DecPB").value==="Yes"){B=this.getField("PB").value;}
event.value = Number(A)+Number(B);}
]{} \\
\mycircle{\CheckBox[name=HisPB,value=Off,width=7pt,
height=7pt,
checkboxsymbol=l,
bordercolor={1 1 1}]{}} & History &
\TextField[
name=HisBonus,
readonly=true,
value={0},
calculate={var A=this.getField("INTBonus").value;
var B=0;
if(this.getField("HisPB").value==="Yes"){B=this.getField("PB").value;}
event.value = Number(A)+Number(B);}
]{} \\
\mycircle{\CheckBox[name=InsPB,value=Off,width=7pt,
height=7pt,
checkboxsymbol=l,
bordercolor={1 1 1}]{}} & Insight &
\TextField[
name=InsBonus,
readonly=true,
value={0},
calculate={var A=this.getField("WISBonus").value;
var B=0;
if(this.getField("InsPB").value==="Yes"){B=this.getField("PB").value;}
event.value = Number(A)+Number(B);}
]{} \\
\mycircle{\CheckBox[name=IntPB,value=Off,width=7pt,
height=7pt,
checkboxsymbol=l,
bordercolor={1 1 1}]{}} & Intimidation &
\TextField[
name=IntBonus,
readonly=true,
value={0},
calculate={var A=this.getField("CHABonus").value;
var B=0;
if(this.getField("IntPB").value==="Yes"){B=this.getField("PB").value;}
event.value = Number(A)+Number(B);}
]{} \\
\mycircle{\CheckBox[name=InvPB,value=Off,width=7pt,
height=7pt,
checkboxsymbol=l,
bordercolor={1 1 1}]{}} & Investigation &
\TextField[
name=InvBonus,
readonly=true,
value={0},
calculate={var A=this.getField("INTBonus").value;
var B=0;
if(this.getField("InvPB").value==="Yes"){B=this.getField("PB").value;}
event.value = Number(A)+Number(B);}
]{} \\
\mycircle{\CheckBox[name=MedPB,value=Off,width=7pt,
height=7pt,
checkboxsymbol=l,
bordercolor={1 1 1}]{}} & Medicine &
\TextField[
name=MedBonus,
readonly=true,
value={0},
calculate={var A=this.getField("WISBonus").value;
var B=0;
if(this.getField("MedPB").value==="Yes"){B=this.getField("PB").value;}
event.value = Number(A)+Number(B);}
]{} \\
\mycircle{\CheckBox[name=NatPB,value=Off,width=7pt,
height=7pt,
checkboxsymbol=l,
bordercolor={1 1 1}]{}} & Nature &
\TextField[
name=NatBonus,
readonly=true,
value={0},
calculate={var A=this.getField("INTBonus").value;
var B=0;
if(this.getField("NatPB").value==="Yes"){B=this.getField("PB").value;}
event.value = Number(A)+Number(B);}
]{} \\
\mycircle{\CheckBox[name=PerPB,value=Off,width=7pt,
height=7pt,
checkboxsymbol=l,
bordercolor={1 1 1}]{}} & Perception &
\TextField[
name=PerBonus,
readonly=true,
value={0},
calculate={var A=this.getField("WISBonus").value;
var B=0;
if(this.getField("PerPB").value==="Yes"){B=this.getField("PB").value;}
event.value = Number(A)+Number(B);}
]{} \\
\mycircle{\CheckBox[name=PerfPB,value=Off,width=7pt,
height=7pt,
checkboxsymbol=l,
bordercolor={1 1 1}]{}} & Performance &
\TextField[
name=PerfBonus,
readonly=true,
value={0},
calculate={var A=this.getField("CHABonus").value;
var B=0;
if(this.getField("PerfPB").value==="Yes"){B=this.getField("PB").value;}
event.value = Number(A)+Number(B);}
]{} \\
\mycircle{\CheckBox[name=PersPB,value=Off,width=7pt,
height=7pt,
checkboxsymbol=l,
bordercolor={1 1 1}]{}} & Persuasion &
\TextField[
name=PersBonus,
readonly=true,
value={0},
calculate={var A=this.getField("CHABonus").value;
var B=0;
if(this.getField("PersPB").value==="Yes"){B=this.getField("PB").value;}
event.value = Number(A)+Number(B);}
]{} \\
\mycircle{\CheckBox[name=RelPB,value=Off,width=7pt,
height=7pt,
checkboxsymbol=l,
bordercolor={1 1 1}]{}} & Religion &
\TextField[
name=RelBonus,
readonly=true,
value={0},
calculate={var A=this.getField("INTBonus").value;
var B=0;
if(this.getField("RelPB").value==="Yes"){B=this.getField("PB").value;}
event.value = Number(A)+Number(B);}
]{} \\
\mycircle{\CheckBox[name=SoHPB,value=Off,width=7pt,
height=7pt,
checkboxsymbol=l,
bordercolor={1 1 1}]{}} & Sleight of Hand &
\TextField[
name=SoHBonus,
readonly=true,
value={0},
calculate={var A=this.getField("DEXBonus").value;
var B=0;
if(this.getField("SoHPB").value==="Yes"){B=this.getField("PB").value;}
event.value = Number(A)+Number(B);}
]{} \\
\mycircle{\CheckBox[name=StePB,value=Off,width=7pt,
height=7pt,
checkboxsymbol=l,
bordercolor={1 1 1}]{}} & Stealth &
\TextField[
name=SteBonus,
readonly=true,
value={0},
calculate={var A=this.getField("DEXBonus").value;
var B=0;
if(this.getField("StePB").value==="Yes"){B=this.getField("PB").value;}
event.value = Number(A)+Number(B);}
]{} \\
\mycircle{\CheckBox[name=SurPB,value=Off,width=7pt,
height=7pt,
checkboxsymbol=l,
bordercolor={1 1 1}]{}} & Survival &
\TextField[
name=SurBonus,
readonly=true,
value={0},
calculate={var A=this.getField("WISBonus").value;
var B=0;
if(this.getField("SurPB").value==="Yes"){B=this.getField("PB").value;}
event.value = Number(A)+Number(B);}
]{} \\
\end{tabular}
\end{minipage}
\end{document}