.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的动画系统做的很优秀,能使开发者在短时间内完成角色动画。

在本篇教程中,你将能学会:

  • 导入带有骨骼的网格资源
  • 导入动画资源
  • 创建动画蓝图,实现不同动画的切换
  • 实现动画切换的平滑过渡

请注意,本篇教程涉及蓝图部分内容。如果你需要复习有关内容,请查看蓝图教程

起步入门

下载示例项目并解压。在文件根目录,可以看到名为Animation Assets的文件夹。这个文件夹里有我们需要引入的角色和动画资源。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

进入项目文件夹,双击SkywardMuffin.uproject打开项目。

按下Play可以运行游戏。游戏玩法是尽可能踩着天空云朵往上跳跃,同时避免掉落地面,点击左键跳跃地面。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

我们要用一只可爱的蘑菇小人来替换游戏里的红色球形:

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

蘑菇小人带有一套骨架用于动画表演。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

什么是骨架?

在3D软件里,一套骨架是一组彼此连接的关节点集合。比如下图的每个球体都是一个关节。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

通过操控关节,角色可以摆出了不同的姿势。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

当角色从一个姿势切换到另一个姿势,动画就产生了。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

当角色反复切换前后两个姿势,我们可以看到这样的动画:

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

在Unreal中,任何带有骨架的网格称之为骨架网格。首先我们先导入蘑菇小人的骨架网格。

导入骨架网格

在Content Browser打开Characters\Muffin,点击Import,在选择面板打开SkywardMuffinStarter\Animation Assets目录,选择SK_Muffin.fbx并点击Open

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

在导入窗口中,取消勾选Mesh设置的Create Physics Asset选项。Physics Asset是Unreal用于创建ragdoll(布娃娃)效果的组件,由于教程并不需要这种效果,这里就不勾选了。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

由于项目已经导入了蘑菇的材质和贴图,所以不用再次引入了。取消勾选Import MaterialsImport Textures选项。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

其他设置保持默认不变,点击Import,Unreal将创建以下资源:

  • SK_Muffin:骨架网格资源,基本上这是一个链接上骨架资源的网格资源。
  • SK_Muffin_Skeleton:骨架资源,带有关节列表及其层级信息。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

现在你已经导入了蘑菇资源,接着看怎么使用它们。

使用骨架网格

在我们使用骨架网格之前,需要先给它加上材质,否则它只是个灰色模型。双击SK_Muffin打开它。

查看Asset Details面板Material Slots部分设置,将材质指定为M_Muffin然后关闭SK_Muffin

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

现在需要将SK_Muffin设置为玩家角色,在Content Browser 双击BP_Muffin.

在Components面板选中Mesh (Inherited)组件,在Details面板的Mesh设置里,将Skeletal Mesh属性设置为SK_Muffin

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

点击Compile并回到主编辑器。按下Play用蘑菇小人体验游戏!

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

游戏感觉好多了!下一步要做的是给蘑菇小人加上一些动画表现,让它变得活灵活现。

导入动画

在Content Browser点击Import,在选择面板打开SkywardMuffinStarter\Animation Assets目录,选择以下文件:

  • SK_Muffin_Death.fbx
  • SK_Muffin_Fall.fbx
  • SK_Muffin_Idle.fbx
  • SK_Muffin_Jump.fbx
  • SK_Muffin_Walk.fbx

选中并点击Open

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

在导入窗口中,取消勾选Mesh设置的Import Mesh选项,避免重复导入骨架网格。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

接着,确保Skeleton属性设置成SK_Muffin_Skeleton,这个设置指定了动画会应用在哪个骨架上。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

最后,点击Import All,就成功导入刚才选中的那些动画了。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

现在,我们已经有了所有动画资源了,还需要找到方法播放它们。我们可以通过动画蓝图(Animation Blueprint)来完成这件事。

创建动画蓝图

动画蓝图很像普通的蓝图。然而,它还有一个专门用于完成动画任务的图表。

首先在Content Broswer点击Add New按钮,选择Animation\Animation Blueprint创建动画蓝图。

在弹出窗口里,找到Target Skeleton属性并选择SK_Muffin_Skeleton,然后点击OK按钮创建动画蓝图。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

将新建资源命名为ABP_Muffin。接着双击资源打开动画蓝图编辑器。

动画蓝图编辑器

动画蓝图编辑器跟蓝图编辑器非常相像,不过额外多了4个面板:

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

  1. Anim Graph:这个图表专门用于处理动画,在这里可以播放你的动画
  2. Preview Scene Settings:这个面板用于调整预览场景的参数
  3. Anim Preview Editor:你所创建的变量会展示在这里,利用这个面板可以实时看到动画的变量值
  4. Asset Browser:这个面板展示了一组当前可用的动画列表

为了确定每个动画的播放时机,我们可以使用状态机(State Machine)

什么是状态机?

状态机本质是一组状态和规则的集合。在本篇教程中为了方便理解,你可以认为每个状态都是一个动画。

