.katex { display: block; text-align: center; white-space: nowrap; }
.katex-display > .katex > .katex-html { display: block; }
.katex-display > .katex > .katex-html > .tag { position: absolute; right: 0px; }
.katex { font: 1.21em/1.2 KaTeX_Main, "Times New Roman", serif; text-indent: 0px; text-rendering: auto; }
.katex * { }
.katex .katex-mathml { position: absolute; clip: rect(1px, 1px, 1px, 1px); padding: 0px; border: 0px; height: 1px; width: 1px; overflow: hidden; }
.katex .katex-html { }
.katex .katex-html > .newline { display: block; }
.katex .base { position: relative; display: inline-block; white-space: nowrap; width: min-content; }
.katex .strut { display: inline-block; }
.katex .textbf { font-weight: bold; }
.katex .textit { font-style: italic; }
.katex .textrm { font-family: KaTeX_Main; }
.katex .textsf { font-family: KaTeX_SansSerif; }
.katex .texttt { font-family: KaTeX_Typewriter; }
.katex .mathit { font-family: KaTeX_Math; font-style: italic; }
.katex .mathrm { font-style: normal; }
.katex .mathbf { font-family: KaTeX_Main; font-weight: bold; }
.katex .boldsymbol { font-family: KaTeX_Math; font-weight: bold; font-style: italic; }
.katex .amsrm { font-family: KaTeX_AMS; }
.katex .mathbb, .katex .textbb { font-family: KaTeX_AMS; }
.katex .mathcal { font-family: KaTeX_Caligraphic; }
.katex .mathfrak, .katex .textfrak { font-family: KaTeX_Fraktur; }
.katex .mathtt { font-family: KaTeX_Typewriter; }
.katex .mathscr, .katex .textscr { font-family: KaTeX_Script; }
.katex .mathsf, .katex .textsf { font-family: KaTeX_SansSerif; }
.katex .mainit { font-family: KaTeX_Main; font-style: italic; }
.katex .mainrm { font-family: KaTeX_Main; font-style: normal; }
.katex .vlist-t { display: inline-table; table-layout: fixed; }
.katex .vlist-r { display: table-row; }
.katex .vlist { display: table-cell; vertical-align: bottom; position: relative; }
.katex .vlist > span { display: block; height: 0px; position: relative; }
.katex .vlist > span > span { display: inline-block; }
.katex .vlist > span > .pstrut { overflow: hidden; width: 0px; }
.katex .vlist-t2 { margin-right: -2px; }
.katex .vlist-s { display: table-cell; vertical-align: bottom; font-size: 1px; width: 2px; min-width: 2px; }
.katex .msupsub { text-align: left; }
.katex .mfrac > span > span { text-align: center; }
.katex .mfrac .frac-line { display: inline-block; width: 100%; border-bottom-style: solid; }
.katex .mspace { display: inline-block; }
.katex .llap, .katex .rlap, .katex .clap { width: 0px; position: relative; }
.katex .llap > .inner, .katex .rlap > .inner, .katex .clap > .inner { position: absolute; }
.katex .llap > .fix, .katex .rlap > .fix, .katex .clap > .fix { display: inline-block; }
.katex .llap > .inner { right: 0px; }
.katex .rlap > .inner, .katex .clap > .inner { left: 0px; }
.katex .clap > .inner > span { margin-left: -50%; margin-right: 50%; }
.katex .rule { display: inline-block; border: 0px solid; position: relative; }
.katex .overline .overline-line, .katex .underline .underline-line, .katex .hline { display: inline-block; width: 100%; border-bottom-style: solid; }
.katex .hdashline { display: inline-block; width: 100%; border-bottom-style: dashed; }
.katex .sqrt > .root { margin-left: 0.277778em; margin-right: -0.555556em; }
.katex .sizing, .katex .fontsize-ensurer { display: inline-block; }
.katex .sizing.reset-size1.size1, .katex .fontsize-ensurer.reset-size1.size1 { font-size: 1em; }
.katex .sizing.reset-size1.size2, .katex .fontsize-ensurer.reset-size1.size2 { font-size: 1.2em; }
.katex .sizing.reset-size1.size3, .katex .fontsize-ensurer.reset-size1.size3 { font-size: 1.4em; }
.katex .sizing.reset-size1.size4, .katex .fontsize-ensurer.reset-size1.size4 { font-size: 1.6em; }
.katex .sizing.reset-size1.size5, .katex .fontsize-ensurer.reset-size1.size5 { font-size: 1.8em; }
.katex .sizing.reset-size1.size6, .katex .fontsize-ensurer.reset-size1.size6 { font-size: 2em; }
.katex .sizing.reset-size1.size7, .katex .fontsize-ensurer.reset-size1.size7 { font-size: 2.4em; }
.katex .sizing.reset-size1.size8, .katex .fontsize-ensurer.reset-size1.size8 { font-size: 2.88em; }
.katex .sizing.reset-size1.size9, .katex .fontsize-ensurer.reset-size1.size9 { font-size: 3.456em; }
.katex .sizing.reset-size1.size10, .katex .fontsize-ensurer.reset-size1.size10 { font-size: 4.148em; }
.katex .sizing.reset-size1.size11, .katex .fontsize-ensurer.reset-size1.size11 { font-size: 4.976em; }
.katex .sizing.reset-size2.size1, .katex .fontsize-ensurer.reset-size2.size1 { font-size: 0.833333em; }
.katex .sizing.reset-size2.size2, .katex .fontsize-ensurer.reset-size2.size2 { font-size: 1em; }
.katex .sizing.reset-size2.size3, .katex .fontsize-ensurer.reset-size2.size3 { font-size: 1.16667em; }
.katex .sizing.reset-size2.size4, .katex .fontsize-ensurer.reset-size2.size4 { font-size: 1.33333em; }
.katex .sizing.reset-size2.size5, .katex .fontsize-ensurer.reset-size2.size5 { font-size: 1.5em; }
.katex .sizing.reset-size2.size6, .katex .fontsize-ensurer.reset-size2.size6 { font-size: 1.66667em; }
.katex .sizing.reset-size2.size7, .katex .fontsize-ensurer.reset-size2.size7 { font-size: 2em; }
.katex .sizing.reset-size2.size8, .katex .fontsize-ensurer.reset-size2.size8 { font-size: 2.4em; }
.katex .sizing.reset-size2.size9, .katex .fontsize-ensurer.reset-size2.size9 { font-size: 2.88em; }
.katex .sizing.reset-size2.size10, .katex .fontsize-ensurer.reset-size2.size10 { font-size: 3.45667em; }
.katex .sizing.reset-size2.size11, .katex .fontsize-ensurer.reset-size2.size11 { font-size: 4.14667em; }
.katex .sizing.reset-size3.size1, .katex .fontsize-ensurer.reset-size3.size1 { font-size: 0.714286em; }
.katex .sizing.reset-size3.size2, .katex .fontsize-ensurer.reset-size3.size2 { font-size: 0.857143em; }
.katex .sizing.reset-size3.size3, .katex .fontsize-ensurer.reset-size3.size3 { font-size: 1em; }
.katex .sizing.reset-size3.size4, .katex .fontsize-ensurer.reset-size3.size4 { font-size: 1.14286em; }
.katex .sizing.reset-size3.size5, .katex .fontsize-ensurer.reset-size3.size5 { font-size: 1.28571em; }
.katex .sizing.reset-size3.size6, .katex .fontsize-ensurer.reset-size3.size6 { font-size: 1.42857em; }
.katex .sizing.reset-size3.size7, .katex .fontsize-ensurer.reset-size3.size7 { font-size: 1.71429em; }
.katex .sizing.reset-size3.size8, .katex .fontsize-ensurer.reset-size3.size8 { font-size: 2.05714em; }
.katex .sizing.reset-size3.size9, .katex .fontsize-ensurer.reset-size3.size9 { font-size: 2.46857em; }
.katex .sizing.reset-size3.size10, .katex .fontsize-ensurer.reset-size3.size10 { font-size: 2.96286em; }
.katex .sizing.reset-size3.size11, .katex .fontsize-ensurer.reset-size3.size11 { font-size: 3.55429em; }
.katex .sizing.reset-size4.size1, .katex .fontsize-ensurer.reset-size4.size1 { font-size: 0.625em; }
.katex .sizing.reset-size4.size2, .katex .fontsize-ensurer.reset-size4.size2 { font-size: 0.75em; }
.katex .sizing.reset-size4.size3, .katex .fontsize-ensurer.reset-size4.size3 { font-size: 0.875em; }
.katex .sizing.reset-size4.size4, .katex .fontsize-ensurer.reset-size4.size4 { font-size: 1em; }
.katex .sizing.reset-size4.size5, .katex .fontsize-ensurer.reset-size4.size5 { font-size: 1.125em; }
.katex .sizing.reset-size4.size6, .katex .fontsize-ensurer.reset-size4.size6 { font-size: 1.25em; }
.katex .sizing.reset-size4.size7, .katex .fontsize-ensurer.reset-size4.size7 { font-size: 1.5em; }
.katex .sizing.reset-size4.size8, .katex .fontsize-ensurer.reset-size4.size8 { font-size: 1.8em; }
.katex .sizing.reset-size4.size9, .katex .fontsize-ensurer.reset-size4.size9 { font-size: 2.16em; }
.katex .sizing.reset-size4.size10, .katex .fontsize-ensurer.reset-size4.size10 { font-size: 2.5925em; }
.katex .sizing.reset-size4.size11, .katex .fontsize-ensurer.reset-size4.size11 { font-size: 3.11em; }
.katex .sizing.reset-size5.size1, .katex .fontsize-ensurer.reset-size5.size1 { font-size: 0.555556em; }
.katex .sizing.reset-size5.size2, .katex .fontsize-ensurer.reset-size5.size2 { font-size: 0.666667em; }
.katex .sizing.reset-size5.size3, .katex .fontsize-ensurer.reset-size5.size3 { font-size: 0.777778em; }
.katex .sizing.reset-size5.size4, .katex .fontsize-ensurer.reset-size5.size4 { font-size: 0.888889em; }
.katex .sizing.reset-size5.size5, .katex .fontsize-ensurer.reset-size5.size5 { font-size: 1em; }
.katex .sizing.reset-size5.size6, .katex .fontsize-ensurer.reset-size5.size6 { font-size: 1.11111em; }
.katex .sizing.reset-size5.size7, .katex .fontsize-ensurer.reset-size5.size7 { font-size: 1.33333em; }
.katex .sizing.reset-size5.size8, .katex .fontsize-ensurer.reset-size5.size8 { font-size: 1.6em; }
.katex .sizing.reset-size5.size9, .katex .fontsize-ensurer.reset-size5.size9 { font-size: 1.92em; }
.katex .sizing.reset-size5.size10, .katex .fontsize-ensurer.reset-size5.size10 { font-size: 2.30444em; }
.katex .sizing.reset-size5.size11, .katex .fontsize-ensurer.reset-size5.size11 { font-size: 2.76444em; }
.katex .sizing.reset-size6.size1, .katex .fontsize-ensurer.reset-size6.size1 { font-size: 0.5em; }
.katex .sizing.reset-size6.size2, .katex .fontsize-ensurer.reset-size6.size2 { font-size: 0.6em; }
.katex .sizing.reset-size6.size3, .katex .fontsize-ensurer.reset-size6.size3 { font-size: 0.7em; }
.katex .sizing.reset-size6.size4, .katex .fontsize-ensurer.reset-size6.size4 { font-size: 0.8em; }
.katex .sizing.reset-size6.size5, .katex .fontsize-ensurer.reset-size6.size5 { font-size: 0.9em; }
.katex .sizing.reset-size6.size6, .katex .fontsize-ensurer.reset-size6.size6 { font-size: 1em; }
.katex .sizing.reset-size6.size7, .katex .fontsize-ensurer.reset-size6.size7 { font-size: 1.2em; }
.katex .sizing.reset-size6.size8, .katex .fontsize-ensurer.reset-size6.size8 { font-size: 1.44em; }
.katex .sizing.reset-size6.size9, .katex .fontsize-ensurer.reset-size6.size9 { font-size: 1.728em; }
.katex .sizing.reset-size6.size10, .katex .fontsize-ensurer.reset-size6.size10 { font-size: 2.074em; }
.katex .sizing.reset-size6.size11, .katex .fontsize-ensurer.reset-size6.size11 { font-size: 2.488em; }
.katex .sizing.reset-size7.size1, .katex .fontsize-ensurer.reset-size7.size1 { font-size: 0.416667em; }
.katex .sizing.reset-size7.size2, .katex .fontsize-ensurer.reset-size7.size2 { font-size: 0.5em; }
.katex .sizing.reset-size7.size3, .katex .fontsize-ensurer.reset-size7.size3 { font-size: 0.583333em; }
.katex .sizing.reset-size7.size4, .katex .fontsize-ensurer.reset-size7.size4 { font-size: 0.666667em; }
.katex .sizing.reset-size7.size5, .katex .fontsize-ensurer.reset-size7.size5 { font-size: 0.75em; }
.katex .sizing.reset-size7.size6, .katex .fontsize-ensurer.reset-size7.size6 { font-size: 0.833333em; }
.katex .sizing.reset-size7.size7, .katex .fontsize-ensurer.reset-size7.size7 { font-size: 1em; }
.katex .sizing.reset-size7.size8, .katex .fontsize-ensurer.reset-size7.size8 { font-size: 1.2em; }
.katex .sizing.reset-size7.size9, .katex .fontsize-ensurer.reset-size7.size9 { font-size: 1.44em; }
.katex .sizing.reset-size7.size10, .katex .fontsize-ensurer.reset-size7.size10 { font-size: 1.72833em; }
.katex .sizing.reset-size7.size11, .katex .fontsize-ensurer.reset-size7.size11 { font-size: 2.07333em; }
.katex .sizing.reset-size8.size1, .katex .fontsize-ensurer.reset-size8.size1 { font-size: 0.347222em; }
.katex .sizing.reset-size8.size2, .katex .fontsize-ensurer.reset-size8.size2 { font-size: 0.416667em; }
.katex .sizing.reset-size8.size3, .katex .fontsize-ensurer.reset-size8.size3 { font-size: 0.486111em; }
.katex .sizing.reset-size8.size4, .katex .fontsize-ensurer.reset-size8.size4 { font-size: 0.555556em; }
.katex .sizing.reset-size8.size5, .katex .fontsize-ensurer.reset-size8.size5 { font-size: 0.625em; }
.katex .sizing.reset-size8.size6, .katex .fontsize-ensurer.reset-size8.size6 { font-size: 0.694444em; }
.katex .sizing.reset-size8.size7, .katex .fontsize-ensurer.reset-size8.size7 { font-size: 0.833333em; }
.katex .sizing.reset-size8.size8, .katex .fontsize-ensurer.reset-size8.size8 { font-size: 1em; }
.katex .sizing.reset-size8.size9, .katex .fontsize-ensurer.reset-size8.size9 { font-size: 1.2em; }
.katex .sizing.reset-size8.size10, .katex .fontsize-ensurer.reset-size8.size10 { font-size: 1.44028em; }
.katex .sizing.reset-size8.size11, .katex .fontsize-ensurer.reset-size8.size11 { font-size: 1.72778em; }
.katex .sizing.reset-size9.size1, .katex .fontsize-ensurer.reset-size9.size1 { font-size: 0.289352em; }
.katex .sizing.reset-size9.size2, .katex .fontsize-ensurer.reset-size9.size2 { font-size: 0.347222em; }
.katex .sizing.reset-size9.size3, .katex .fontsize-ensurer.reset-size9.size3 { font-size: 0.405093em; }
.katex .sizing.reset-size9.size4, .katex .fontsize-ensurer.reset-size9.size4 { font-size: 0.462963em; }
.katex .sizing.reset-size9.size5, .katex .fontsize-ensurer.reset-size9.size5 { font-size: 0.520833em; }
.katex .sizing.reset-size9.size6, .katex .fontsize-ensurer.reset-size9.size6 { font-size: 0.578704em; }
.katex .sizing.reset-size9.size7, .katex .fontsize-ensurer.reset-size9.size7 { font-size: 0.694444em; }
.katex .sizing.reset-size9.size8, .katex .fontsize-ensurer.reset-size9.size8 { font-size: 0.833333em; }
.katex .sizing.reset-size9.size9, .katex .fontsize-ensurer.reset-size9.size9 { font-size: 1em; }
.katex .sizing.reset-size9.size10, .katex .fontsize-ensurer.reset-size9.size10 { font-size: 1.20023em; }
.katex .sizing.reset-size9.size11, .katex .fontsize-ensurer.reset-size9.size11 { font-size: 1.43981em; }
.katex .sizing.reset-size10.size1, .katex .fontsize-ensurer.reset-size10.size1 { font-size: 0.24108em; }
.katex .sizing.reset-size10.size2, .katex .fontsize-ensurer.reset-size10.size2 { font-size: 0.289296em; }
.katex .sizing.reset-size10.size3, .katex .fontsize-ensurer.reset-size10.size3 { font-size: 0.337512em; }
.katex .sizing.reset-size10.size4, .katex .fontsize-ensurer.reset-size10.size4 { font-size: 0.385728em; }
.katex .sizing.reset-size10.size5, .katex .fontsize-ensurer.reset-size10.size5 { font-size: 0.433944em; }
.katex .sizing.reset-size10.size6, .katex .fontsize-ensurer.reset-size10.size6 { font-size: 0.48216em; }
.katex .sizing.reset-size10.size7, .katex .fontsize-ensurer.reset-size10.size7 { font-size: 0.578592em; }
.katex .sizing.reset-size10.size8, .katex .fontsize-ensurer.reset-size10.size8 { font-size: 0.694311em; }
.katex .sizing.reset-size10.size9, .katex .fontsize-ensurer.reset-size10.size9 { font-size: 0.833173em; }
.katex .sizing.reset-size10.size10, .katex .fontsize-ensurer.reset-size10.size10 { font-size: 1em; }
.katex .sizing.reset-size10.size11, .katex .fontsize-ensurer.reset-size10.size11 { font-size: 1.19961em; }
.katex .sizing.reset-size11.size1, .katex .fontsize-ensurer.reset-size11.size1 { font-size: 0.200965em; }
.katex .sizing.reset-size11.size2, .katex .fontsize-ensurer.reset-size11.size2 { font-size: 0.241158em; }
.katex .sizing.reset-size11.size3, .katex .fontsize-ensurer.reset-size11.size3 { font-size: 0.28135em; }
.katex .sizing.reset-size11.size4, .katex .fontsize-ensurer.reset-size11.size4 { font-size: 0.321543em; }
.katex .sizing.reset-size11.size5, .katex .fontsize-ensurer.reset-size11.size5 { font-size: 0.361736em; }
.katex .sizing.reset-size11.size6, .katex .fontsize-ensurer.reset-size11.size6 { font-size: 0.401929em; }
.katex .sizing.reset-size11.size7, .katex .fontsize-ensurer.reset-size11.size7 { font-size: 0.482315em; }
.katex .sizing.reset-size11.size8, .katex .fontsize-ensurer.reset-size11.size8 { font-size: 0.578778em; }
.katex .sizing.reset-size11.size9, .katex .fontsize-ensurer.reset-size11.size9 { font-size: 0.694534em; }
.katex .sizing.reset-size11.size10, .katex .fontsize-ensurer.reset-size11.size10 { font-size: 0.833601em; }
.katex .sizing.reset-size11.size11, .katex .fontsize-ensurer.reset-size11.size11 { font-size: 1em; }
.katex .delimsizing.size1 { font-family: KaTeX_Size1; }
.katex .delimsizing.size2 { font-family: KaTeX_Size2; }
.katex .delimsizing.size3 { font-family: KaTeX_Size3; }
.katex .delimsizing.size4 { font-family: KaTeX_Size4; }
.katex .delimsizing.mult .delim-size1 > span { font-family: KaTeX_Size1; }
.katex .delimsizing.mult .delim-size4 > span { font-family: KaTeX_Size4; }
.katex .nulldelimiter { display: inline-block; width: 0.12em; }
.katex .delimcenter { position: relative; }
.katex .op-symbol { position: relative; }
.katex .op-symbol.small-op { font-family: KaTeX_Size1; }
.katex .op-symbol.large-op { font-family: KaTeX_Size2; }
.katex .op-limits > .vlist-t { text-align: center; }
.katex .accent > .vlist-t { text-align: center; }
.katex .accent .accent-body:not(.accent-full) { width: 0px; }
.katex .accent .accent-body { position: relative; }
.katex .overlay { display: block; }
.katex .mtable .vertical-separator { display: inline-block; margin: 0px -0.025em; border-right: 0.05em solid; }
.katex .mtable .vs-dashed { border-right: 0.05em dashed; }
.katex .mtable .arraycolsep { display: inline-block; }
.katex .mtable .col-align-c > .vlist-t { text-align: center; }
.katex .mtable .col-align-l > .vlist-t { text-align: left; }
.katex .mtable .col-align-r > .vlist-t { text-align: right; }
.katex .svg-align { text-align: left; }
.katex svg, .screenShotTempCanvas { display: block; position: absolute; width: 100%; height: inherit; fill: currentcolor; stroke: currentcolor; fill-rule: nonzero; fill-opacity: 1; stroke-width: 1; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 4; stroke-dasharray: none; stroke-dashoffset: 0; stroke-opacity: 1; }
.katex svg path { stroke: none; }
.katex .stretchy { width: 100%; display: block; position: relative; overflow: hidden; }
.katex .stretchy::before, .katex .stretchy::after { content: ""; }
.katex .hide-tail { width: 100%; position: relative; overflow: hidden; }
.katex .halfarrow-left { position: absolute; left: 0px; width: 50.2%; overflow: hidden; }
.katex .halfarrow-right { position: absolute; right: 0px; width: 50.2%; overflow: hidden; }
.katex .brace-left { position: absolute; left: 0px; width: 25.1%; overflow: hidden; }
.katex .brace-center { position: absolute; left: 25%; width: 50%; overflow: hidden; }
.katex .brace-right { position: absolute; right: 0px; width: 25.1%; overflow: hidden; }
.katex .x-arrow-pad { padding: 0px 0.5em; }
.katex .x-arrow, .katex .mover, .katex .munder { text-align: center; }
.katex .boxpad { padding: 0px 0.3em; }
.katex .fbox { box-sizing: border-box; border: 0.04em solid black; }
.katex .fcolorbox { box-sizing: border-box; border: 0.04em solid; }
.katex .cancel-pad { padding: 0px 0.2em; }
.katex .cancel-lap { margin-left: -0.2em; margin-right: -0.2em; }
.katex .sout { border-bottom-style: solid; border-bottom-width: 0.08em; }
.output_wrapper pre code { display: -webkit-box !important; }
.output_wrapper .hljs{color: rgb(169, 183, 198); background: rgb(40, 43, 46); display: block; overflow-x: auto; padding: 0.5em;}
.output_wrapper .hljs-params{color: rgb(255, 152, 35);}
.output_wrapper .hljs-number,.output_wrapper .hljs-literal,.output_wrapper .hljs-symbol,.output_wrapper .hljs-bullet{color: rgb(174, 135, 250);}
.output_wrapper .hljs-function,.output_wrapper .hljs-built_in,.output_wrapper .hljs-name,.output_wrapper .hljs-keyword,.output_wrapper .hljs-selector-tag,.output_wrapper .hljs-deletion{color: rgb(248, 35, 117);}
.output_wrapper .hljs-variable,.output_wrapper .hljs-template-variable,.output_wrapper .hljs-link{color: rgb(98, 151, 85);}
.output_wrapper .hljs-comment,.output_wrapper .hljs-quote{color: rgb(128, 128, 128);}
.output_wrapper .hljs-meta{color: rgb(91, 218, 237);}
.output_wrapper .hljs-string,.output_wrapper .hljs-attribute,.output_wrapper .hljs-addition{color: rgb(238, 220, 112);}
.output_wrapper .hljs-attr,.output_wrapper .hljs-section,.output_wrapper .hljs-title,.output_wrapper .hljs-type{color: rgb(165, 218, 45);}
.output_wrapper .hljs-selector-class{color: rgb(165, 218, 45);}
.output_wrapper .hljs-emphasis{font-style: italic;}
.output_wrapper .hljs-strong{font-weight: bold;}
.output_wrapper pre code {line-height: 18px; font-size: 14px; font-weight: normal; word-spacing: 0px; letter-spacing: 0px;}
.output_wrapper{font-size: 16px; color: rgb(62, 62, 62); line-height: 1.6; word-spacing: 0px; letter-spacing: 0px; font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif; background-image: linear-gradient(90deg, rgba(50, 0, 0, 0.05) 3%, rgba(0, 0, 0, 0) 3%), linear-gradient(360deg, rgba(50, 0, 0, 0.05) 3%, rgba(0, 0, 0, 0) 3%); background-size: 20px 20px; background-position: center center;}
.output_wrapper *{font-size: inherit; color: inherit; line-height: inherit; margin: 0px; padding: 0px;}
.output_wrapper p{margin: 1.5em 0px;}
.output_wrapper h1,.output_wrapper h2,.output_wrapper h3,.output_wrapper h4,.output_wrapper h5,.output_wrapper h6{margin: 1.5em 0px; font-weight: bold;}
.output_wrapper h1{font-size: 1.6em;}
.output_wrapper h2{font-size: 1.4em;}
.output_wrapper h3{font-size: 1.3em;}
.output_wrapper h4{font-size: 1.2em;}
.output_wrapper h5{font-size: 1em;}
.output_wrapper h6{font-size: 1em;}
.output_wrapper ul,.output_wrapper ol{padding-left: 32px;}
.output_wrapper ul{list-style-type: disc;}
.output_wrapper ol{list-style-type: decimal;}
.output_wrapper li *{}
.output_wrapper li{margin-bottom: 0.5em;}
.output_wrapper .code_size_default{line-height: 18px; font-size: 14px; font-weight: normal; word-spacing: 0px; letter-spacing: 0px;}
.output_wrapper .code_size_tight{line-height: 15px; font-size: 11px; font-weight: normal; word-spacing: -3px; letter-spacing: 0px;}
.output_wrapper pre code{font-family: Consolas, Inconsolata, Courier, monospace; border-radius: 0px;}
.output_wrapper blockquote{display: block; padding: 15px 15px 15px 1rem; font-size: 0.9em; margin: 1em 0px; color: rgb(129, 145, 152); border-left: 6px solid rgb(220, 230, 240); background: rgb(242, 247, 251); overflow: auto; overflow-wrap: normal; word-break: normal;}
.output_wrapper blockquote p{margin: 0px;}
.output_wrapper a{text-decoration: none; color: rgb(30, 107, 184); overflow-wrap: break-word;}
.output_wrapper strong{font-weight: bold;}
.output_wrapper em{font-style: italic;}
.output_wrapper del{font-style: italic;}
.output_wrapper strong em{font-weight: bold;}
.output_wrapper hr{height: 1px; margin: 1.5rem 0px; border-right: none; border-bottom: none; border-left: none; border-image: initial; border-top: 1px dashed rgb(165, 165, 165);}
.output_wrapper code{overflow-wrap: break-word; padding: 2px 4px; border-radius: 4px; margin: 0px 2px; color: rgb(233, 105, 0); background: rgb(248, 248, 248);}
.output_wrapper img{display: block; margin: 0px auto; max-width: 100%;}
.output_wrapper figcaption{margin-top: 10px; text-align: center; color: rgb(153, 153, 153); font-size: 0.7em;}
.output_wrapper table{display: table; width: 100%; text-align: left;}
.output_wrapper tbody{border: 0px;}
.output_wrapper table tr{border-width: 1px 0px 0px; border-right-style: initial; border-bottom-style: initial; border-left-style: initial; border-right-color: initial; border-bottom-color: initial; border-left-color: initial; border-image: initial; border-top-style: solid; border-top-color: rgb(204, 204, 204); background-color: white;}
.output_wrapper table tr th,.output_wrapper table tr td{font-size: 1em; border: 1px solid rgb(204, 204, 204); padding: 0.5em 1em; text-align: left;}
.output_wrapper table tr th{font-weight: bold; background-color: rgb(240, 240, 240);}
.output_wrapper .katex-display{font-size: 1.22em;}
.output_wrapper .katex{padding: 8px 3px;}
.output_wrapper .katex-display > .katex{display: inline-block; text-align: center; padding: 3px;}
.output_wrapper .katex img{display: inline-block; vertical-align: middle;}
.output_wrapper a[href^="#"] sup{vertical-align: super; margin: 0px 2px; padding: 1px 3px; color: rgb(255, 255, 255); background: rgb(102, 102, 102); font-size: 0.7em;}
.output_wrapper .task-list-list{list-style-type: none;}
.output_wrapper .task-list-list.checked{color: rgb(62, 62, 62);}
.output_wrapper .task-list-list.uncheck{color: rgb(191, 193, 191);}
.output_wrapper .task-list-list .icon_uncheck,.output_wrapper .task-list-list .icon_check{display: inline-block; vertical-align: middle; margin-right: 10px;}
.output_wrapper .task-list-list .icon_check::before{content: "√"; border: 2px solid rgb(62, 62, 62); color: red;}
.output_wrapper .task-list-list .icon_uncheck::before{content: "x"; border: 2px solid rgb(191, 193, 191); color: rgb(191, 193, 191);}
.output_wrapper .task-list-list .icon_check::before,.output_wrapper .task-list-list .icon_uncheck::before{padding: 2px 8px 2px 5px; border-radius: 5px;}
.output_wrapper .toc{margin-left: 25px;}
.output_wrapper .toc_item{display: block;}
.output_wrapper .toc_left{margin-left: 25px;}
.output_wrapper pre code{border-radius: 3px; border-width: 1px 1px 1px 6px; border-style: solid; border-color: rgb(204, 204, 204) rgb(204, 204, 204) rgb(204, 204, 204) rgb(33, 152, 99);}
.output_wrapper pre code .linenum{padding-right: 20px; word-spacing: 0px;}
.output_wrapper .hljs{color: rgb(169, 183, 198); background: rgb(40, 43, 46); display: block; overflow-x: auto; padding: 0.5em;}
.output_wrapper .hljs-params{color: rgb(255, 152, 35);}
.output_wrapper .hljs-number,.output_wrapper .hljs-literal,.output_wrapper .hljs-symbol,.output_wrapper .hljs-bullet{color: rgb(174, 135, 250);}
.output_wrapper .hljs-function,.output_wrapper .hljs-built_in,.output_wrapper .hljs-name,.output_wrapper .hljs-keyword,.output_wrapper .hljs-selector-tag,.output_wrapper .hljs-deletion{color: rgb(248, 35, 117);}
.output_wrapper .hljs-variable,.output_wrapper .hljs-template-variable,.output_wrapper .hljs-link{color: rgb(98, 151, 85);}
.output_wrapper .hljs-comment,.output_wrapper .hljs-quote{color: rgb(128, 128, 128);}
.output_wrapper .hljs-meta{color: rgb(91, 218, 237);}
.output_wrapper .hljs-string,.output_wrapper .hljs-attribute,.output_wrapper .hljs-addition{color: rgb(238, 220, 112);}
.output_wrapper .hljs-attr,.output_wrapper .hljs-section,.output_wrapper .hljs-title,.output_wrapper .hljs-type{color: rgb(165, 218, 45);}
.output_wrapper .hljs-selector-class{color: rgb(165, 218, 45);}
.output_wrapper .hljs-emphasis{font-style: italic;}
.output_wrapper .hljs-strong{font-weight: bold;}
.output_wrapper p{margin: 1.5em 0px;}
.output_wrapper h1,.output_wrapper h2,.output_wrapper h3,.output_wrapper h4,.output_wrapper h5,.output_wrapper h6{margin: 1.5em 0px; font-weight: bold;}
.output_wrapper h1{font-size: 1.6em;}
.output_wrapper h2{font-size: 1.4em;}
.output_wrapper h3{font-size: 1.3em;}
.output_wrapper h4{font-size: 1.2em;}
.output_wrapper h5{font-size: 1em;}
.output_wrapper h6{font-size: 1em;}
.output_wrapper h3{border-bottom: 2px solid rgb(62, 62, 62); margin-bottom: 50px;}
.output_wrapper h3 span{display: inline-block; padding: 10px 0px;}
.output_wrapper h3 span::first-letter,.output_wrapper h3 .firstletter{color: rgb(255, 255, 255); padding: 10px 15px; margin-right: 20px; background: rgb(62, 62, 62);}
-->
原文:Unreal Engine 4 Tutorial for Beginners: Getting Started
作者:Tommy Tran
译者:Shuchang Liu
本篇教程将引导你安装Unreal Engine 4引擎,了解基本操作界面,并创建你的第一个游戏物体。
Unreal Engine 4引擎本质上是一个游戏开发工具集,能够胜任从2D手机游戏到3A主机游戏的制作,其中不乏方舟生存:进化,铁拳7,王国之心3等3A游戏。
新手很容易就能上手Unreal Engine 4引擎开发游戏。通过蓝图可视化脚本系统,你甚至无需编写任何代码就制作出游戏!配合简单易上手的操作界面,开发者能很快制作出可玩的游戏原型。
本篇教程主要帮助初学者了解上手Unreal Engine 4引擎,以下是本篇教程的关键知识点:
- 引擎安装
- 资源导入
- 创建材质
- 利用蓝图创建具有基本功能的物体
为了实际掌握这些知识点,我们会动手写个小例子:在游戏场景创建一个转台,旋转展示香蕉。
注意:本篇教程只是Unreal Engine 4系列教程的其中一篇:
安装Unreal Engine 4引擎
Unreal Engine 4引擎需要通过Epic Games 启动器来下载安装。直接前往官网,点击右上角的Get Unreal按钮。
你需要先创建一个账号,才能下载启动器。创建完账号后,根据操作系统下载对应的启动器。
下载安装并打开启动器,你会看到下面的窗口:
接着输入注册邮箱和密码,点击Sign In,会看到下面的窗口:
点击左上角的Install Engine,启动器会跳转到选择组件安装的界面。
注意:Epic Game一直在更新Unreal Engine 4引擎,所以你下载的引擎版本可能跟教程中的不一样。我刚开始写这篇教程,引擎版本就更新到了4.14.3!不过只要你的引擎版本在4.14以上,这篇教程的内容还是适用的。
安装界面的默认选项是Starter Content,Templates and Feature Packs和Engine Source。我建议你全部勾选,因为:
- Starter Content:资源包,你可以在项目里免费使用这些资源,其中包括模型,材质。你可以把这些资源用于制作游戏原型,或者用于最终成品里。
- Templates and Feature Packs:勾选该选项,会根据你选择的类型构建具备基本功能的模板项目。比如,勾选Side Scroller创建出来的模板项目,会有一个具备移动功能的角色以及固定视角的平面摄像机。
- Engine Source: Epic提供了引擎源码,意味着任何人都可以修改引擎源码。比如说你想给引擎编辑器添加自定义功能,可以通过修改源码做到这一点。
下拉列表,可以看到引擎支持多个平台。如果你不打算针对某些平台开发游戏,可以不用勾选。
选择完毕后,点击Install。当安装完毕,Library页签就会出现引擎信息。现在我们可以来创建项目了。
创建项目
点击Launch按钮打开项目浏览器,然后点击New Project页签。
点击Blueprint页签,你可以选择其中一种模版来创建项目。不过,我们打算从头实现教程例子,所以选择Blank创建空模板项目。
在底下,你可以看到一些额外设置。
简单讲解这些设置的作用:
- Target Hardware: 选择Mobile/Tablet会禁用掉一些后处理效果。在该设置下,鼠标输入会被自动识别成触控输入。我们把该选项设置成Desktop/Console。
- Graphic Target:选择Scalable 3D or 2D会禁用一些后处理特效。把该选项设置成Maximum Quality。
- Starter Content:你可以启用该选项来引入初始资源。简单起见,该选项设置成No Starter Content。
最后底下的部门用于设置项目存放位置,以及你的项目文件名。
你可以通过点击右侧的省略号图标修改项目存放位置。
项目名称指的并不是游戏名称,后续修改游戏名称,也无需修改项目名称。选择Name处的文本框,输入BananaTurntable。
最后,点击Create Project。
认识操作界面
一旦创建了项目,编辑器就会自动打开。整个编辑器由多个面板组成:
1.Content Browser: 该面板展示了所有项目的文件。使用该面板创建文件夹,存放项目文件。你可以使用搜索框或筛选列表搜索文件。
2.Modes:通过该面板可以选择地形工具和植被工具。默认打开的页签是放置工具,用于在关卡放置不同类型的物体比如光线和摄像机。
3.World Outliner:展示当前关卡的所有物体。你可以对物体进行分门别类管理,创建不同文件夹,将同类物体放在一起。
4.Details:该面板展示你所选中物体的详细属性。我们可以通过该面板编辑物体,编辑只会对当前物体实例生效。比如,场景里有两个球体,你修改了其中一个球体的大小,修改只对你选中的球体生效。
5.Toolbar:包含一系列不同方法,最常用的方法通常是Play。
6.Viewport:关卡场景窗口。你可以通过长按右键并移动鼠标旋转视角。长按右键并使用WASD键移动视角。
导入资源
作为一个转台却没有任何东西可展示有什么意思?下载香蕉模型。下载包里有两个文件:Banana_Model.fbx 和Banana_Texture.jpg。你当然也可以用别的模型来完成这个例子,但你都有一根屌炸天的香蕉了,完全不用多此一举。
你需要先导入香蕉模型,才可以在Unreal Engine引擎里使用。点击Content Browser的Import按钮。
在弹出的文件浏览器里,跳转到香蕉模型文件夹,选中两个文件后点击Open。
Unreal Engine引擎会弹出.fbx文件的导入选项面板。确保Import Materials是未勾选状态,因为我们要自己创建材质。其他设置可以不用管。
点击Import。现在Content Browser里就会出现这两个文件。
当做完前面的操作,这些资源还并没有真正保存进项目里。我们需要右键点击文件,选择Save。也通过点击面板的File\Save All保存所有导入资源。记得养成时常手动保存资源的习惯。
注意在Unreal Engine引擎里,模型称之为网格。所以现在我们有了个香蕉网格,是时候把它放进场景里了。
关卡中添加网格
关卡场景现在还是空空的,所以让我们把它丰富起来。
通过左键把Banana_Model从Content Browser拖拽到Viewport里。释放左键,网格就放置到关卡里了。
我们可以移动、旋转、缩放关卡里的物体,与之对应的快捷键是W,E,R。配合快捷键和鼠标,就可以这样调整香蕉网格了:
关于材质
如果你仔细观察香蕉,就会发现它不是黄色的!事实上,它看起来像已经过期发黑了。
为了赋予香蕉一些色彩和细节,你需要创建一个材质。
什么是材质?
材质决定了物体的视觉外观。基本上,材质会影响以下四个外观属性:
- 底色(Base Color):材质的基本色。用来决定物体的外观颜色。
- 金属度(Metallic):决定物体表面的金属质感。通常来说,纯金属的金属度值是最大的,而纺织品的金属度为0。
- 高光(Specular):控制非金属表面的光泽度。比如,陶瓷制品会有比较强的高光,而黏土则没有。
- 粗糙度(Roughness):如果物体表面的粗糙度越高,光泽度就越低。通常来说,岩石和木头表面的粗糙度就很高。
下面是三种不同材质的外观例子。它们有着相同的颜色,不同的外观属性。每种材质对应的属性都调成了最大值,而其他属性都设置为0。
创建材质
我们可以通过在Content Browser点击Add New按钮,弹出可创建资源的列表菜单。点击Material。
将材质命名为**Banana_Material **,并双击打开材质编辑菜单。
材质编辑器
材质编辑器由四个主要面板构成:
- 1. Graph:这个面板包含了你的所有节点和结果节点。通过长按右键和移动鼠标来移动,滑动滚轮来缩放面板。
- 2. Details:展示选中节点的详细属性。如果没有选中任何节点,面板会展示材质的详细属性。
- 3.Viewport:材质的预览界面。通过长按左键和移动鼠标来移动,滑动滚轮来缩放面板。
- 4. Palette:当前材质可用的节点列表。
什么是节点?
在开始制作材质前,你需要了解制作材质的基本元素:节点。
节点构成了材质的整体。材质可以拥有很多种类型的节点,各自具备不同功能。
节点拥有输入和输出,看起来像个带箭头的圆圈。左侧是输入,右侧是输出。
下面这个例子,用了个Multiply和Constant3Vector节点将贴图改成了黄色:
材质有一个特殊的结果节点,这个节点从材质创建一开始就存在,是材质的最后一个节点。这个节点怎么连线,会直接影响材质的最终呈现效果。
添加贴图
为了给模型添加颜色和细节,我们需要添加贴图。贴图就是一张2D图片。简单来讲,2D贴图被映射覆盖在3D模型上,从而赋予模型颜色和细节。
我们使用Banana_Texture.jpg来作为香蕉的贴图。TextureSample节点可以用于设置贴图。
在Palette面板搜索TextureSample。通过长按左键节点将其拖拽到图表区域。
选中**TextureSample **节点,在Details面板点击Texture属性栏右侧的下拉框。
下拉菜单会展示项目里的所有可用贴图。选中Banana_Texture。
为了在预览网格看到贴图,你需要将节点连线接入结果节点。左键长按TextureSample节点的白色输出引脚,将其拖拽到结果节点的Base Color输入引脚。
此时观察Viewport预览网格的贴图,通过长按左键拖拽就可以旋转网格,全方位观察它的细节。
点击Toolbar上的Apply按钮,就能更新材质设置。
使用材质
为了在香蕉网格应用材质,我们需要进一步手动操作。在Content Browser双击Banana_Model,会出现下面编辑器窗口:
观察Details面板的Materials选项,点击Element 0右侧的下拉框,并选择Banana_Material。
关闭窗口,回到主编辑器,观察Viewport,你能看到香蕉已经有了贴图。恭喜你,你已经具备一个关卡设计师的所需技能了!
注意:如果光线看起来太暗了,你可以通过在World Outliner面板点击Light Source,在Details面板修改Intensity为更大的值进行调整。
关于蓝图
虽然香蕉看起来不错,如果它能放在转台上展示会更不错。我们通过蓝图就可以实现这点。
简单化理解,一个蓝图代表一个“东西”。蓝图可以赋予“东西”一些自定义行为。“东西”可以是个实物(比如转台),或是抽象概念,比如血条系统。
想要一台能跑起来的车?做个蓝图吧。一头飞猪?蓝图。炸上天的厨房?还是蓝图。
类似于材质系统,蓝图也是个节点系统。这意味着你所需要做的是创建一些节点并做做连线,完全不需要编写代码!
注意:如果你更愿意写代码,你可以使用C++编写。
虽然蓝图便捷易用,它的运行效率不如C++代码。所以,如果你要实现一些大量运算的逻辑,比如复杂算法,还是应该用C++。
不过即使你更倾向于用C++,在一些场景下使用蓝图是个好主意。以下是使用蓝图的好处:
- 通常来讲,蓝图开发效率优于C++。
- 直观清晰。你可以将节点划分成不同区域,比如不同的方法和图表。
- 如果你跟非开发人员协同合作,得益于蓝图的可视、直观,双方修改蓝图逻辑会更加简单。
尽量尝试用蓝图创建逻辑,当有部分逻辑需要提升运行效率时,再将其转换成C++代码。
创建蓝图
在Content Browser点击Add New按钮,从下拉列表中点击Blueprint Class。
紧接着会出现提示框让你选择新建蓝图类所要继承的父类。蓝图类会继承父类的所有变量,函数及组件。让我们花一点时间看每个类是做什么的。
注意:因为Pawn和Character类也能够被放置、生成,它们也同属于Actor。
因为转台只需要静止放置在一个固定点上,所以Actor类是最合适的。选择Actor并将其命名为Banana_Blueprint。
最后,双击Banana_Blueprint,出现以下面板时点击Open Full Blueprint Editor:
蓝图编辑器
首先,确保编辑器界面页签选中Event Graph。
蓝图编辑器由以下五个面板组成:
1.Components:包含当前蓝图已用组件列表。
2.My Blueprint:该面板主要用于管理你的图表,方法和变量。
3.Details:展示选中项的详细参数。
4.Graph:化腐朽为神奇的部分。所有的节点逻辑都在这里。通过长按右键和移动鼠标来移动,滑动滚轮来缩放面板。
5.Viewport:所有包含可视元素的组件都会显示在这里。操作方法类同主编辑器的Viewport界面。
创建转台
转台由两部分组成:底座和展示物体。我们可以通过组件创建这两者。
什么是组件?
如果一个蓝图是一辆车,那组件就是这辆车的零部件。车门,方向盘和引擎都是组件。
然而,组件的概念也不限于实际物体。
比如,为了开动这辆车,你还会给它加上运动组件,甚至还能通过添加飞行组件使得车子飞起来。
添加组件
首先,我们先把页签切换到Viewport,把界面切到场景展示。看起来是这样的:
注意:当引擎处于运行模式时,DefaultSceneRoot组件是看不到的,它只会在编辑模式下展示。
转台有两个组件:
- 圆柱体(Cylinder):一个简单的白色圆柱体作为底层,用于盛放香蕉。
- 静态网格(Static Mesh):这个组件用于展示香蕉网格。
为了添加组件,在Components面板点击Add Component并选择Cylinder。
把底座调矮点,视觉效果看起来会更好点。按下R键激活缩放操作杆,并滑动对应轴调整底座高度。
接着来添加网格。在Components面板左键点击空白区域,取消选中Cylinder组件。这样就保证后面新加的组件不会放在Cylinder组件下。
注意:如果你不这样,后面新加的组件就会放在Cylinder组件下,这意味着这个组件会继承Cylinder组件的缩放值。由于你缩放过圆柱体,这样做的结果就是新加的香蕉模型也会跟着一起缩放。
接着,点击Add Component并选择Static Mesh。
为了显示香蕉的样子,选择Static Mesh组件并点击Details页签。点击Static Mesh选项右侧的下拉框,选择Banana_Model。
如果香蕉的位置不太对,就按下W键激活移动操作杆,调整香蕉的位置。
关于蓝图节点
是时候让转台转起来了。这里就涉及到蓝图节点的使用。
不同于它的表亲材质节点,蓝图节点有一种特殊引脚叫执行引脚。节点左侧是输入引脚,右侧是输出引脚。所有的节点都至少会有输入/输出引脚的其中一种。
如果一个节点有输入引脚,它一定要有个对应的接入才能被执行。如果它的输入引脚没有连接,它的后续节点也不可能被执行。
这里是个例子:
节点A和节点B因为其有连接,所以能够执行。由于节点C输入引脚没有连接,节点C和节点D都不会执行。
旋转转台
在我们动手前,先看看Components面板。你能够看到Cylinder和Static Mesh组件是有缩进的,DefaultSceneRoot则没有。这样因为前两者是DefaultSceneRoot节点的子节点。
如果移动、旋转、缩放根节点,子节点也会一起影响。利用这个特性,你就能一并控制Cylinder和Static Mesh了。
创建节点
为了编写逻辑,我们把页签切换到Event Graph.
旋转物体非常简单,只需要创建一个节点就能完成。在图表界面空白处右键弹出可用节点菜单,搜索AddLocalRotation节点。由于我们想要一并旋转底座和香蕉,直接旋转根组件节点即可。因此选择AddLocalRotation (DefaultSceneRoot)。
注意:如果看不到对应节点,请反选右上角的Context Sensitive选项。
你的图表现在有了一个新的名为AddLocalRotation的节点了。它的Target输入会自动连接你所选择的组件。
将Delta Rotation的z值修改为1.0,这样蓝图就会让目标围绕Z轴进行旋转。值越大,转台旋转越快。
为了持续旋转转台,你需要每帧调用AddLocalRotation。为了实现这点,需要使用上Event Tick节点。它应该默认就在你的图表里。如果没有,就仿照刚才的操作创建节点。
拖拽Event Tick节点的输出引脚连接AddLocalRotation节点的输入引脚。
注意:在这个例子中,转台旋转速度取决于帧率。这意味着转台在低配机器上会旋转得更慢,反之亦然。这对于教程来说没什么大问题,这样处理会比较简单,我会在之后的教程里教你解决这个问题。
最后,点击Toolbar的Compile按钮更新蓝图修改,并关闭编辑器。
在关卡里添加蓝图
在添加蓝图前,在主编辑器的Viewport窗口删除之前放置的香蕉模型。选中香蕉模型,点击Eidt\Delete或者按下Delete键进行删除。
添加蓝图的步骤功能跟之前添加网格的步骤是一样的。左键拖拽蓝图文件,将其放置到Viewport窗口。
在Toolbar上点击Play按钮,就可以看到最终成果了!
注意:如果你没有删除掉关卡的香蕉模型,你可以会看到重建光线的警告提示。删掉模型,就能去掉警告。
后续学习
你可以在这里下载教程项目。
本篇教程所学习的内容只是Unreal Engine 4引擎的冰山一角。如果你还想继续学习Unreal Engine 4引擎,点击下篇教程,我会进一步讲解Unreal Engine 4引擎的蓝图系统。
原文地址:https://www.cnblogs.com/leoin2012/p/11713349.html