状态机在任一时刻都只能处于一种状态下,要从一种状态切换到另一种状态,必须满足其切换条件。

下图是一个简单的状态机例子,它展示了跳跃状态,其与其他状态切换的规则条件。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

状态切换还可以是双向的。如下图所示,跳跃和下落状态可以互相切换。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

如果没有这种双向关系,角色就没办法实现空中二段跳了,因为角色只有在地面站立状态下才能切换到跳跃状态。

关于状态机简单了解到这里就足够了。下面来动手创建一个状态机。

创建状态机

确保界面处于Anim Graph,右键点击空白区域,从弹出菜单中选择Add New State Machine

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

这样图表上会多出一个状态机节点,将其重命名为Locomotion。随后,连接Locomotion状态机与Final Animation Pose节点。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

现在,Locomotion状态机就能直接影响蘑菇小人的动作表现了。

接着,双击打开Locomotion状态机,可以看到状态机内部有个Entry节点。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

任何与之相连的节点就是默认状态。在本篇教程中,默认状态就是站立动画。在图表空白处右键点击,从弹出菜单中选择Add State,将其重命名为Idle

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

现在,连接Entry节点与Idle状态。拖拽Entry引脚至Idle状态的灰色区域,释放鼠标进行连接。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

当我们用弹出菜单创建状态后,它其实还没有关联任何动画,下面来做下动画关联。

动画关联状态

双击打开Idle状态。

为了关联动画,在Asset Browser 拖拽SK_Muffin_Idle动画至图表的空白处添加动画。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

接着,连接Play SK_Muffin_Idle节点与Final Animation Pose节点。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

为了使用动画蓝图,我们还需要更新BP_Muffin

使用动画蓝图

点击Compile并切换到BP_Muffin

在Components面板选中Mesh (Inherited)组件,在Details面板的Animation设置,将Animation Mode改成Use Animation Blueprint,然后Anim Class改成ABP_Muffin

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

现在,骨架网格就会使用ABP_Muffin作为动画蓝图了。

点击Compile并关闭BP_Muffin。在主界面点击Play运行游戏测试动画蓝图。由于Idle就是默认状态,蘑菇会自动播放站立动作。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

接下来,我们将会创建跳跃和掉落状态。

创建跳跃和掉落状态

回到ABP_Muffin并切换到Locomotion状态机图表,我们可以通过点击图表上方的Locomotion导航快速跳转过去。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

与其创建状态再关联上动画,不如直接创建关联好动画的状态,我们改用另一种方法来创建跳跃状态。

在Asset Browser中,拖拽SK_Muffin_Jump动画至图表空白处,就能创建带有动画的状态。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

将其重命名为Jump

重复以上步骤,将SK_Muffin_Fall生成的状态重命名为Fall

现在我们就有三个状态了:IdleJumpFall

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

接着,我们要连接这些状态。我们可以通过拖拽起始状态的灰色区域目标状态灰色区域来创建连接。

创建连接状态如下:

  • IdleJump
  • JumpFall
  • FallJump
  • FallIdle

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

现在有了状态切换,还需要确定什么情况下会发生状态切换,这就要使用过渡规则(Transition Rule)了。

过渡规则

下面图标表示过渡规则:

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

每个过渡规则都有一个带有boolean输入的Result节点。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

当输入为true时,就会发生状态切换。

接着,我们要创建变量用于表明玩家角色处于跳跃还是下落状态,过渡规则里会用到这些变量。

检查玩家处于跳跃还是下落

创建两个boolean变量命名为IsJumpingIsFalling

首先,我们需要设置IsJumping的值。切换到Event Graph并找到Event Blueprint Update Animation节点,这个节点看起来类似于Event Tick节点。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

为了判断玩家是否处于跳跃状态,如下图设置图表:

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

这样就能确认玩家Z轴的速度是否大于0。如果是,说明玩家处于跳跃状态,将IsJumping变量设置为true

要判断玩家是否处于下落状态,我们就要做反之相反的检查设置。添加如下高亮节点:

现在,当玩家的Z轴速度小于0时,IsFalling就会设置为true

是时候将这些变量应用到过渡规则里去了。

定义过渡规则

首先,你需要定义Idle到Jump的过渡规则。切换到Locomotion状态机。双击打开Idle到Jump过渡规则。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

创建IsJumping节点并连接Result节点。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

现在,当IsJumpingtrue时,Idle状态就能切换到Jump状态上。

重复以上步骤来设置Jump到FallFall到Jump过渡规则,分别使用如下变量:

  • Jump到Fall: IsFalling
  • Fall到Jump: IsJumping

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

现在,JumpFall状态就能正常互相切换了。

还剩下一个过渡规则没有定义。我们接着打开Fall到Idle过渡规则。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

要过渡到Idle状态,玩家肯定不能处于跳跃或掉落状态。要实现这样的判断检查,我们可以使用NOR节点。还有当它的输入都为false时,它的输出才为true

创建NOR节点,并连接IsJumpingIsFalling节点。随后,连接NOR节点与Result节点。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

现在,当IsJumpingIsFalling节点都为false时,Fall状态就能切换到Idle状态。

点击Compile并回到主编辑器。按下Play来测试动画转换。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

现在,当蘑菇小人在地面移动时只会滑行,这是因为我们还没用上步行动画!

除了像上面那样为步行创建一个新状态外,我们还可以使用混合空间(Blend Space)

什么是混合空间?

混合空间是一种动画资源,它基于输入把两种不同的动画插值混合在一起。在本篇教程中,我们将以玩家的速度作为输入。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

混合空间有助于简化我们的状态机。下图是如果不使用混合空间的情况下,Locomotion状态机的样子:

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

使用了混合空间,我们只需要替换Idle动画即可。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

了解完混合空间的魔力,让我们来创建试试。

创建混合空间

在Content Browser里点击Add New,从弹出菜单中选中Animation\Blend Space 1D

从弹出窗口中,选择SK_Muffin_Skeleton

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

将新建资源命名为BS_IdleWalk双击打开动画编辑器。

当我们打开混合空间,可以看到如下图的面板。这就是混合空间编辑器,我们要在这里添加动画。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

让我们试试往上面添加些动画。

混合空间添加动画

首先,我们需要先修改变量(输入)轴的名称,在Asset Details面板找到Axis Settings设置,将Horizontal Axis\Name字段改成Speed

现在,我们可以开始添加动画了。在Asset Browser 拖拽SK_Muffin_Idle动画至混合空间网格的左侧,让动画放置在0.0数值处。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

随后,将SK_Muffin_Walk动画添加到100.0数值处。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

现在,混合空间会根据输入值混合站立与步行动画。
如果输入为0,只会播放站立动画。如果输入是100,会播放步行动画。其他的中间值就会播放两者插值混合后的动画。

现在就让我们来使用混合空间吧。

使用混合空间

关闭BS_IdleWalk并打开ABP_Muffin。切换到Locomotion状态机并打开Idle状态。

首先,删除Play SK_Muffin_Idle节点。

接着,通过拖拽添加BS_IdleWalk。随后,连接BS_IdleWalk节点与Final Animation Pose节点。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

现在,BS_IdleWalk被设置为默认状态,会自动播放了。然而我们能发现,由于Speed输入一直为0,它只会播放站立动画。

要解决这个问题,我们需要给它提供玩家速度。

获取玩家速度

创建名为Speedfloat变量,随着切换到Event Graph。

Sequence节点添加新引脚并添加下图高亮节点:

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

这样设置就可以恒定将玩家速度设置给Speed变量了。

切换回Idle状态图表,将Speed变量与BS_IdleWalk节点的Speed输入相连。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

现在,BS_IdleWalk就能在混合表现站立和步行动画了。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

还剩下最后一个动画没用到:死亡动画!

使用死亡动画

在游戏里,很显然蘑菇小人只有在站立状态(处于地面)才能切换到死亡状态。然而,设想下如果它能在任何状态下切换到死亡状态,我们的第一想法就是创建Death状态并将其与其他所有状态相连。这当然也是一种选择,但它将很快导致图表变成一团乱麻。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

另一种解决方案是使用Blend Poses by bool节点。这个节点能够根据boolean值输入决定两种动画的切换。

再我们创建节点前,先创建一个可以保存玩家死亡状态的变量。

检查玩家是否死亡

回到ABP_Muffin并创建名为IsDeadboolean变量。随后,切换到Event Graph。

Sequence节点添加新引脚并添加如下图高亮节点:

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

这样设置就可以恒定将玩家死亡状态设置给IsDead变量了。

接着,我们再来使用Blend Poses by bool节点。

使用Blend Poses by bool节点

切换到Anim Graph并添加SK_Muffin_Death动画,选中动画,并在Details面板取消勾选Loop Animation属性。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

这样确保死亡动画只会播放一次。

接着,创建Blend Poses by bool节点。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

选中Blend Poses by bool节点的情况下,在Details面板的Option设置部分勾选Reset Child on Activation属性。

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

由于死亡动画只会播放一次,这个选项可以确保动画每次播放前会先自动重置到第一帧。

最后,添加IsDead变量,如下图连接图表:

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

现在,当IsDeadtrue时,会播放死亡动画。当IsDeadfalse时,会播放Locomotion状态机的当前动画。

点击Compile并关闭ABP_Muffin。按下Play运行游戏试试死亡动画吧!

Unreal Engine 4 系列教程 Part 6:动画教程-LMLPHP

后续学习

你可以在这里下载完整项目。

这个游戏看起来打磨得更好了,对吧?虽然你已经可以根据所学实现一些东西了,然而还有很多知识点没有涉及!推荐你阅读Unreal引擎文档关于骨架动画系统部分内容,了解其他类型动画资源和具体用法。

如果你还想继续学习引擎其他内容,点击下篇教程,将讲解如何在游戏中使用音乐音效。

05-11 16:53