<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>崎径 其镜</title>
  
  <subtitle>求学道路上的行车记录仪</subtitle>
  <link href="/atom.xml" rel="self"/>
  
  <link href="http://www.z16388.top/"/>
  <updated>2026-04-18T12:45:50.159Z</updated>
  <id>http://www.z16388.top/</id>
  
  <author>
    <name>Anqi Zhao</name>
    
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title>从零配置 VS Code C++ 环境</title>
    <link href="http://www.z16388.top/2026/04/12/cpp-vscode/"/>
    <id>http://www.z16388.top/2026/04/12/cpp-vscode/</id>
    <published>2026-04-12T22:32:49.000Z</published>
    <updated>2026-04-18T12:45:50.159Z</updated>
    
    <content type="html"><![CDATA[<p>本文档记录在 Windows 系统上从零配置 VS Code C++ 开发环境的全过程，包括编译、调试和运行。</p><h2 id="前置条件"><a href="#前置条件" class="headerlink" title="前置条件"></a>前置条件</h2><ul><li>Windows 10/11 系统</li><li>已安装 VS Code（<a href="https://code.visualstudio.com/" target="_blank" rel="noopener">下载链接</a>）</li></ul><h2 id="需要的工具"><a href="#需要的工具" class="headerlink" title="需要的工具"></a>需要的工具</h2><h3 id="1-MSYS2"><a href="#1-MSYS2" class="headerlink" title="1. MSYS2"></a>1. MSYS2</h3><p>MSYS2 是一个 Windows 下的 Linux-like 环境，提供 g++ 编译器和 gdb 调试器。</p><ul><li><strong>下载链接</strong>：<a href="https://www.msys2.org/" target="_blank" rel="noopener">https://www.msys2.org/</a></li><li><strong>安装路径</strong>：推荐安装到 <code>C:\msys64</code>（默认路径）</li></ul><h3 id="2-VS-Code-扩展"><a href="#2-VS-Code-扩展" class="headerlink" title="2. VS Code 扩展"></a>2. VS Code 扩展</h3><ul><li><strong>C/C++ 扩展</strong>：由 Microsoft 提供，支持 IntelliSense、调试等功能<ul><li>在 VS Code 中搜索安装：<code>ms-vscode.cpptools</code></li></ul></li></ul><h2 id="安装步骤"><a href="#安装步骤" class="headerlink" title="安装步骤"></a>安装步骤</h2><h3 id="步骤-1：安装-MSYS2"><a href="#步骤-1：安装-MSYS2" class="headerlink" title="步骤 1：安装 MSYS2"></a>步骤 1：安装 MSYS2</h3><ol><li>下载 MSYS2 安装包并运行安装程序</li><li>选择安装路径为 <code>C:\msys64</code></li><li>安装完成后，运行 MSYS2 UCRT64 终端（从开始菜单启动）</li></ol><h3 id="步骤-2：更新-MSYS2-并安装工具"><a href="#步骤-2：更新-MSYS2-并安装工具" class="headerlink" title="步骤 2：更新 MSYS2 并安装工具"></a>步骤 2：更新 MSYS2 并安装工具</h3><p>在 MSYS2 UCRT64 终端中执行以下命令：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 更新包数据库</span></span><br><span class="line">pacman -Syu</span><br><span class="line"></span><br><span class="line"><span class="comment"># 安装 g++ 编译器和 gdb 调试器</span></span><br><span class="line">pacman -S mingw-w64-ucrt-x86_64-gcc mingw-w64-ucrt-x86_64-gdb</span><br></pre></td></tr></table></figure><h3 id="步骤-3：安装-VS-Code-扩展"><a href="#步骤-3：安装-VS-Code-扩展" class="headerlink" title="步骤 3：安装 VS Code 扩展"></a>步骤 3：安装 VS Code 扩展</h3><ol><li>打开 VS Code</li><li>按 <code>Ctrl+Shift+X</code> 打开扩展面板</li><li>搜索 <code>C/C++</code> 并安装 Microsoft 的 C/C++ 扩展</li></ol><h2 id="VS-Code-配置"><a href="#VS-Code-配置" class="headerlink" title="VS Code 配置"></a>VS Code 配置</h2><p>在你的 C++ 项目根目录（例如 <code>C:\Dev\leetcode</code>）创建 <code>.vscode</code> 文件夹，并添加以下配置文件：</p><h3 id="1-c-cpp-properties-json"><a href="#1-c-cpp-properties-json" class="headerlink" title="1. c_cpp_properties.json"></a>1. c_cpp_properties.json</h3><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">    <span class="attr">"configurations"</span>: [</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="attr">"name"</span>: <span class="string">"windows-gcc-x64"</span>,</span><br><span class="line">            <span class="attr">"includePath"</span>: [</span><br><span class="line">                <span class="string">"$&#123;workspaceFolder&#125;/**"</span></span><br><span class="line">            ],</span><br><span class="line">            <span class="attr">"compilerPath"</span>: <span class="string">"C:\\msys64\\ucrt64\\bin\\gcc"</span>,</span><br><span class="line">            <span class="attr">"cStandard"</span>: <span class="string">"$&#123;default&#125;"</span>,</span><br><span class="line">            <span class="attr">"cppStandard"</span>: <span class="string">"$&#123;default&#125;"</span>,</span><br><span class="line">            <span class="attr">"intelliSenseMode"</span>: <span class="string">"windows-gcc-x64"</span>,</span><br><span class="line">            <span class="attr">"compilerArgs"</span>: [</span><br><span class="line">                <span class="string">""</span></span><br><span class="line">            ]</span><br><span class="line">        &#125;</span><br><span class="line">    ],</span><br><span class="line">    <span class="attr">"version"</span>: <span class="number">4</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="2-settings-json"><a href="#2-settings-json" class="headerlink" title="2. settings.json"></a>2. settings.json</h3><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="attr">"C_Cpp.default.compilerPath"</span>: <span class="string">"c:\\msys64\\ucrt64\\bin\\gcc.exe"</span>,</span><br><span class="line">  <span class="attr">"C_Cpp_Runner.cCompilerPath"</span>: <span class="string">"gcc"</span>,</span><br><span class="line">  <span class="attr">"C_Cpp_Runner.cppCompilerPath"</span>: <span class="string">"g++"</span>,</span><br><span class="line">  <span class="attr">"C_Cpp_Runner.debuggerPath"</span>: <span class="string">"gdb"</span>,</span><br><span class="line">  <span class="attr">"C_Cpp_Runner.cStandard"</span>: <span class="string">""</span>,</span><br><span class="line">  <span class="attr">"C_Cpp_Runner.cppStandard"</span>: <span class="string">""</span>,</span><br><span class="line">  <span class="attr">"C_Cpp_Runner.msvcBatchPath"</span>: <span class="string">"C:/Program Files/Microsoft Visual Studio/VR_NR/Community/VC/Auxiliary/Build/vcvarsall.bat"</span>,</span><br><span class="line">  <span class="attr">"C_Cpp_Runner.useMsvc"</span>: <span class="literal">false</span>,</span><br><span class="line">  <span class="attr">"C_Cpp_Runner.warnings"</span>: [</span><br><span class="line">    <span class="string">"-Wall"</span>,</span><br><span class="line">    <span class="string">"-Wextra"</span>,</span><br><span class="line">    <span class="string">"-Wpedantic"</span>,</span><br><span class="line">    <span class="string">"-Wshadow"</span>,</span><br><span class="line">    <span class="string">"-Wformat=2"</span>,</span><br><span class="line">    <span class="string">"-Wcast-align"</span>,</span><br><span class="line">    <span class="string">"-Wconversion"</span>,</span><br><span class="line">    <span class="string">"-Wsign-conversion"</span>,</span><br><span class="line">    <span class="string">"-Wnull-dereference"</span></span><br><span class="line">  ],</span><br><span class="line">  <span class="attr">"C_Cpp_Runner.msvcWarnings"</span>: [</span><br><span class="line">    <span class="string">"/W4"</span>,</span><br><span class="line">    <span class="string">"/permissive-"</span>,</span><br><span class="line">    <span class="string">"/w14242"</span>,</span><br><span class="line">    <span class="string">"/w14287"</span>,</span><br><span class="line">    <span class="string">"/w14296"</span>,</span><br><span class="line">    <span class="string">"/w14311"</span>,</span><br><span class="line">    <span class="string">"/w14826"</span>,</span><br><span class="line">    <span class="string">"/w44062"</span>,</span><br><span class="line">    <span class="string">"/w44242"</span>,</span><br><span class="line">    <span class="string">"/w14905"</span>,</span><br><span class="line">    <span class="string">"/w14906"</span>,</span><br><span class="line">    <span class="string">"/w14263"</span>,</span><br><span class="line">    <span class="string">"/w44265"</span>,</span><br><span class="line">    <span class="string">"/w14928"</span></span><br><span class="line">  ],</span><br><span class="line">  <span class="attr">"C_Cpp_Runner.enableWarnings"</span>: <span class="literal">true</span>,</span><br><span class="line">  <span class="attr">"C_Cpp_Runner.warningsAsError"</span>: <span class="literal">false</span>,</span><br><span class="line">  <span class="attr">"C_Cpp_Runner.compilerArgs"</span>: [],</span><br><span class="line">  <span class="attr">"C_Cpp_Runner.linkerArgs"</span>: [],</span><br><span class="line">  <span class="attr">"C_Cpp_Runner.includePaths"</span>: [],</span><br><span class="line">  <span class="attr">"C_Cpp_Runner.includeSearch"</span>: [</span><br><span class="line">    <span class="string">"*"</span>,</span><br><span class="line">    <span class="string">"**/*"</span></span><br><span class="line">  ],</span><br><span class="line">  <span class="attr">"C_Cpp_Runner.excludeSearch"</span>: [</span><br><span class="line">    <span class="string">"**/build"</span>,</span><br><span class="line">    <span class="string">"**/build/**"</span>,</span><br><span class="line">    <span class="string">"**/.*"</span>,</span><br><span class="line">    <span class="string">"**/.*/**"</span>,</span><br><span class="line">    <span class="string">"**/.vscode"</span>,</span><br><span class="line">    <span class="string">"**/.vscode/**"</span></span><br><span class="line">  ],</span><br><span class="line">  <span class="attr">"C_Cpp_Runner.useAddressSanitizer"</span>: <span class="literal">false</span>,</span><br><span class="line">  <span class="attr">"C_Cpp_Runner.useUndefinedSanitizer"</span>: <span class="literal">false</span>,</span><br><span class="line">  <span class="attr">"C_Cpp_Runner.useLeakSanitizer"</span>: <span class="literal">false</span>,</span><br><span class="line">  <span class="attr">"C_Cpp_Runner.showCompilationTime"</span>: <span class="literal">false</span>,</span><br><span class="line">  <span class="attr">"C_Cpp_Runner.useLinkTimeOptimization"</span>: <span class="literal">false</span>,</span><br><span class="line">  <span class="attr">"C_Cpp_Runner.msvcSecureNoWarnings"</span>: <span class="literal">false</span>,</span><br><span class="line">  <span class="attr">"terminal.external.windowsExec"</span>: <span class="string">"C:\\Windows\\System32\\cmd.exe"</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="3-tasks-json"><a href="#3-tasks-json" class="headerlink" title="3. tasks.json"></a>3. tasks.json</h3><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">    <span class="attr">"version"</span>: <span class="string">"2.0.0"</span>,</span><br><span class="line">    <span class="attr">"tasks"</span>: [</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="attr">"type"</span>: <span class="string">"cppbuild"</span>,</span><br><span class="line">            <span class="attr">"label"</span>: <span class="string">"C/C++: g++.exe build active file"</span>,</span><br><span class="line">            <span class="attr">"command"</span>: <span class="string">"C:\\msys64\\ucrt64\\bin\\g++.exe"</span>,</span><br><span class="line">            <span class="attr">"args"</span>: [</span><br><span class="line">                <span class="string">"-fdiagnostics-color=always"</span>,</span><br><span class="line">                <span class="string">"-g"</span>,</span><br><span class="line">                <span class="string">"$&#123;file&#125;"</span>,</span><br><span class="line">                <span class="string">"-o"</span>,</span><br><span class="line">                <span class="string">"$&#123;workspaceFolder&#125;\\build\\Debug\\outDebug.exe"</span></span><br><span class="line">            ],</span><br><span class="line">            <span class="attr">"options"</span>: &#123;</span><br><span class="line">                <span class="attr">"cwd"</span>: <span class="string">"$&#123;workspaceFolder&#125;"</span></span><br><span class="line">            &#125;,</span><br><span class="line">            <span class="attr">"problemMatcher"</span>: [</span><br><span class="line">                <span class="string">"$gcc"</span></span><br><span class="line">            ],</span><br><span class="line">            <span class="attr">"group"</span>: &#123;</span><br><span class="line">                <span class="attr">"kind"</span>: <span class="string">"build"</span>,</span><br><span class="line">                <span class="attr">"isDefault"</span>: <span class="literal">true</span></span><br><span class="line">            &#125;,</span><br><span class="line">            <span class="attr">"detail"</span>: <span class="string">"Compile current C++ file to build/Debug/outDebug.exe"</span></span><br><span class="line">        &#125;,</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="attr">"type"</span>: <span class="string">"shell"</span>,</span><br><span class="line">            <span class="attr">"label"</span>: <span class="string">"Run C++ Program"</span>,</span><br><span class="line">            <span class="attr">"command"</span>: <span class="string">"cmd.exe"</span>,</span><br><span class="line">            <span class="attr">"args"</span>: [</span><br><span class="line">                <span class="string">"/c"</span>,</span><br><span class="line">                <span class="string">"start \"\" cmd.exe /k \"$&#123;workspaceFolder&#125;\\build\\Debug\\outDebug.exe\""</span></span><br><span class="line">            ],</span><br><span class="line">            <span class="attr">"dependsOn"</span>: [</span><br><span class="line">                <span class="string">"C/C++: g++.exe build active file"</span></span><br><span class="line">            ],</span><br><span class="line">            <span class="attr">"options"</span>: &#123;</span><br><span class="line">                <span class="attr">"shell"</span>: &#123;</span><br><span class="line">                    <span class="attr">"executable"</span>: <span class="string">"C:\\Windows\\System32\\cmd.exe"</span></span><br><span class="line">                &#125;</span><br><span class="line">            &#125;,</span><br><span class="line">            <span class="attr">"group"</span>: &#123;</span><br><span class="line">                <span class="attr">"kind"</span>: <span class="string">"test"</span>,</span><br><span class="line">                <span class="attr">"isDefault"</span>: <span class="literal">true</span></span><br><span class="line">            &#125;,</span><br><span class="line">            <span class="attr">"presentation"</span>: &#123;</span><br><span class="line">                <span class="attr">"echo"</span>: <span class="literal">true</span>,</span><br><span class="line">                <span class="attr">"reveal"</span>: <span class="string">"always"</span>,</span><br><span class="line">                <span class="attr">"focus"</span>: <span class="literal">true</span>,</span><br><span class="line">                <span class="attr">"panel"</span>: <span class="string">"shared"</span></span><br><span class="line">            &#125;,</span><br><span class="line">            <span class="attr">"problemMatcher"</span>: []</span><br><span class="line">        &#125;</span><br><span class="line">    ]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="4-launch-json"><a href="#4-launch-json" class="headerlink" title="4. launch.json"></a>4. launch.json</h3><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="attr">"version"</span>: <span class="string">"0.2.0"</span>,</span><br><span class="line">  <span class="attr">"configurations"</span>: [</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="attr">"name"</span>: <span class="string">"C/C++ Runner: Debug Session"</span>,</span><br><span class="line">      <span class="attr">"type"</span>: <span class="string">"cppdbg"</span>,</span><br><span class="line">      <span class="attr">"request"</span>: <span class="string">"launch"</span>,</span><br><span class="line">      <span class="attr">"args"</span>: [],</span><br><span class="line">      <span class="attr">"stopAtEntry"</span>: <span class="literal">false</span>,</span><br><span class="line">      <span class="attr">"externalConsole"</span>: <span class="literal">false</span>,</span><br><span class="line">      <span class="attr">"cwd"</span>: <span class="string">"c:/Dev/leetcode"</span>,</span><br><span class="line">      <span class="attr">"program"</span>: <span class="string">"$&#123;workspaceFolder&#125;/build/Debug/outDebug.exe"</span>,</span><br><span class="line">      <span class="attr">"MIMode"</span>: <span class="string">"gdb"</span>,</span><br><span class="line">      <span class="attr">"miDebuggerPath"</span>: <span class="string">"C:\\msys64\\ucrt64\\bin\\gdb.exe"</span>,</span><br><span class="line">      <span class="attr">"setupCommands"</span>: [</span><br><span class="line">        &#123;</span><br><span class="line">          <span class="attr">"description"</span>: <span class="string">"Enable pretty-printing for gdb"</span>,</span><br><span class="line">          <span class="attr">"text"</span>: <span class="string">"-enable-pretty-printing"</span>,</span><br><span class="line">          <span class="attr">"ignoreFailures"</span>: <span class="literal">true</span></span><br><span class="line">        &#125;</span><br><span class="line">      ]</span><br><span class="line">    &#125;</span><br><span class="line">  ]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="5-keybindings-json（全局配置）"><a href="#5-keybindings-json（全局配置）" class="headerlink" title="5. keybindings.json（全局配置）"></a>5. keybindings.json（全局配置）</h3><p>在 VS Code 用户设置中添加快捷键绑定（<code>Ctrl+Shift+P</code> -&gt; <code>Preferences: Open Keyboard Shortcuts (JSON)</code>）：</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">[</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="attr">"key"</span>: <span class="string">"f6"</span>,</span><br><span class="line">        <span class="attr">"command"</span>: <span class="string">"workbench.action.tasks.runTask"</span>,</span><br><span class="line">        <span class="attr">"args"</span>: &#123;</span><br><span class="line">            <span class="attr">"task"</span>: <span class="string">"Run C++ Program"</span></span><br><span class="line">        &#125;,</span><br><span class="line">        <span class="attr">"when"</span>: <span class="string">"editorTextFocus"</span></span><br><span class="line">    &#125;</span><br><span class="line">]</span><br></pre></td></tr></table></figure><h2 id="使用方法"><a href="#使用方法" class="headerlink" title="使用方法"></a>使用方法</h2><ol><li><strong>编译</strong>：按 <code>Ctrl+Shift+B</code> 或打开命令面板运行 “Tasks: Run Build Task”</li><li><strong>调试</strong>：按 <code>F5</code>，会启动 gdb 调试器</li><li><strong>运行</strong>：按 <code>F6</code>，会打开 cmd 黑框窗口运行程序</li></ol><h2 id="常见问题"><a href="#常见问题" class="headerlink" title="常见问题"></a>常见问题</h2><h3 id="1-找不到-g-或-gdb"><a href="#1-找不到-g-或-gdb" class="headerlink" title="1. 找不到 g++ 或 gdb"></a>1. 找不到 g++ 或 gdb</h3><ul><li>确保 MSYS2 已正确安装并更新</li><li>检查 PATH 环境变量是否包含 <code>C:\msys64\ucrt64\bin</code></li></ul><h3 id="2-编译失败"><a href="#2-编译失败" class="headerlink" title="2. 编译失败"></a>2. 编译失败</h3><ul><li>检查代码语法错误</li><li>确保头文件路径正确</li></ul><h3 id="3-调试失败"><a href="#3-调试失败" class="headerlink" title="3. 调试失败"></a>3. 调试失败</h3><ul><li>确保已编译生成 <code>build/Debug/outDebug.exe</code></li><li>检查 gdb 路径是否正确</li></ul><h3 id="4-黑框不弹出"><a href="#4-黑框不弹出" class="headerlink" title="4. 黑框不弹出"></a>4. 黑框不弹出</h3><ul><li>重启 VS Code</li><li>检查 <code>terminal.external.windowsExec</code> 设置</li></ul><h2 id="版本信息"><a href="#版本信息" class="headerlink" title="版本信息"></a>版本信息</h2><ul><li>MSYS2: 最新版本</li><li>g++: 15.2.0</li><li>gdb: 17.1</li><li>VS Code: 最新版本</li><li>C/C++ 扩展: 最新版本</li></ul><h2 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h2><ul><li><a href="https://www.msys2.org/docs/" target="_blank" rel="noopener">MSYS2 官方文档</a></li><li><a href="https://code.visualstudio.com/docs/cpp/config-mingw" target="_blank" rel="noopener">VS Code C++ 配置指南</a></li><li><a href="https://code.visualstudio.com/docs/cpp/cpp-ide" target="_blank" rel="noopener">C/C++ 扩展文档</a></li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;本文档记录在 Windows 系统上从零配置 VS Code C++ 开发环境的全过程，包括编译、调试和运行。&lt;/p&gt;
&lt;h2 id=&quot;前置条件&quot;&gt;&lt;a href=&quot;#前置条件&quot; class=&quot;headerlink&quot; title=&quot;前置条件&quot;&gt;&lt;/a&gt;前置条件&lt;/h2&gt;&lt;u
      
    
    </summary>
    
    
      <category term="算法" scheme="http://www.z16388.top/tags/%E7%AE%97%E6%B3%95/"/>
    
  </entry>
  
  <entry>
    <title>力扣笔记</title>
    <link href="http://www.z16388.top/2026/04/05/leetcode/"/>
    <id>http://www.z16388.top/2026/04/05/leetcode/</id>
    <published>2026-04-05T21:14:58.000Z</published>
    <updated>2026-04-18T12:45:50.160Z</updated>
    
    <content type="html"><![CDATA[<h2 id="程序模板"><a href="#程序模板" class="headerlink" title="程序模板"></a>程序模板</h2><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span><span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span><span class="meta-string">&lt;cstring&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="数学模板"><a href="#数学模板" class="headerlink" title="数学模板"></a>数学模板</h2><h3 id="公约数、公倍数"><a href="#公约数、公倍数" class="headerlink" title="公约数、公倍数"></a>公约数、公倍数</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">int gcd(int a,int b)  // 最大公约数</span><br><span class="line">&#123;</span><br><span class="line">if(b==0) return a;</span><br><span class="line">else return gcd(b,a%b);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">int lcm(int a,int b)  // 最小公倍数</span><br><span class="line">&#123;</span><br><span class="line">return a/gcd(a,b)*b;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="素数"><a href="#素数" class="headerlink" title="素数"></a>素数</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">int prime(int b)      // 素数</span><br><span class="line">&#123;</span><br><span class="line">    for(int i=2;i&lt;=(int)sqrt(b);i++) &#123;</span><br><span class="line">        if(b%i==0) return 0;</span><br><span class="line">    &#125;</span><br><span class="line">    return 1;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="排列组合打表"><a href="#排列组合打表" class="headerlink" title="排列组合打表"></a>排列组合打表</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">int c[N][N];</span><br><span class="line">void com() &#123;</span><br><span class="line">memset(c,0,sizeof(c));</span><br><span class="line">for(int i=1;i&lt;N;i++) &#123;</span><br><span class="line">c[i][0]=c[i][i]=1;</span><br><span class="line">for(int j=1;j&lt;i;j++) &#123;</span><br><span class="line">c[i][j]=c[i-1][j]+c[i-1][j-1];</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="快速幂"><a href="#快速幂" class="headerlink" title="快速幂"></a>快速幂</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">int Fast(int x,int n) &#123;</span><br><span class="line">int tem=x,ans=1;</span><br><span class="line">while(n) &#123;</span><br><span class="line">if(n%2==1) ans*=tem;</span><br><span class="line">tem*=tem;</span><br><span class="line">n&gt;&gt;=1;</span><br><span class="line">&#125;</span><br><span class="line">return ans;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="快速幂取模"><a href="#快速幂取模" class="headerlink" title="快速幂取模"></a>快速幂取模</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">int pow(int a,int x) &#123;</span><br><span class="line">int ans=1,temp=a%p;</span><br><span class="line">while(x) &#123;</span><br><span class="line">if(x&amp;1) ans=((long long)ans*temp)%p;</span><br><span class="line">temp=((long long)temp*temp)%p;</span><br><span class="line">x&gt;&gt;=1;</span><br><span class="line">&#125;</span><br><span class="line">return ans;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="十进制转换其他进制"><a href="#十进制转换其他进制" class="headerlink" title="十进制转换其他进制"></a>十进制转换其他进制</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">string trans(int num,int base) &#123;</span><br><span class="line">string str;</span><br><span class="line">while(num&gt;0) &#123;</span><br><span class="line">if(num%base&lt;10) &#123;</span><br><span class="line">str+=num%base+&apos;0&apos;;</span><br><span class="line">&#125;</span><br><span class="line">else &#123;</span><br><span class="line">str+=num%base-10+&apos;A&apos;;</span><br><span class="line">&#125;</span><br><span class="line">num=num/base;</span><br><span class="line">&#125;</span><br><span class="line">reverse(str.begin(),str.end());</span><br><span class="line">return str;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="常用数学公式"><a href="#常用数学公式" class="headerlink" title="常用数学公式"></a>常用数学公式</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">等差数列求和公式：</span><br><span class="line"></span><br><span class="line">Sn=n*a1+n(n-1)d/2</span><br><span class="line">Sn=n(a1+an)/2</span><br><span class="line"></span><br><span class="line">等比数列求和公式：</span><br><span class="line"></span><br><span class="line">Sn=a1(1-q^n)/(1-q)</span><br></pre></td></tr></table></figure><h2 id="常用函数"><a href="#常用函数" class="headerlink" title="常用函数"></a>常用函数</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sort（起始地址，终点地址，比较方法）；</span><br><span class="line">lower_bound（起始地址，终点地址，查找元素）；</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;程序模板&quot;&gt;&lt;a href=&quot;#程序模板&quot; class=&quot;headerlink&quot; title=&quot;程序模板&quot;&gt;&lt;/a&gt;程序模板&lt;/h2&gt;&lt;figure class=&quot;highlight c++&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;
      
    
    </summary>
    
    
      <category term="算法" scheme="http://www.z16388.top/tags/%E7%AE%97%E6%B3%95/"/>
    
  </entry>
  
  <entry>
    <title>Unity 游戏的 Google Play 16 kb页面对齐处理</title>
    <link href="http://www.z16388.top/2026/04/03/google-16kb/"/>
    <id>http://www.z16388.top/2026/04/03/google-16kb/</id>
    <published>2026-04-03T17:21:42.000Z</published>
    <updated>2026-04-18T12:45:50.159Z</updated>
    
    <content type="html"><![CDATA[<p>16 KB 内存页面大小的支持，是Google Play 新提出的要求。要在2026年5月31日之前，满足这一条件：</p><p><a href="https://play.google.com/console/u/0/developers/9060101706093336387/app/4974577679306649072/policy-center/issues/4988764664083295045/details" target="_blank" rel="noopener">https://play.google.com/console/u/0/developers/9060101706093336387/app/4974577679306649072/policy-center/issues/4988764664083295045/details</a></p><p>Android 15 的 16KB page 检测主要看三件事：</p><ol><li>PT_LOAD &gt;= 16 KB</li><li>RELRO 必须在 segment 末尾（suffix）</li><li>RELRO end 必须 16KB 对齐</li></ol><blockquote><p>对于aab 来说，上面的三个要求，一般只用关注PT_LOAD。因为aab 有压缩率，所以关于压缩的两项检验直接计算是不准确的。Google Play 在分发时会自动处理。</p></blockquote><p>官方文档：</p><p><a href="https://developer.android.com/guide/practices/page-sizes?utm_source=chatgpt.com&amp;hl=zh-cn" target="_blank" rel="noopener">https://developer.android.com/guide/practices/page-sizes?utm_source=chatgpt.com&amp;hl=zh-cn</a></p><h2 id="检测方式"><a href="#检测方式" class="headerlink" title="检测方式"></a>检测方式</h2><p>关于so 文件是否合规的检测，主要有以下几种方法：</p><h3 id="方法一"><a href="#方法一" class="headerlink" title="方法一"></a>方法一</h3><p>可以解压出so文件，然后使用ndk 工具检测（一定使用PowerShell，cmd无法运行）：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">llvm-objdump.exe -p E:\Test\so\arm64-v8a\libanogs.so | Select-String -Pattern &quot;LOAD&quot;</span><br></pre></td></tr></table></figure><p>运行结果可以看LOAD off 类型行尾是不是带有2<strong>12、2</strong>13。<br>低于2**14的so文件都不符合。</p><p>工具的路径在：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;YourNDKPath&#125;\toolchains\llvm\prebuilt\windows-x86_64\bin</span><br></pre></td></tr></table></figure><p>但是这里只检查了PT_LOAD。</p><h3 id="方法二"><a href="#方法二" class="headerlink" title="方法二"></a>方法二</h3><p>Google 官方提供了检测工具：</p><p><a href="https://cs.android.com/android/platform/superproject/main/+/main:system/extras/tools/check_elf_alignment.sh?hl=zh-cn" target="_blank" rel="noopener">https://cs.android.com/android/platform/superproject/main/+/main:system/extras/tools/check_elf_alignment.sh?hl=zh-cn</a></p><p>可以直接使用这个脚本进行检测。</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">check_elf_alignment.sh APK_NAME.apk</span><br></pre></td></tr></table></figure><h3 id="方法三"><a href="#方法三" class="headerlink" title="方法三"></a>方法三</h3><p>最后，如果将Android Studio 更到最新版本，即可使用Apk Analyze 功能进行检测。</p><p>前者报错为：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">4 KB LOAD section alignment, but 16 KB is required</span><br></pre></td></tr></table></figure></p><p>后者报错为：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">RELRO is not a suffix and its end is not 16 KB aligned</span><br></pre></td></tr></table></figure></p><h2 id="适配方法"><a href="#适配方法" class="headerlink" title="适配方法"></a>适配方法</h2><h3 id="Unity-相关so"><a href="#Unity-相关so" class="headerlink" title="Unity 相关so"></a>Unity 相关so</h3><p>Unity相关的so，需要通过提升Unity 编辑器版本号的方式进行解决。</p><h3 id="第三方SDK"><a href="#第三方SDK" class="headerlink" title="第三方SDK"></a>第三方SDK</h3><p>第三方SDK 相关的so，需要联系相关提供商进行SDK 升级。</p><p>如果无法完成合规，应该考虑取消对该插件的接入。</p><h3 id="自己编译的so"><a href="#自己编译的so" class="headerlink" title="自己编译的so"></a>自己编译的so</h3><p>如果是自己使用NDK 编译的so，需要升级NDK工具并在编译中指定相关参数。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">(&#123;NDK Path&#125;/ndk-build ^</span><br><span class="line">NDK_PROJECT_PATH=. ^</span><br><span class="line">APP_BUILD_SCRIPT=Android.mk ^</span><br><span class="line">NDK_APPLICATION_MK=Application.mk ^</span><br><span class="line">APP_ABI=&quot;armeabi-v7a x86 arm64-v8a x86_64&quot; ^</span><br><span class="line">APP_LDFLAGS=&quot;-Wl,-z,max-page-size=16384 -Wl,-z,common-page-size=16384&quot; ^ // 新增</span><br><span class="line">|| pause) &amp;&amp; pause</span><br></pre></td></tr></table></figure><p>对于Android.mk 文件和Application.mk 文件也有内容需要修改：</p><p>如果旧内容涉及cmd-strip，在打包时会报错。这是因为NDK r23+中，strip 工具路径变成 LLVM 版本。最简单的解决方式是删掉这一行，新版本不需要手动调用strip，会自动调用。</p><p>如果文件中存在：APP_STL := gnustl_static，也需要进行修改。<br>修改为：APP_STL := c++_static</p><p>为了兼容RELRO 必须在 segment 末尾（suffix）和 RELRO end 必须 16KB 对齐，需要在Android.mk 中增加：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">LOCAL_LDFLAGS += -Wl,-z,max-page-size=16384</span><br><span class="line">LOCAL_LDFLAGS += -Wl,-z,common-page-size=16384</span><br></pre></td></tr></table></figure><p>最后，在旧的代码中，如果使用了PAGE_SIZE / PAGE_MASK 宏，这会报错，在新版本中，NDK 不再提供。<br>需要增加以下内容：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">#ifndef PAGE_SIZE</span><br><span class="line">#define PAGE_SIZE 4096</span><br><span class="line">#endif</span><br><span class="line"></span><br><span class="line">#ifndef PAGE_MASK</span><br><span class="line">#define PAGE_MASK (~(PAGE_SIZE - 1))</span><br><span class="line">#endif</span><br></pre></td></tr></table></figure><h2 id="3-il2cpp处理方式"><a href="#3-il2cpp处理方式" class="headerlink" title="3. il2cpp处理方式"></a>3. il2cpp处理方式</h2><p>升级到新版Unity之后，如果不修改代码，可能不会让C++代码重新导出。</p><p>也可以删除Library目录下的Bee目录和所有的il2cpp_*目录的缓存，强制生成。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;16 KB 内存页面大小的支持，是Google Play 新提出的要求。要在2026年5月31日之前，满足这一条件：&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://play.google.com/console/u/0/developers/906010170609333
      
    
    </summary>
    
    
      <category term="Android" scheme="http://www.z16388.top/tags/Android/"/>
    
      <category term="Unity" scheme="http://www.z16388.top/tags/Unity/"/>
    
      <category term="游戏" scheme="http://www.z16388.top/tags/%E6%B8%B8%E6%88%8F/"/>
    
  </entry>
  
  <entry>
    <title>一文详解Hexo 博客搭建</title>
    <link href="http://www.z16388.top/2026/04/03/hexo-github-actions/"/>
    <id>http://www.z16388.top/2026/04/03/hexo-github-actions/</id>
    <published>2026-04-03T14:06:32.000Z</published>
    <updated>2026-04-18T12:45:50.160Z</updated>
    
    <content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>捡起了好久没有更新的博客。</p><p>在AI 的帮助下，我完成了整个环境的重新搭建。</p><p>由于我使用的hexo 框架和版本都比较老了，所以有些地方可能不适应于新版本的主题，在接入时还请注意。</p><p>参考视频： <a href="https://www.bilibili.com/video/BV1xTgTemEDU/" target="_blank" rel="noopener">https://www.bilibili.com/video/BV1xTgTemEDU/</a></p><p>视频文档： <a href="https://xiamu-ssr.github.io/Hexo/2024/06/19/2024-H1/2024-06-19-12-31-52/" target="_blank" rel="noopener">https://xiamu-ssr.github.io/Hexo/2024/06/19/2024-H1/2024-06-19-12-31-52/</a></p><h2 id="准备工作"><a href="#准备工作" class="headerlink" title="准备工作"></a>准备工作</h2><p>使用Github Actions 服务，将hexo 部署到 Github Pages。</p><p>与参考内容不同的是，我使用了两个仓库来实现。</p><p>参考内容中，使用了同一个项目，两个分支。其中一个分支用于提交博客源文件，另一个分支用于存放生成的静态网页文件。</p><p>考虑到将博客源文件内容暴露出来会有一定的风险，于是我的方案是使用两个仓库来实现。其中，Private 的仓库用于存放博客源文件，Public 的仓库用于存放页面。</p><p>我之前是有hexo 环境的，会和从头开始实现有所区别，在接下来的内容中，我将会分别说明。</p><p>关于Github Actions 服务的用量，Public 仓库可以免费使用，但是Private 的仓库会有一定的限制。但是如果只是作为hexo的资源站，免费的额度也是可以覆盖的。</p><h2 id="hexo准备"><a href="#hexo准备" class="headerlink" title="hexo准备"></a>hexo准备</h2><p>安装并初始化hexo，如果已有hexo环境，可跳过这一步。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">npm install -g hexo-cli</span><br><span class="line">hexo init blog</span><br><span class="line">cd blog</span><br><span class="line">npm install</span><br></pre></td></tr></table></figure><p>如果是已有hexo环境，在其他地方做过备份的。可以删除node_modules目录和package-lock.json，然后重新安装：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">cd blog</span><br><span class="line">npm install</span><br></pre></td></tr></table></figure><h2 id="仓库准备"><a href="#仓库准备" class="headerlink" title="仓库准备"></a>仓库准备</h2><p>在github上新建两个仓库，一个Private的blog_base，一个Public 的username.github.io；</p><p>已有Github Pages 的，可以不用重新创建username.github.io，只创建博客源文件仓库。</p><h2 id="Token准备"><a href="#Token准备" class="headerlink" title="Token准备"></a>Token准备</h2><p>使用Github Actions ，需要生成Personal access tokens，而且至少要包含repo 权限。把这个Token 配置给Github Action， 它才有权限去执行自动部署。</p><p>首先是Token 的创建：</p><p>单击头像 -&gt; Settings -&gt; Developer Settings -&gt; Personal access tokens -&gt; Tokens (classic)</p><p>这里是所有Tokens的列表，下面我们继续创建：</p><p>Generate new token -&gt; Generate new token (classic)</p><p>新打开的界面中，我们需要给这个token 命名，随便命名即可，比如blog_base。</p><p>在下面的权限列表中，勾选repo，workflow 两项。</p><p>记录token的有效期，有效期到期后需要给Github Actions 配置新的token。</p><p>完成创建后，去到blog_base 仓库进行配置。首先打开该仓库，点击上方的Settings -&gt; Secrets and variables -&gt; Actions</p><p>点击 New repository secret 创建，Name设置为：GH_TOKEN（可随意设置，后面保持一致即可），Secret 粘贴刚才生成出来的token内容，就是一串以ghp_为开头的字符串。</p><h2 id="修改-config-yml"><a href="#修改-config-yml" class="headerlink" title="修改_config.yml"></a>修改_config.yml</h2><p>为了设置推送的地址，需要在_config.yml 中配置推送地址。这里选择Public 的Github pages 仓库地址：</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">deploy:</span></span><br><span class="line">  <span class="attr">type:</span> <span class="string">git</span></span><br><span class="line">  <span class="attr">repo:</span> <span class="string">https://github.com/yourusername/your-repo.git</span></span><br><span class="line">  <span class="attr">branch:</span> <span class="string">master</span></span><br></pre></td></tr></table></figure><h2 id="配置Github-Actions-工作流"><a href="#配置Github-Actions-工作流" class="headerlink" title="配置Github Actions 工作流"></a>配置Github Actions 工作流</h2><p>在blog_base 目录创建<strong>.github</strong>文件夹，再在.github文件夹下创建<strong>workflows</strong>文件夹，然后创建<strong>deploy.yml</strong>，内容如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line">name: Deploy Hexo to GitHub Pages</span><br><span class="line"></span><br><span class="line">on:</span><br><span class="line">  push:</span><br><span class="line">    branches:</span><br><span class="line">      - main  # 当推送到 main 分支时触发</span><br><span class="line"></span><br><span class="line">jobs:</span><br><span class="line">  build:</span><br><span class="line">    runs-on: ubuntu-latest</span><br><span class="line"></span><br><span class="line">    steps:</span><br><span class="line">      - name: Checkout repository</span><br><span class="line">        uses: actions/checkout@v2</span><br><span class="line">        with:</span><br><span class="line">          submodules: false  # 禁用子模块检查</span><br><span class="line"></span><br><span class="line">      - name: Setup Node.js</span><br><span class="line">        uses: actions/setup-node@v2</span><br><span class="line">        with:</span><br><span class="line">          node-version: &apos;12&apos;</span><br><span class="line"></span><br><span class="line">      - name: Install Dependencies</span><br><span class="line">        run: npm install</span><br><span class="line"></span><br><span class="line">      - name: Install Hexo Git Deployer</span><br><span class="line">        run: |</span><br><span class="line">          npm install hexo-deployer-git --save</span><br><span class="line">          npm install hexo-cli -g</span><br><span class="line"></span><br><span class="line">      - name: Clean and Generate Static Files</span><br><span class="line">        run: |</span><br><span class="line">          hexo clean</span><br><span class="line">          hexo generate</span><br><span class="line"></span><br><span class="line">      - name: Configure Git</span><br><span class="line">        run: |</span><br><span class="line">          git config --global user.name &apos;github-actions[bot]&apos;</span><br><span class="line">          git config --global user.email &apos;github-actions[bot]@users.noreply.github.com&apos;</span><br><span class="line"></span><br><span class="line">      - name: Deploy to GitHub Pages</span><br><span class="line">        env:</span><br><span class="line">          GH_TOKEN: $&#123;&#123; secrets.GH_TOKEN &#125;&#125;</span><br><span class="line">        run: |</span><br><span class="line">          cd public/</span><br><span class="line">          git init</span><br><span class="line">          git add -A</span><br><span class="line">          git commit -m &quot;Create by workflows&quot;</span><br><span class="line">          git branch -M master</span><br><span class="line">          git remote add origin https://$&#123;&#123; secrets.GH_TOKEN &#125;&#125;@github.com/yourusername/your-repo.git</span><br><span class="line">          git push -f origin master</span><br></pre></td></tr></table></figure><p>这里最后一步是将生成的内容，推送到你配置的仓库的master 分支，我的Github Pages就是设置的这个分支。</p><p>配置里的node-version 这个参数需要注意。旧版的hexo 使用新版的node 可能会生成失败。我的主题使用的hexo 版本比较老，使用12版本是可以生成的，最新的24 反而无法生成，这里可以按需修改版本。</p><p>这个工作流的意思就是，使用ubuntu-latest作为基础环境，然后安装各种依赖，随后hexo generate生成博客网站静态文件夹，最后再推送到设定的仓库和分支。</p><h2 id="配置Github-Pages"><a href="#配置Github-Pages" class="headerlink" title="配置Github Pages"></a>配置Github Pages</h2><p>到Github Pages 仓库，点击Settings，设置page来源的分支。</p><p>推送并查看是否能够生效。</p><p>在这里，介绍一下我的.gitignore文件:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">.DS_Store</span><br><span class="line">Thumbs.db</span><br><span class="line">db.json</span><br><span class="line">*.log</span><br><span class="line">public/</span><br><span class="line">.deploy*/</span><br><span class="line">node_modules/</span><br></pre></td></tr></table></figure><p><strong>.DS_Store</strong>文件和<strong>Thumbs.db</strong>文件。这两个文件分别是Mac系统和Win系统生成的垃圾。</p><p>public 目录存放的是本地生成的静态页面，这个也不必上传。Github Actions 会自动生成。</p><p>node_modules 目录一定不能上传，需要排除掉。因为它太大了，不方便版本控制。而且不同平台需求的可能都不同。本地环境和运行Github Actions 的虚拟机环境不可能保证一致的。</p><h2 id="其他注意事项"><a href="#其他注意事项" class="headerlink" title="其他注意事项"></a>其他注意事项</h2><p>如果你之前是有Github Pages的，需要做好备份，防止文件丢失。</p><p>我就出现了CNAME文件和其他文件丢失的情况，这里需要注意。</p><h2 id="自定义域名"><a href="#自定义域名" class="headerlink" title="自定义域名"></a>自定义域名</h2><p>如果嫌username.github.io 的网址不够优雅，可以注册域名，然后配置解析。</p><p>在购买域名后，进行以下设置：</p><h3 id="Github-配置"><a href="#Github-配置" class="headerlink" title="Github 配置"></a>Github 配置</h3><p>进入Github Pages 仓库，单击Settings 切页。</p><p>在左侧边栏点击Pages。</p><p>Custom domain 配置为：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">www.yourdomin.xxx</span><br></pre></td></tr></table></figure><p>然后勾选Enforce HTTPS </p><h3 id="域名解析"><a href="#域名解析" class="headerlink" title="域名解析"></a>域名解析</h3><p>在域名解析中，做出以下设置：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">www  CNAME  yourusername.github.io</span><br><span class="line">@  AAAA  2606:50c0:8003::153</span><br><span class="line">@  AAAA  2606:50c0:8002::153</span><br><span class="line">@  AAAA  2606:50c0:8001::153</span><br><span class="line">@  AAAA  2606:50c0:8000::153</span><br><span class="line">@  A  185.199.111.153</span><br><span class="line">@  A  185.199.110.153</span><br><span class="line">@  A  185.199.108.153</span><br></pre></td></tr></table></figure><p>这里参考Github的文档：<a href="https://docs.github.com/en/pages/configuring-a-custom-domain-for-your-github-pages-site/managing-a-custom-domain-for-your-github-pages-site" target="_blank" rel="noopener">https://docs.github.com/en/pages/configuring-a-custom-domain-for-your-github-pages-site/managing-a-custom-domain-for-your-github-pages-site</a></p><h3 id="创建CNAME"><a href="#创建CNAME" class="headerlink" title="创建CNAME"></a>创建CNAME</h3><p>需要在Github Pages 网站的根目录创建CNAME文件，内容是在第一步中配置的<a href="http://www.yourdomin.xxx" target="_blank" rel="noopener">www.yourdomin.xxx</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;前言&quot;&gt;&lt;a href=&quot;#前言&quot; class=&quot;headerlink&quot; title=&quot;前言&quot;&gt;&lt;/a&gt;前言&lt;/h2&gt;&lt;p&gt;捡起了好久没有更新的博客。&lt;/p&gt;
&lt;p&gt;在AI 的帮助下，我完成了整个环境的重新搭建。&lt;/p&gt;
&lt;p&gt;由于我使用的hexo 框架和版本都比
      
    
    </summary>
    
    
      <category term="hexo" scheme="http://www.z16388.top/tags/hexo/"/>
    
      <category term="Github" scheme="http://www.z16388.top/tags/Github/"/>
    
  </entry>
  
  <entry>
    <title>xlua学习笔记</title>
    <link href="http://www.z16388.top/2021/05/18/xlua/"/>
    <id>http://www.z16388.top/2021/05/18/xlua/</id>
    <published>2021-05-18T19:05:07.000Z</published>
    <updated>2026-04-18T12:45:50.161Z</updated>
    
    <content type="html"><![CDATA[<h1 id="文件加载"><a href="#文件加载" class="headerlink" title="文件加载"></a>文件加载</h1><p>使用LuaEnv中的DoString方法来执行Lua脚本。<br>因为创建一个LuaEnv相当于创建了一个lua虚拟机，所以一个游戏最好只有一个LuaEnv。</p><figure class="highlight cs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 执行lua代码</span></span><br><span class="line">env.DoString(<span class="string">"print(\"Hello World\")"</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 通过文件执行lua代码</span></span><br><span class="line">TextAsset ta = Resources.Load&lt;TextAsset&gt;(<span class="string">"Lua/helloworld.lua"</span>);</span><br><span class="line">env.DoString(ta.text);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 通过默认Loader执行lua代码</span></span><br><span class="line">env.DoString(<span class="string">"require 'Lua/helloworld'"</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 通过自定义Loader执行lua代码</span></span><br><span class="line"><span class="comment">// require实际上是调一个个的Loader去加载，有一个成功就不再往下尝试，全失败则报文件找不到。</span></span><br><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">byte</span>[] <span class="title">LuaLoader</span>(<span class="params"><span class="keyword">ref</span> <span class="keyword">string</span> filePath</span>)</span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">string</span> path = <span class="string">"Lua/"</span> + filePath + <span class="string">".lua"</span>;</span><br><span class="line">    print(path);</span><br><span class="line">    TextAsset ta = Resources.Load&lt;TextAsset&gt;(path);</span><br><span class="line">    <span class="keyword">return</span> System.Text.Encoding.UTF8.GetBytes(ta.text);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">env.AddLoader(LuaLoader);</span><br><span class="line">env.DoString(<span class="string">"require 'helloworld'"</span>);</span><br></pre></td></tr></table></figure><p>官方建议的加载Lua脚本方式是：整个程序就一个DoString(“require ‘main’”)，然后在main.lua加载其它脚本（类似lua脚本的命令行执行：lua main.lua）。</p><h1 id="C-访问Lua普通全局变量"><a href="#C-访问Lua普通全局变量" class="headerlink" title="C#访问Lua普通全局变量"></a>C#访问Lua普通全局变量</h1><p>先加载lua脚本，再通过LuaEnv.Global.Get获取变量。</p><figure class="highlight cs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">TextAsset ta = Resources.Load&lt;TextAsset&gt;(<span class="string">"Lua/variable.lua"</span>);</span><br><span class="line">env.DoString(ta.text);</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> g_int = env.Global.Get&lt;<span class="keyword">int</span>&gt;(<span class="string">"g_int"</span>);</span><br><span class="line"><span class="keyword">string</span> g_str = env.Global.Get&lt;<span class="keyword">string</span>&gt;(<span class="string">"g_str"</span>);</span><br><span class="line"><span class="keyword">bool</span> g_bool = env.Global.Get&lt;<span class="keyword">bool</span>&gt;(<span class="string">"g_bool"</span>);</span><br></pre></td></tr></table></figure><h1 id="C-访问Lua-table的四种方法"><a href="#C-访问Lua-table的四种方法" class="headerlink" title="C#访问Lua table的四种方法"></a>C#访问Lua table的四种方法</h1><p>需要注意的是，在构建C#中对应的结构时，接口一定要是public修饰，否则会报错。类最好也是，但是经测试，没有报错。</p><p><strong>映射到普通class或struct</strong></p><p>table的属性可以多于或者少于class的属性，也就是不一定都需要做映射。这个过程是值拷贝，如果class比较复杂代价会比较大。而且修改class的字段值不会同步到table，反过来也不会。<br><figure class="highlight cs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title">Person</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">string</span> name;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">int</span> age;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">Person p = env.Global.Get&lt;Person&gt;(<span class="string">"g_tbl"</span>);</span><br></pre></td></tr></table></figure></p><p><strong>映射到接口</strong></p><p>一定要加[CSharpCallLua]和public，否则会报错。<br><figure class="highlight lua"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">g_int = <span class="number">1</span></span><br><span class="line">g_str = <span class="string">"Hello World Variable"</span></span><br><span class="line">g_bool = <span class="literal">false</span></span><br><span class="line">g_tbl = &#123;name = <span class="string">"Juhnny"</span>, age = <span class="number">12</span>&#125;</span><br><span class="line">g_tbl.say = <span class="function"><span class="keyword">function</span><span class="params">(this, str)</span></span></span><br><span class="line">    <span class="built_in">print</span>(str)</span><br><span class="line"><span class="keyword">end</span></span><br></pre></td></tr></table></figure></p><figure class="highlight cs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">[<span class="meta">CSharpCallLua</span>]</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title">IPerson</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">string</span> name &#123; <span class="keyword">get</span>; <span class="keyword">set</span>; &#125;</span><br><span class="line">    <span class="keyword">int</span> age &#123; <span class="keyword">get</span>; <span class="keyword">set</span>; &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">say</span>(<span class="params"><span class="keyword">string</span> str</span>)</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">IPerson p = env.Global.Get&lt;IPerson&gt;(<span class="string">"g_tbl"</span>);</span><br><span class="line">p.say(<span class="string">"Yahoo"</span>);</span><br></pre></td></tr></table></figure><p><strong>映射到Dictionary和List</strong></p><p>这种方法较方法2更为轻量级，但是要求table下key和value类型一致。<br><figure class="highlight lua"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">g_dic = &#123;apple = <span class="string">"iPhone"</span>, flower = <span class="string">"Huawei"</span>&#125;</span><br><span class="line">g_list = &#123;<span class="number">1</span>, <span class="number">3</span>, <span class="number">5</span>, <span class="number">7</span>, <span class="number">9</span>&#125;</span><br></pre></td></tr></table></figure></p><figure class="highlight cs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">Dictionary&lt;<span class="keyword">string</span>, <span class="keyword">string</span>&gt; dic = env.Global.Get&lt;Dictionary&lt;<span class="keyword">string</span>, <span class="keyword">string</span>&gt;&gt;(<span class="string">"g_dic"</span>);</span><br><span class="line"><span class="keyword">foreach</span> (<span class="keyword">var</span> child <span class="keyword">in</span> dic)</span><br><span class="line">&#123;</span><br><span class="line">    print(<span class="keyword">string</span>.Format(<span class="string">"Key is &#123;0&#125;, Value is &#123;1&#125;"</span>, child.Key, child.Value));</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">List&lt;<span class="keyword">int</span>&gt; list = env.Global.Get&lt;List&lt;<span class="keyword">int</span>&gt;&gt;(<span class="string">"g_list"</span>);</span><br><span class="line"><span class="keyword">foreach</span> (<span class="keyword">var</span> v <span class="keyword">in</span> list)</span><br><span class="line">&#123;</span><br><span class="line">    print(v);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>映射到LuaTable</strong></p><p>这种方法比较慢，而且没有类型检查，不推荐使用。<br><figure class="highlight cs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">LuaTable tab = env.Global.Get&lt;LuaTable&gt;(<span class="string">"g_tbl"</span>);</span><br><span class="line"><span class="keyword">string</span> name = tab.Get&lt;<span class="keyword">string</span>&gt;(<span class="string">"name"</span>);</span><br><span class="line"><span class="keyword">int</span> age = tab.Get&lt;<span class="keyword">int</span>&gt;(<span class="string">"age"</span>);</span><br><span class="line">print(<span class="keyword">string</span>.Format(<span class="string">"Name is &#123;0&#125;, age is &#123;1&#125;"</span>, name, age));</span><br><span class="line"><span class="keyword">foreach</span> (<span class="keyword">string</span> key <span class="keyword">in</span> tab.GetKeys())</span><br><span class="line">&#123;</span><br><span class="line">    print(tab.Get&lt;<span class="keyword">object</span>&gt;(key));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p><h1 id="C-访问Lua全局函数"><a href="#C-访问Lua全局函数" class="headerlink" title="C#访问Lua全局函数"></a>C#访问Lua全局函数</h1><p><strong>使用delegate映射</strong></p><p>这种是建议的方式，性能好很多，而且类型安全，但是要生成代码。支持带返回值，多返回值，甚至返回值都可以是delegate。<br><figure class="highlight lua"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">g_func1 = <span class="function"><span class="keyword">function</span><span class="params">()</span></span></span><br><span class="line">    <span class="built_in">print</span>(<span class="string">"FF"</span>)</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"></span><br><span class="line">g_func2 = <span class="function"><span class="keyword">function</span><span class="params">(num)</span></span></span><br><span class="line">    <span class="built_in">print</span>(num)</span><br><span class="line">    <span class="keyword">return</span> num, <span class="string">"Yoshida"</span>, <span class="string">"SE"</span></span><br><span class="line"><span class="keyword">end</span></span><br></pre></td></tr></table></figure></p><figure class="highlight cs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">[<span class="meta">CSharpCallLua</span>]</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">delegate</span> <span class="keyword">int</span> <span class="title">Func2</span>(<span class="params"><span class="keyword">int</span> num, <span class="keyword">out</span> <span class="keyword">string</span> name, <span class="keyword">out</span> <span class="keyword">string</span> company</span>)</span>;</span><br><span class="line"><span class="comment">// 声明委托时，一定要加public和[CSharpCallLua]</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 无返回</span></span><br><span class="line">Action func1 = env.Global.Get&lt;Action&gt;(<span class="string">"g_func1"</span>);</span><br><span class="line">func1();</span><br><span class="line">func1 = <span class="literal">null</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 单返回值</span></span><br><span class="line">Func2 func2 = env.Global.Get&lt;Func2&gt;(<span class="string">"g_func2"</span>);</span><br><span class="line"><span class="keyword">int</span> num = func2(<span class="number">14</span>);</span><br><span class="line">func2 = <span class="literal">null</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 多返回值</span></span><br><span class="line">Func2 func2 = env.Global.Get&lt;Func2&gt;(<span class="string">"g_func2"</span>);</span><br><span class="line"><span class="keyword">string</span> name;</span><br><span class="line"><span class="keyword">string</span> company;</span><br><span class="line"><span class="keyword">int</span> num = func2(<span class="number">14</span>, <span class="keyword">out</span> name, <span class="keyword">out</span> company);</span><br><span class="line">func2 = <span class="literal">null</span></span><br></pre></td></tr></table></figure><p>在过去的一些版本中，需要在不使用后，将接收到的函数销毁，否则会在LuaEnv.Dispose的时候报错。</p><p><strong>使用LuaFunction</strong></p><p>与上一种方法优缺点相反，不推荐使用。<br><figure class="highlight cs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">LuaFunction func = env.Global.Get&lt;LuaFunction&gt;(<span class="string">"g_func2"</span>);</span><br><span class="line"><span class="keyword">object</span>[] res = func.Call(<span class="number">14</span>);</span><br></pre></td></tr></table></figure></p><h1 id="Lua调用C"><a href="#Lua调用C" class="headerlink" title="Lua调用C"></a>Lua调用C</h1><figure class="highlight cs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 读静态属性</span></span><br><span class="line">CS.UnityEngine.Time.deltaTime</span><br><span class="line"></span><br><span class="line"><span class="comment">// 写静态属性</span></span><br><span class="line">CS.UnityEngine.Time.timeScale = <span class="number">0.5</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 调用静态方法</span></span><br><span class="line">CS.UnityEngine.GameObject.Find(<span class="string">'helloworld'</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 读写成员属性类似，但是访问成员方法要使用:</span></span><br><span class="line">testobj:DMFunc()</span><br></pre></td></tr></table></figure><h1 id="其它注意事项"><a href="#其它注意事项" class="headerlink" title="其它注意事项"></a>其它注意事项</h1><p><strong>方法的参数处理</strong><br>Lua调用侧的参数处理规则：C#的普通参数算一个输入形参，ref修饰的算一个输入形参，out不算，然后从左往右对应lua 调用侧的实参列表。</p><p>Lua调用侧的返回值处理规则：C#函数的返回值（如果有的话）算一个返回值，out算一个返回值，ref算一个返回值，然后从左往右对应lua的多返回值。</p><p><strong>可变参数的处理</strong><br><figure class="highlight cs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 对于C#的如下方法：</span></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">VariableParamsFunc</span>(<span class="params"><span class="keyword">int</span> a, <span class="keyword">params</span> <span class="keyword">string</span>[] strs</span>)</span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function"><span class="comment">// 可以在lua里头这样调用：</span></span></span><br><span class="line"><span class="function">testobj:<span class="title">VariableParamsFunc</span>(<span class="params"><span class="number">5</span>, <span class="string">'hello'</span>, <span class="string">'john'</span></span>)</span></span><br></pre></td></tr></table></figure></p><p><strong>枚举</strong><br><figure class="highlight cs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 枚举值就像枚举类型下的静态属性一样。</span></span><br><span class="line"></span><br><span class="line">    testobj:EnumTestFunc(CS.Tutorial.TestEnum.E1)</span><br><span class="line"></span><br><span class="line">上面的EnumTestFunc函数参数是Tutorial.TestEnum类型的。</span><br><span class="line"></span><br><span class="line">枚举类支持__CastFrom方法，可以实现从一个整数或者字符串到枚举值的转换，例如：</span><br><span class="line"></span><br><span class="line">    CS.Tutorial.TestEnum.__CastFrom(<span class="number">1</span>)</span><br><span class="line">    CS.Tutorial.TestEnum.__CastFrom(<span class="string">'E1'</span>)</span><br></pre></td></tr></table></figure></p><p><strong>委托</strong></p><figure class="highlight lua"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 使用+-号来实现委托</span></span><br><span class="line"><span class="comment">-- 比如testobj里头有个事件定义是这样：public event Action TestEvent;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">-- 增加事件回调</span></span><br><span class="line">testobj:TestEvent(<span class="string">'+'</span>, lua_event_callback)</span><br><span class="line"></span><br><span class="line"><span class="comment">--移除事件回调</span></span><br><span class="line">testobj:TestEvent(<span class="string">'-'</span>, lua_event_callback)</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;文件加载&quot;&gt;&lt;a href=&quot;#文件加载&quot; class=&quot;headerlink&quot; title=&quot;文件加载&quot;&gt;&lt;/a&gt;文件加载&lt;/h1&gt;&lt;p&gt;使用LuaEnv中的DoString方法来执行Lua脚本。&lt;br&gt;因为创建一个LuaEnv相当于创建了一个lua虚拟机，所以
      
    
    </summary>
    
    
      <category term="游戏" scheme="http://www.z16388.top/tags/%E6%B8%B8%E6%88%8F/"/>
    
      <category term="xlua" scheme="http://www.z16388.top/tags/xlua/"/>
    
      <category term="热更新" scheme="http://www.z16388.top/tags/%E7%83%AD%E6%9B%B4%E6%96%B0/"/>
    
  </entry>
  
  <entry>
    <title>Lua新知</title>
    <link href="http://www.z16388.top/2021/05/10/luanew/"/>
    <id>http://www.z16388.top/2021/05/10/luanew/</id>
    <published>2021-05-10T11:42:01.000Z</published>
    <updated>2026-04-18T12:45:50.160Z</updated>
    
    <content type="html"><![CDATA[<p>两年没有碰过Lua了，总觉得得要捡起来。现在从头到尾再过一遍，总结一些东西。之前根据菜鸟学的时候，使用了5.1.1的版本。与现在常用的版本相悖。因此这次我使用了：zerobrane studio，它可以方便切换版本，能实现很好的练习效果。</p><h1 id="关于多行注释的安全问题"><a href="#关于多行注释的安全问题" class="headerlink" title="关于多行注释的安全问题"></a>关于多行注释的安全问题</h1><p>如果直接使用默认的<code>–[[</code>和<code>–]]</code>来进行多行注释的时候,如果遇到table包table的情况会直接结束注释:<br><figure class="highlight lua"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">--[[</span></span><br><span class="line"><span class="comment">a = [];</span></span><br><span class="line"><span class="comment">b = [a];</span></span><br><span class="line"><span class="comment">a[b[1]]</span></span><br><span class="line">a = <span class="number">1</span></span><br><span class="line"><span class="comment">--]]</span></span><br></pre></td></tr></table></figure></p><p>可以使用另一种方法来进行多行注释,避免这个问题:<br><figure class="highlight lua"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">--[=[</span></span><br><span class="line"><span class="comment">a = [];</span></span><br><span class="line"><span class="comment">b = [a];</span></span><br><span class="line"><span class="comment">a[b[1]]</span></span><br><span class="line">a = <span class="number">1</span></span><br><span class="line">]=]</span><br></pre></td></tr></table></figure></p><p>当然,最安全的方法还是使用IDE的快捷键进行注释.IDE会在每行的前面加单行注释,避免错误的发生.</p><h1 id="多行字符串安全问题"><a href="#多行字符串安全问题" class="headerlink" title="多行字符串安全问题"></a>多行字符串安全问题</h1><p>多行字符串,也会出现类似于上面的情况:<br><figure class="highlight lua"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">str = </span><br><span class="line"><span class="string">[[</span></span><br><span class="line"><span class="string">话说</span></span><br><span class="line"><span class="string">这个东西</span></span><br><span class="line"><span class="string">好像打印不出来</span></span><br><span class="line"><span class="string">就是这个</span></span><br><span class="line"><span class="string">table[table[idx]]</span></span><br><span class="line">咋办啊</span><br><span class="line">]]</span><br><span class="line"><span class="built_in">print</span>(str)</span><br></pre></td></tr></table></figure></p><h1 id="运算符相关"><a href="#运算符相关" class="headerlink" title="运算符相关"></a>运算符相关</h1><p>#运算符取的是最大索引的值，如果删除了中间的值，获得的结果不会改变：<br><figure class="highlight lua"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">tb_a = &#123;<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>&#125;</span><br><span class="line"><span class="built_in">print</span> (#tb_a)</span><br><span class="line"></span><br><span class="line">tb_a[<span class="number">2</span>] = <span class="literal">nil</span></span><br><span class="line"><span class="built_in">print</span> (#tb_a)</span><br></pre></td></tr></table></figure></p><p>但是这种情况仅限于Lua 5.1 ，Lua5.3和Lua5.4结果是1。</p><p>模拟三目运算符的<code>and…or…</code>，在第二个参数为false时，始终返回c，会出现问题：<br><figure class="highlight lua"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">a = <span class="literal">true</span></span><br><span class="line"><span class="built_in">print</span> (a <span class="keyword">and</span> <span class="literal">false</span> <span class="keyword">or</span> <span class="literal">true</span>)</span><br></pre></td></tr></table></figure></p><p>输出结果会是true 而不是三目运算符应该返回的false。<br>这时候，可以将三目运算符的后面两个部分转换成table，运算结束后再取第一个元素，即可实现：<br><figure class="highlight lua"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">a = <span class="literal">true</span></span><br><span class="line">b = (a <span class="keyword">and</span> &#123;<span class="literal">false</span>&#125; <span class="keyword">or</span> &#123;<span class="literal">true</span>&#125;)[<span class="number">1</span>]</span><br><span class="line"><span class="keyword">if</span> b <span class="keyword">then</span></span><br><span class="line"><span class="built_in">print</span>(<span class="string">"true"</span>)</span><br><span class="line"><span class="keyword">else</span></span><br><span class="line"><span class="built_in">print</span>(<span class="string">"false"</span>)</span><br><span class="line"><span class="keyword">end</span></span><br></pre></td></tr></table></figure></p><h1 id="自定义迭代器"><a href="#自定义迭代器" class="headerlink" title="自定义迭代器"></a>自定义迭代器</h1><p>自定义迭代器的格式：<br><figure class="highlight lua"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> 变量列表 <span class="keyword">in</span> 迭代函数, 状态变量, 控制变量 <span class="keyword">do</span></span><br><span class="line">    <span class="comment">-- 循环体</span></span><br><span class="line"><span class="keyword">end</span></span><br></pre></td></tr></table></figure></p><p>自定义无状态迭代器<br><figure class="highlight lua"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">square</span><span class="params">(iteratorMaxCount, currentNumber)</span></span></span><br><span class="line">    <span class="keyword">if</span> currentNumber &lt; iteratorMaxCount <span class="keyword">then</span></span><br><span class="line">        currentNumber = currentNumber + <span class="number">1</span></span><br><span class="line">        <span class="keyword">return</span> currentNumber, currentNumber * currentNumber</span><br><span class="line">    <span class="keyword">end</span></span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> i, n <span class="keyword">in</span> square, <span class="number">3</span>, <span class="number">0</span></span><br><span class="line"><span class="keyword">do</span></span><br><span class="line">    <span class="built_in">print</span>(i, n)</span><br><span class="line"><span class="keyword">end</span></span><br></pre></td></tr></table></figure></p><p>多状态迭代器：<br>多个状态可以存放在table，因此只需要一个参数即可：<br><figure class="highlight lua"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">array = &#123;<span class="string">"Google"</span>, <span class="string">"Runoob"</span>&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">elementIterator</span> <span class="params">(collection)</span></span></span><br><span class="line">    <span class="keyword">local</span> index = <span class="number">0</span></span><br><span class="line">    <span class="keyword">local</span> count = #collection</span><br><span class="line">    <span class="comment">-- 闭包函数</span></span><br><span class="line">    <span class="keyword">return</span> <span class="function"><span class="keyword">function</span> <span class="params">()</span></span></span><br><span class="line">        index = index + <span class="number">1</span></span><br><span class="line">        <span class="keyword">if</span> index &lt;= count <span class="keyword">then</span></span><br><span class="line">            <span class="comment">--  返回迭代器的当前元素</span></span><br><span class="line">            <span class="keyword">return</span> collection[index]</span><br><span class="line">        <span class="keyword">end</span></span><br><span class="line">    <span class="keyword">end</span></span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> element <span class="keyword">in</span> elementIterator(array) <span class="keyword">do</span></span><br><span class="line">    <span class="built_in">print</span>(element)</span><br><span class="line"><span class="keyword">end</span></span><br></pre></td></tr></table></figure></p><h1 id="循环时的goto语句"><a href="#循环时的goto语句" class="headerlink" title="循环时的goto语句"></a>循环时的goto语句</h1><p>可以使用goto语句来实现continue：<br><figure class="highlight lua"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> i=<span class="number">1</span>, <span class="number">3</span> <span class="keyword">do</span></span><br><span class="line">    <span class="keyword">if</span> i &lt;= <span class="number">2</span> <span class="keyword">then</span></span><br><span class="line">        <span class="built_in">print</span>(i, <span class="string">"yes continue"</span>)</span><br><span class="line">        <span class="keyword">goto</span> continue</span><br><span class="line">    <span class="keyword">end</span></span><br><span class="line">    <span class="built_in">print</span>(i, <span class="string">" no continue"</span>)</span><br><span class="line">    ::continue::</span><br><span class="line">    <span class="built_in">print</span>(<span class="string">[[i'm end]]</span>)</span><br><span class="line"><span class="keyword">end</span></span><br></pre></td></tr></table></figure></p><h1 id="元表"><a href="#元表" class="headerlink" title="元表"></a>元表</h1><p>Lua可以通过设置元表，定义元方法的方式，改变table的一些行为：</p><p><strong>index元方法，可以修改按索引取值的逻辑。<br>若</strong>index内容是一个表的话，如果table里没有值，会从元表中对应的索引去取：<br><figure class="highlight lua"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">t_table = <span class="built_in">setmetatable</span>(&#123;k1 = <span class="string">"v1"</span>&#125;, &#123;<span class="built_in">__index</span> = &#123;k2 = <span class="string">"v2"</span>&#125;&#125;)</span><br><span class="line"><span class="built_in">print</span>(t_table[<span class="string">"k1"</span>])</span><br><span class="line"><span class="built_in">print</span>(t_table[<span class="string">"k2"</span>])</span><br><span class="line">t_table[<span class="string">"k2"</span>] = <span class="string">"v3"</span></span><br><span class="line"><span class="built_in">print</span>(t_table[<span class="string">"k2"</span>])</span><br><span class="line"><span class="comment">--[[</span></span><br><span class="line"><span class="comment">输出是：</span></span><br><span class="line"><span class="comment">v1</span></span><br><span class="line"><span class="comment">v2</span></span><br><span class="line"><span class="comment">v3</span></span><br><span class="line"><span class="comment">--]]</span></span><br></pre></td></tr></table></figure></p><p>若__index内容是一个函数，则可以定义返回逻辑：<br><figure class="highlight lua"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line">t_table = <span class="built_in">setmetatable</span>(&#123;&#125;, &#123;<span class="built_in">__index</span> =</span><br><span class="line"><span class="function"><span class="keyword">function</span><span class="params">(t_table, key)</span></span></span><br><span class="line"><span class="keyword">if</span> key == <span class="number">1</span> <span class="keyword">then</span></span><br><span class="line"><span class="keyword">return</span> <span class="string">"true"</span></span><br><span class="line"><span class="keyword">else</span></span><br><span class="line"><span class="keyword">return</span> <span class="string">"false"</span></span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"><span class="keyword">end</span></span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(t_table[<span class="number">1</span>])</span><br><span class="line"><span class="built_in">print</span>(t_table[<span class="number">2</span>])</span><br><span class="line"><span class="built_in">print</span>(t_table[<span class="number">3</span>])</span><br><span class="line"></span><br><span class="line">t_table = &#123;<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>&#125;</span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(t_table[<span class="number">1</span>])</span><br><span class="line"><span class="built_in">print</span>(t_table[<span class="number">2</span>])</span><br><span class="line"><span class="built_in">print</span>(t_table[<span class="number">3</span>])</span><br><span class="line"><span class="comment">--[[</span></span><br><span class="line"><span class="comment">输出是：</span></span><br><span class="line"><span class="comment">true</span></span><br><span class="line"><span class="comment">false</span></span><br><span class="line"><span class="comment">false</span></span><br><span class="line"><span class="comment">1</span></span><br><span class="line"><span class="comment">2</span></span><br><span class="line"><span class="comment">3</span></span><br><span class="line"><span class="comment">--]]</span></span><br></pre></td></tr></table></figure></p><p>__newindex元方法，可以修改追加索引时的逻辑<br><figure class="highlight lua"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">t_table = <span class="built_in">setmetatable</span>(&#123;k1 = <span class="string">"v1"</span>&#125;, &#123;</span><br><span class="line"><span class="built_in">__newindex</span> =</span><br><span class="line"><span class="function"><span class="keyword">function</span><span class="params">(t_table, key, value)</span></span></span><br><span class="line"><span class="built_in">rawset</span>(t_table, key, <span class="string">"\"v"</span> .. value .. <span class="string">"\""</span>)</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line">t_table[<span class="string">"k2"</span>] = <span class="number">2</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(t_table[<span class="string">"k1"</span>])</span><br><span class="line"><span class="built_in">print</span>(t_table[<span class="string">"k2"</span>])</span><br><span class="line"></span><br><span class="line"><span class="comment">--[[</span></span><br><span class="line"><span class="comment">输出是：</span></span><br><span class="line"><span class="comment">v1</span></span><br><span class="line"><span class="comment">"v2"</span></span><br><span class="line"><span class="comment">--]]</span></span><br></pre></td></tr></table></figure></p><p>其它的规则：<br>|元表|运算符|<br>|:–:|:–:|<br>|<strong>add|+|<br>|</strong>sub|-|<br>|<strong>mul|*|<br>|</strong>div|/|<br>|<strong>mod|%|<br>|</strong>unm|-(相反数)|<br>|<strong>concat|..|<br>|</strong>eq|==|<br>|<strong>lt|&lt;|<br>|</strong>le|&lt;=|</p><p><strong>add和</strong>tostring:<br><figure class="highlight lua"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">t_table = <span class="built_in">setmetatable</span>(&#123;<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>&#125;, &#123;<span class="built_in">__add</span> =</span><br><span class="line"><span class="function"><span class="keyword">function</span><span class="params">(t_table, data)</span></span></span><br><span class="line">t_table[#t_table + <span class="number">1</span>] = data</span><br><span class="line"><span class="keyword">return</span> t_table</span><br><span class="line"><span class="keyword">end</span>,</span><br><span class="line"><span class="built_in">__tostring</span> =</span><br><span class="line"><span class="function"><span class="keyword">function</span><span class="params">(t_table)</span></span></span><br><span class="line"><span class="keyword">local</span> res = <span class="string">""</span></span><br><span class="line"><span class="keyword">for</span> _, v <span class="keyword">in</span> <span class="built_in">pairs</span>(t_table) <span class="keyword">do</span></span><br><span class="line">res = res .. v</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"><span class="keyword">return</span> res</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line">&#125;)</span><br><span class="line"><span class="built_in">print</span>(t_table)</span><br><span class="line"><span class="built_in">print</span>(t_table + <span class="number">4</span>)</span><br><span class="line"><span class="comment">--[[</span></span><br><span class="line"><span class="comment">输出：</span></span><br><span class="line"><span class="comment">123</span></span><br><span class="line"><span class="comment">1234</span></span><br><span class="line"><span class="comment">--]]</span></span><br></pre></td></tr></table></figure></p><p>需要注意的是，关系运算符，比较的两端，元表必须相同。如果只有一方有元表，另一方没有，又或者是两方拥有不同的元表，会导致比较报错：<br><figure class="highlight lua"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">a_metatable =</span><br><span class="line">&#123;</span><br><span class="line">__gt = <span class="function"><span class="keyword">function</span><span class="params">(a_table, b_table)</span></span></span><br><span class="line"><span class="keyword">return</span> a_table[<span class="number">1</span>] &gt; b_table[<span class="number">1</span>]</span><br><span class="line"><span class="keyword">end</span>,</span><br><span class="line"><span class="built_in">__lt</span> = <span class="function"><span class="keyword">function</span><span class="params">(a_table, b_table)</span></span></span><br><span class="line"><span class="keyword">return</span> a_table[<span class="number">1</span>] &lt; b_table[<span class="number">1</span>]</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line">&#125;</span><br><span class="line">b_metatable =</span><br><span class="line">&#123;</span><br><span class="line">__gt = <span class="function"><span class="keyword">function</span><span class="params">(a_table, b_table)</span></span></span><br><span class="line"><span class="keyword">return</span> b_table[<span class="number">1</span>] &gt; a_table[<span class="number">1</span>]</span><br><span class="line"><span class="keyword">end</span>,</span><br><span class="line"><span class="built_in">__lt</span> = <span class="function"><span class="keyword">function</span><span class="params">(a_table, b_table)</span></span></span><br><span class="line"><span class="keyword">return</span> b_table[<span class="number">1</span>] &lt; a_table[<span class="number">1</span>]</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line">&#125;</span><br><span class="line">a_table = <span class="built_in">setmetatable</span>(&#123;<span class="number">0</span>&#125;, a_metatable)</span><br><span class="line">b_table = <span class="built_in">setmetatable</span>(&#123;<span class="number">1</span>&#125;, b_metatable)</span><br><span class="line"><span class="built_in">print</span>(a_table&lt;b_table)</span><br><span class="line"><span class="comment">--[[</span></span><br><span class="line"><span class="comment">报错内容是：</span></span><br><span class="line"><span class="comment">attempt to compare two table values</span></span><br><span class="line"><span class="comment">--]]</span></span><br></pre></td></tr></table></figure></p><p>重写取反操作<br><figure class="highlight lua"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">a_metatable =</span><br><span class="line">&#123;</span><br><span class="line"><span class="built_in">__unm</span> = <span class="function"><span class="keyword">function</span><span class="params">(a_table)</span></span></span><br><span class="line"><span class="keyword">local</span> _temp_table = &#123;&#125;</span><br><span class="line"><span class="keyword">for</span> i = #a_table, <span class="number">1</span>, <span class="number">-1</span> <span class="keyword">do</span></span><br><span class="line">_temp_table[#a_table + <span class="number">1</span> - i] = a_table[i]</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"><span class="keyword">return</span> _temp_table</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line">&#125;</span><br><span class="line">p_metatable =</span><br><span class="line">&#123;</span><br><span class="line"><span class="built_in">__tostring</span> =</span><br><span class="line"><span class="function"><span class="keyword">function</span><span class="params">(a_table)</span></span></span><br><span class="line"><span class="keyword">local</span> res = <span class="string">""</span></span><br><span class="line"><span class="keyword">for</span> _, v <span class="keyword">in</span> <span class="built_in">pairs</span>(a_table) <span class="keyword">do</span></span><br><span class="line">res = res .. v</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"><span class="keyword">return</span> res</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line">&#125;</span><br><span class="line">a_table = <span class="built_in">setmetatable</span>(&#123;<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>&#125;, a_metatable)</span><br><span class="line">b_table = <span class="built_in">setmetatable</span>(-a_table, p_metatable)</span><br><span class="line"><span class="built_in">print</span>(b_table)</span><br></pre></td></tr></table></figure></p><p>__call比较有意思，可以让table可以变得和函数一样可以执行。因此可以写成如下的极其过分的形式：<br><figure class="highlight lua"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">function_content =</span><br><span class="line">&#123;</span><br><span class="line"><span class="built_in">__call</span> = <span class="function"><span class="keyword">function</span><span class="params">(a_table, a_data)</span></span></span><br><span class="line"><span class="built_in">print</span>(a_data)</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">func_print = <span class="built_in">setmetatable</span>(&#123;&#125;, function_content)</span><br><span class="line">b = func_print(<span class="number">4</span>)</span><br></pre></td></tr></table></figure></p><h1 id="协程"><a href="#协程" class="headerlink" title="协程"></a>协程</h1><figure class="highlight lua"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">sleep</span><span class="params">(n)</span></span></span><br><span class="line">   <span class="keyword">local</span> t0 = <span class="built_in">os</span>.<span class="built_in">clock</span>()</span><br><span class="line">   <span class="keyword">while</span> <span class="built_in">os</span>.<span class="built_in">clock</span>() - t0 &lt;= n <span class="keyword">do</span> <span class="keyword">end</span></span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"><span class="comment">-- 这里的sleep会占用大量资源 正常逻辑不能使用</span></span><br><span class="line"></span><br><span class="line">test_coroutine = coroutine.<span class="built_in">create</span>(</span><br><span class="line"><span class="function"><span class="keyword">function</span><span class="params">()</span></span></span><br><span class="line"><span class="keyword">for</span> i = <span class="number">1</span>, <span class="number">10</span>, <span class="number">1</span> <span class="keyword">do</span></span><br><span class="line"><span class="built_in">print</span>(i)</span><br><span class="line">sleep(<span class="number">0.1</span>)</span><br><span class="line">coroutine.<span class="built_in">yield</span>()</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"><span class="keyword">end</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">do_cro</span><span class="params">(co)</span></span></span><br><span class="line"><span class="keyword">while</span>(coroutine.<span class="built_in">status</span>(co) ~=<span class="string">"dead"</span>) <span class="keyword">do</span></span><br><span class="line">coroutine.<span class="built_in">resume</span>(co)</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"></span><br><span class="line">do_cro(test_coroutine)</span><br></pre></td></tr></table></figure><h1 id="面向对象"><a href="#面向对象" class="headerlink" title="面向对象"></a>面向对象</h1><p>用table实现了类与继承<br><figure class="highlight lua"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 类</span></span><br><span class="line"><span class="comment">-- 类管理器 </span></span><br><span class="line">CClassManager = &#123;&#125;</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">CClassManager.ctor</span><span class="params">(cls, ...)</span></span></span><br><span class="line">  <span class="keyword">local</span> this = &#123;&#125;</span><br><span class="line">  <span class="built_in">setmetatable</span>(this, cls)</span><br><span class="line">  cls.<span class="built_in">__index</span> = cls  <span class="comment">-- 将元表的__index设为自身，访问表的属性不存在时会搜索元表</span></span><br><span class="line">  cls.init(this, ...)</span><br><span class="line">  <span class="keyword">return</span> this</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">CClassManager.VInit</span><span class="params">(self, ...)</span></span></span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">CClassManager.init</span><span class="params">(self, ...)</span></span></span><br><span class="line">  self:VInit(...)</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">CClassManager.dtor</span><span class="params">(cls)</span></span></span><br><span class="line">  <span class="comment">-- do sth</span></span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">-- 通过继承实现的类的定义</span></span><br><span class="line">ClassT = CClassManager:ctor()</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">ClassT.VInit</span><span class="params">(self, word)</span></span></span><br><span class="line">  self.word = word</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">ClassT.say</span><span class="params">(self)</span></span></span><br><span class="line">  <span class="built_in">print</span>(self.word)</span><br><span class="line"><span class="keyword">end</span></span><br><span class="line"></span><br><span class="line">test = ClassT:ctor(<span class="string">"B"</span>)</span><br><span class="line">test:say()</span><br><span class="line">test:dtor()</span><br><span class="line">test:say()</span><br></pre></td></tr></table></figure></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;两年没有碰过Lua了，总觉得得要捡起来。现在从头到尾再过一遍，总结一些东西。之前根据菜鸟学的时候，使用了5.1.1的版本。与现在常用的版本相悖。因此这次我使用了：zerobrane studio，它可以方便切换版本，能实现很好的练习效果。&lt;/p&gt;
&lt;h1 id=&quot;关于多行注
      
    
    </summary>
    
    
      <category term="Lua" scheme="http://www.z16388.top/tags/Lua/"/>
    
      <category term="游戏" scheme="http://www.z16388.top/tags/%E6%B8%B8%E6%88%8F/"/>
    
  </entry>
  
  <entry>
    <title>EFK日志分析系统的搭建</title>
    <link href="http://www.z16388.top/2021/05/06/efk/"/>
    <id>http://www.z16388.top/2021/05/06/efk/</id>
    <published>2021-05-06T17:22:01.000Z</published>
    <updated>2026-04-18T12:45:50.159Z</updated>
    
    <content type="html"><![CDATA[<h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><blockquote><p>EFK 是三个开源软件的缩写，Elasticsearch，FileBeat，Kibana。其中 ELasticsearch 负责日志分析和存储，FileBeat 负责日志收集，Kibana 负责界面展示。它们之间互相配合使用，完美衔接，高效的满足了很多场合的应用，是目前主流的一种日志分析系统解决方案。</p></blockquote><blockquote><p>EFK 和 ELK 只有一个区别， 收集日志的组件由 Logstash 替换成了 FileBeat，因为 Filebeat 相对于 Logstash 来说有2个好处:<br>1.侵入低，无需修改 elasticsearch 和 kibana 的配置；<br>2.性能高，IO 占用率比 logstash 小太多</p></blockquote><blockquote><p>当然 Logstash 相比于 FileBeat 也有一定的优势，比如 Logstash 对于日志的格式化处理能力，FileBeat 只是将日志从日志文件中读取出来，当然如果收集的日志本身是有一定格式的，FileBeat 也可以格式化，但是相对于Logstash 来说，效果差很多。</p></blockquote><h2 id="部署步骤"><a href="#部署步骤" class="headerlink" title="部署步骤"></a>部署步骤</h2><p><strong>1 .  安装Docker</strong></p><p><strong>2 .  下载所需镜像</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">docker pull elasticsearch:7.12.0</span><br><span class="line">docker pull kibana:7.12.0</span><br><span class="line">docker pull store/elastic/filebeat:7.12.0</span><br></pre></td></tr></table></figure><p><strong>3 .  创建自定义网络</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker network create elk_net</span><br></pre></td></tr></table></figure><p><strong>4 .  启动Elasticsearch和Kibana</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">docker run -d --name elasticsearch --net elk_net -p 9200:9200 -p 9300:9300 -e &quot;discovery.type=single-node&quot; elasticsearch:7.12.0</span><br><span class="line">docker run -d --name kibana --net elk_net -p 5601:5601 kibana:7.12.0</span><br></pre></td></tr></table></figure><p>如果希望使用中文界面（中文化不完全，不推荐使用），可以进入kibana的容器里，修改排至文件，在现有配置文件中加一行中文相关的配置即可：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">server.name: kibana</span><br><span class="line">server.host: &quot;0&quot;</span><br><span class="line">elasticsearch.hosts: [ &quot;http://elasticsearch:9200&quot; ]</span><br><span class="line">monitoring.ui.container.elasticsearch.enabled: true</span><br><span class="line">// 设置语言为中文↓</span><br><span class="line">i18n.locale: &quot;zh-CN&quot;</span><br></pre></td></tr></table></figure><p>进入docker容器的指令为：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker exec -it kibana /bin/bash</span><br></pre></td></tr></table></figure><p><strong>5 .  配置日志解析规则</strong><br>日志解析的规则，是存放在Elasticsearch中的。只要通过curl命令即可实现向es中插入数据。<br>新建json文件：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  &quot;grok&quot;: &#123;</span><br><span class="line">    &quot;field&quot;: &quot;message&quot;,</span><br><span class="line">    &quot;patterns&quot;: [</span><br><span class="line">      &quot;%&#123;TIMESTAMP_ISO8601:Time&#125;\\s\\s*\\[%&#123;DATA:ServerType&#125;\\]*\\[%&#123;DATA:ServerID&#125;\\]*\\[%&#123;LOGLEVEL:Level&#125;\\s+\\]*\\[%&#123;DATA:Func&#125;\\]%&#123;GREEDYDATA:Log&#125;&quot;</span><br><span class="line">    ],</span><br><span class="line">    &quot;pattern_definitions&quot;: &#123;</span><br><span class="line">      &quot;ALL_CODE&quot;: &quot;(.|\\n)*&quot;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;,</span><br><span class="line">&#123;</span><br><span class="line">  &quot;date&quot;: &#123;</span><br><span class="line">    &quot;field&quot;: &quot;Time&quot;,</span><br><span class="line">    &quot;formats&quot;: [</span><br><span class="line">      &quot;ISO8601&quot;</span><br><span class="line">    ],</span><br><span class="line">    &quot;target_field&quot;: &quot;@timestamp&quot;,</span><br><span class="line">    &quot;timezone&quot;: &quot;Asia/Shanghai&quot;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;,</span><br><span class="line">&#123;</span><br><span class="line">  &quot;remove&quot;: &#123;</span><br><span class="line">    &quot;field&quot;: &quot;message&quot;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;,</span><br><span class="line">&#123;</span><br><span class="line">  &quot;remove&quot;: &#123;</span><br><span class="line">    &quot;field&quot;: &quot;Time&quot;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>patterns部分为解析每行日志的正则表达式，pattern_definitions是处理换行标志。<br>测试可以使用kibana自带的grok测试工具，在设置界面会有。<br>下方的date部分，是通过对上方产生的Time字段，存放到默认的时间戳上，用于处理排序。<br>处理完成后，把多余的字段删除，特别是输入的message，有利于缩减入库数据的量。<br>需要注意的是，json文件里的反斜杠一定要进行转义。</p><p>执行命令：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">curl -H &quot;Content-Type: application/json&quot; -XPUT &apos;http://192.168.3.67:9200/_ingest/pipeline/lmyzpip&apos; -d@/home/docker/pipline/pip.json</span><br></pre></td></tr></table></figure><p>除此之外，可以登录Kibana界面，通过可视化界面配置解析。</p><ul><li>点击左侧的三条线按钮，进入Stack Management-&gt;Ingest Node Pipelines-&gt;Create a pipeline</li><li>输入名称和描述</li><li>点击下方Add a processor，增加处理方式</li><li>填写相关参数，点击Add保存</li></ul><p>右侧Add documents可以填写测试用例，测试相关配置是否正确（通过直接写入ES的配置也可以在此测试）。</p><p>测试数据的格式为：</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">[</span><br><span class="line">    &#123;<span class="attr">"_index"</span>:<span class="string">"index"</span>,</span><br><span class="line">        <span class="attr">"_id"</span>:<span class="string">"id"</span>,</span><br><span class="line">        <span class="attr">"_source"</span>:&#123;<span class="attr">"message"</span>:<span class="string">"2021-04-29T15:42:05.000000  [Game][4][DEBUG   ][CNetManager::_SendServerConfigRequest]Request for server-config, Stream-&#123;Game: 4-0&#125;. ServerConfig&lt;2&gt; DBConfig&lt;0&gt; RedisConfig&lt;0&gt;"</span>&#125;</span><br><span class="line">    &#125;</span><br><span class="line">]</span><br></pre></td></tr></table></figure><p><strong>6 .  安装filebeat</strong><br>新增配置文件filebeat.docker.yml：</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#=========================== Filebeat inputs ==============</span></span><br><span class="line"><span class="attr">filebeat.inputs:</span></span><br><span class="line"></span><br><span class="line"><span class="bullet">-</span> <span class="attr">type:</span> <span class="string">log</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">enabled:</span> <span class="literal">true</span></span><br><span class="line">  <span class="comment">##配置你要收集的日志目录，可以配置多个目录</span></span><br><span class="line">  <span class="attr">paths:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="string">/home/docker/logs/*.log</span></span><br><span class="line"></span><br><span class="line"><span class="comment">## 设置kibana的地址，开始filebeat的可视化  </span></span><br><span class="line"><span class="attr">setup.kibana.host:</span> <span class="string">"http://kibana:5601"</span></span><br><span class="line"><span class="attr">setup.dashboards.enabled:</span> <span class="literal">true</span></span><br><span class="line"><span class="comment">#-------------------------- Elasticsearch output ---------</span></span><br><span class="line"><span class="attr">output.elasticsearch:</span></span><br><span class="line">    <span class="attr">hosts:</span> <span class="string">["elasticsearch:9200"]</span></span><br><span class="line">    <span class="attr">pipeline:</span> <span class="string">"lmyzpip"</span></span><br><span class="line"></span><br><span class="line"><span class="attr">setup.template.name:</span> <span class="string">"my-log"</span></span><br><span class="line"><span class="attr">setup.template.pattern:</span> <span class="string">"my-log-*"</span></span><br><span class="line"><span class="attr">json.keys_under_root:</span> <span class="literal">false</span></span><br><span class="line"><span class="attr">json.overwrite_keys:</span> <span class="literal">true</span></span><br></pre></td></tr></table></figure><p>其中需要注意的是，如果filebeat和前面的EK两个东西，没有部署在同一台机器上，需要把容器名改成对应的ip地址。</p><p>运行Filebeat：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker run -d --net elk_net -v /home/docker/filebeat/filebeat.docker.yml:/usr/share/filebeat/filebeat.yml -v /home/docker/logs/:/home/docker/logs/ --link elasticsearch:elasticsearch --link kibana:kibana  --name filebeat docker.io/store/elastic/filebeat:7.12.0</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;简介&quot;&gt;&lt;a href=&quot;#简介&quot; class=&quot;headerlink&quot; title=&quot;简介&quot;&gt;&lt;/a&gt;简介&lt;/h2&gt;&lt;blockquote&gt;
&lt;p&gt;EFK 是三个开源软件的缩写，Elasticsearch，FileBeat，Kibana。其中 ELasticse
      
    
    </summary>
    
    
      <category term="运维" scheme="http://www.z16388.top/tags/%E8%BF%90%E7%BB%B4/"/>
    
  </entry>
  
  <entry>
    <title>使用贝塞尔曲线实现道具随机飞动效果</title>
    <link href="http://www.z16388.top/2020/12/12/bezier/"/>
    <id>http://www.z16388.top/2020/12/12/bezier/</id>
    <published>2020-12-12T21:03:53.000Z</published>
    <updated>2026-04-18T12:45:50.159Z</updated>
    
    <content type="html"><![CDATA[<p>工作中，遇到了一个需求是要实现获得道具和货币的飞动效果：</p><ol><li>根据道具的多少生成不同数目的道具</li><li>货币首先要有一个炸开的效果，然后向一个点汇集；道具从原位置沿直线飞过去</li><li>balabala</li></ol><p>这里只讨论货币飞行路线的问题。</p><p>贝塞尔曲线(Bézier curve)，又称贝兹曲线或贝济埃曲线，是应用于二维图形应用程序的数学曲线。PS中的钢笔工具就是使用贝塞尔曲线来绘制矢量曲线的。</p><p>这里使用简单的，四个点确定的贝塞尔曲线来实现飞行轨迹。首先p0和p3分别是移动的起点和终点。为了模拟爆炸效果，可以通过随机选取以p0为圆心，长度为R的圆上的点，调整曲线的第一次弯折位置实现。这一点定为P1。最后，根据P1点和P0点之间的关系，进行x轴或者y轴的修正，实现曲线平滑延申到p3，这一点是p2点。</p><p>p1点（爆炸点）的获取方式：<br><figure class="highlight cs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">static</span> Vector3 <span class="title">GetRandomPosition</span>(<span class="params">Vector3 vec</span>)</span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">float</span> sita = UnityEngine.Random.Range(-Mathf.PI, Mathf.PI);</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> Vector3(vec.x + Mathf.Cos(sita) * Screen.width / <span class="number">8</span>, vec.y + Mathf.Sin(sita) * Screen.width / <span class="number">8</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p><p>p2点（修正点）的获取方式：<br><figure class="highlight cs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">static</span> Vector3 <span class="title">GetFixedPoint</span>(<span class="params">Vector3 start, Vector3 end</span>)</span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> Vector3(start.x + <span class="number">3</span>*(end.x - start.x)/<span class="number">4</span>, start.y + <span class="number">3</span> * (end.y - start.y) / <span class="number">4</span> + p1.y &gt; start.y ? Screen.height / <span class="number">15</span> : - Screen.height / <span class="number">15</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p><p>根据已知的四个点，实现物体延贝塞尔曲线移动的效果。</p><figure class="highlight cs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"><span class="doctag">///</span> <span class="doctag">&lt;summary&gt;</span></span></span><br><span class="line"><span class="comment"><span class="doctag">///</span> 延贝塞尔曲线移动</span></span><br><span class="line"><span class="comment"><span class="doctag">///</span> <span class="doctag">&lt;/summary&gt;</span></span></span><br><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">static</span> IEnumerator <span class="title">MoveBezier</span>(<span class="params">GComponent gcom, <span class="keyword">float</span> time, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3</span>)</span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">float</span> t = <span class="number">0</span>; t &lt; time; t += Time.deltaTime)</span><br><span class="line">    &#123;</span><br><span class="line">        gcom.position = CalculateCubicBezierPoint(t / time, p0, p1, p2, p3);</span><br><span class="line">        <span class="keyword">yield</span> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    gcom.position = p3;</span><br><span class="line">    gcom.Dispose();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment"><span class="doctag">///</span> <span class="doctag">&lt;summary&gt;</span></span></span><br><span class="line"><span class="comment"><span class="doctag">///</span> 计算贝塞尔曲线点的坐标</span></span><br><span class="line"><span class="comment"><span class="doctag">///</span> <span class="doctag">&lt;/summary&gt;</span></span></span><br><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">static</span> Vector3 <span class="title">CalculateCubicBezierPoint</span>(<span class="params"><span class="keyword">float</span> t, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3</span>)</span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">float</span> u = <span class="number">1</span> - t;</span><br><span class="line">    <span class="keyword">float</span> tt = t * t;</span><br><span class="line">    <span class="keyword">float</span> uu = u * u;</span><br><span class="line">    <span class="keyword">float</span> uuu = uu * u;</span><br><span class="line">    <span class="keyword">float</span> ttt = tt * t;</span><br><span class="line"></span><br><span class="line">    Vector3 p = uuu * p0;</span><br><span class="line">    p += <span class="number">3</span> * uu * t * p1;</span><br><span class="line">    p += <span class="number">3</span> * u * tt * p2;</span><br><span class="line">    p += ttt * p3;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> p;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;工作中，遇到了一个需求是要实现获得道具和货币的飞动效果：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;根据道具的多少生成不同数目的道具&lt;/li&gt;
&lt;li&gt;货币首先要有一个炸开的效果，然后向一个点汇集；道具从原位置沿直线飞过去&lt;/li&gt;
&lt;li&gt;balabala&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这
      
    
    </summary>
    
    
      <category term="Unity" scheme="http://www.z16388.top/tags/Unity/"/>
    
      <category term="游戏" scheme="http://www.z16388.top/tags/%E6%B8%B8%E6%88%8F/"/>
    
  </entry>
  
  <entry>
    <title>震惊，JS不加分号会造成错误！？</title>
    <link href="http://www.z16388.top/2019/12/02/%E9%9C%87%E6%83%8Ajs/"/>
    <id>http://www.z16388.top/2019/12/02/震惊js/</id>
    <published>2019-12-02T00:12:19.000Z</published>
    <updated>2026-04-18T12:45:50.163Z</updated>
    
    <content type="html"><![CDATA[<p>在之前的工作中，我遇到了一个奇怪的问题。明明在语法上没有问题，找同事也看了，但是程序依旧会产生奇怪的错误。最后通过一步一步断点，定为了错误位置，才找到了造成这个错误的原因———在一个不需要分号的语言中，句末不加分号居然报错了。</p><p>不卖关子了，这个错误是多返回值函数造成了对上一句值的影响。下面举个例子：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">func</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> [<span class="number">1</span>, <span class="number">2</span>]</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> b = <span class="number">0</span></span><br><span class="line"><span class="keyword">let</span> c = <span class="number">0</span></span><br><span class="line"><span class="keyword">let</span> a = <span class="number">3</span></span><br><span class="line">[b, c] = func();</span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">"a is :"</span> + a)</span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">"b is :"</span> + b + <span class="string">" c is :"</span> + c)</span><br></pre></td></tr></table></figure><p>运行的结果将会是这样:</p><blockquote><p>a is :1,2<br>b is :0 c is :0</p></blockquote><p>很容易看到，我们函数的返回值给了上一行的a。这是因为我们的编译器将代码认为了：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> a = <span class="number">3</span> ,[b, c] = func();</span><br></pre></td></tr></table></figure><p>避免这种情况，还是要多加分号吧——虽然它并不会报错。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;在之前的工作中，我遇到了一个奇怪的问题。明明在语法上没有问题，找同事也看了，但是程序依旧会产生奇怪的错误。最后通过一步一步断点，定为了错误位置，才找到了造成这个错误的原因———在一个不需要分号的语言中，句末不加分号居然报错了。&lt;/p&gt;
&lt;p&gt;不卖关子了，这个错误是多返回值函
      
    
    </summary>
    
    
      <category term="JavaScript" scheme="http://www.z16388.top/tags/JavaScript/"/>
    
  </entry>
  
  <entry>
    <title>Linux升级Python</title>
    <link href="http://www.z16388.top/2019/11/28/linuxuppy/"/>
    <id>http://www.z16388.top/2019/11/28/linuxuppy/</id>
    <published>2019-11-28T12:12:19.000Z</published>
    <updated>2026-04-18T12:45:50.160Z</updated>
    
    <content type="html"><![CDATA[<p>11月底，腾讯云搞了一波双11返场活动，我买了三年的服务器。</p><p>和买了新的电脑或者做了新系统一样，得先把生产环境搞好。</p><p>距离Python2.x停止维护大概只有5个月了吧，所以第一要务是升级Python的版本。但是yum是依赖Python2的，所以升级还是会有一些顾虑的。下面是升级的过程：</p><h1 id="下载、解压"><a href="#下载、解压" class="headerlink" title="下载、解压"></a>下载、解压</h1><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">wget https://www.python.org/ftp/python/3.8.0/Python-3.8.0.tgz</span><br><span class="line">tar -zxvf Python-3.8.0.tgz</span><br></pre></td></tr></table></figure><h1 id="安装编译环境"><a href="#安装编译环境" class="headerlink" title="安装编译环境"></a>安装编译环境</h1><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">yum install make build-essential libssl-dev zlib1g-dev libbz2-dev</span><br><span class="line">yum install zlib</span><br></pre></td></tr></table></figure><h1 id="编译、安装"><a href="#编译、安装" class="headerlink" title="编译、安装"></a>编译、安装</h1><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">yum install -y make build-essential libssl-dev zlib1g-dev libbz2-dev</span><br><span class="line">yum -y install zlib</span><br><span class="line"></span><br><span class="line">cd Python-3.8.0</span><br><span class="line">./configure</span><br><span class="line">make &amp;&amp; make install</span><br></pre></td></tr></table></figure><h1 id="备份与配置"><a href="#备份与配置" class="headerlink" title="备份与配置"></a>备份与配置</h1><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">mv /usr/bin/python /usr/bin/python.bak</span><br><span class="line">ln -s /usr/local/bin/python3 /usr/bin/python</span><br></pre></td></tr></table></figure><h1 id="保证yum可用"><a href="#保证yum可用" class="headerlink" title="保证yum可用"></a>保证yum可用</h1><p>将下面文件中的配置修改为Python2.x版本的路径。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">/usr/bin/yum</span><br><span class="line">/usr/libexec/urlgrabber-ext-down</span><br></pre></td></tr></table></figure><h1 id="安装pip"><a href="#安装pip" class="headerlink" title="安装pip"></a>安装pip</h1><p>pip需要依赖setuptools，所以要先安装setuptools。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">wget https://files.pythonhosted.org/packages/ce/1d/96320b9784b04943c924a9f1c6fa49124a1542039ce098a5f9a369227bad/setuptools-42.0.1.zip</span><br><span class="line">unzip setuptools-42.0.1.zip</span><br><span class="line">cd setuptools-42.0.1</span><br><span class="line">python setup.py build</span><br><span class="line">python setup.py install</span><br><span class="line"></span><br><span class="line">wget https://files.pythonhosted.org/packages/ce/ea/9b445176a65ae4ba22dce1d93e4b5fe182f953df71a145f557cffaffc1bf/pip-19.3.1.tar.gz</span><br><span class="line">tar -zxvf pip-19.3.1.tar.gz</span><br><span class="line">cd pip-19.3.1</span><br><span class="line">python setup.py build</span><br><span class="line">python setup.py install</span><br></pre></td></tr></table></figure><h1 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h1><p><a href="https://www.cnblogs.com/zhangym/p/6226435.html" target="_blank" rel="noopener">https://www.cnblogs.com/zhangym/p/6226435.html</a><br><a href="https://www.cnblogs.com/fjping0606/p/9156344.html" target="_blank" rel="noopener">https://www.cnblogs.com/fjping0606/p/9156344.html</a><br><a href="https://www.cnblogs.com/fyly/p/11112169.html" target="_blank" rel="noopener">https://www.cnblogs.com/fyly/p/11112169.html</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;11月底，腾讯云搞了一波双11返场活动，我买了三年的服务器。&lt;/p&gt;
&lt;p&gt;和买了新的电脑或者做了新系统一样，得先把生产环境搞好。&lt;/p&gt;
&lt;p&gt;距离Python2.x停止维护大概只有5个月了吧，所以第一要务是升级Python的版本。但是yum是依赖Python2的，所以升
      
    
    </summary>
    
    
      <category term="Python" scheme="http://www.z16388.top/tags/Python/"/>
    
      <category term="Linux" scheme="http://www.z16388.top/tags/Linux/"/>
    
  </entry>
  
  <entry>
    <title>Github图床工具</title>
    <link href="http://www.z16388.top/2019/11/17/picupdate/"/>
    <id>http://www.z16388.top/2019/11/17/picupdate/</id>
    <published>2019-11-17T18:32:44.000Z</published>
    <updated>2026-04-18T12:45:50.160Z</updated>
    
    <content type="html"><![CDATA[<p>这是一个上传图片到github的工具，目前还不是很成熟，不过已经可以实现压缩并上传图片的目的了，对于写博客来说已经够用了。</p><h1 id="使用步骤"><a href="#使用步骤" class="headerlink" title="使用步骤"></a>使用步骤</h1><ol><li>创建todo目录</li><li>创建pic目录，在github上创建一个空项目，然后pull到这里</li><li>修改配置文件，将git_url修改为上一步新建的项目</li><li>将图片放到todo文件夹下</li><li>执行工具</li></ol><p>需要注意的是，因为图床需要一个git目录，同时代码也需要。在使用部分git管理工具时会禁止这种目录的嵌套。因此最好将代码独立运行。可以自己打包，也可以使用我打好的可执行程序。</p><p>在这里需要提一句，一般如果只想要下载github上项目的一个目录或者一个文件，可以使用svn进行下载。将文件路径中的<code>文件名/master</code>替换为<code>trunk</code>即可使用下载。</p><p>经过配置之后，以后只需要将图片放到todo目录下，执行脚本即可。</p><p>编译时需要安装以下运行库</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">pip install pyyaml</span><br><span class="line">pip install gitpython</span><br><span class="line">pip install pillow</span><br></pre></td></tr></table></figure><h1 id="更新文档"><a href="#更新文档" class="headerlink" title="更新文档"></a>更新文档</h1><p>Ver.0.2 2019-11-17 提交编译的可执行程序；增加配置文件</p><p>Ver.0.1 2019-11-12 提交项目</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;这是一个上传图片到github的工具，目前还不是很成熟，不过已经可以实现压缩并上传图片的目的了，对于写博客来说已经够用了。&lt;/p&gt;
&lt;h1 id=&quot;使用步骤&quot;&gt;&lt;a href=&quot;#使用步骤&quot; class=&quot;headerlink&quot; title=&quot;使用步骤&quot;&gt;&lt;/a&gt;使用步骤&lt;
      
    
    </summary>
    
    
      <category term="Python" scheme="http://www.z16388.top/tags/Python/"/>
    
      <category term="Github" scheme="http://www.z16388.top/tags/Github/"/>
    
  </entry>
  
  <entry>
    <title>JS使用replace()函数全部替换</title>
    <link href="http://www.z16388.top/2019/11/16/jsreplace/"/>
    <id>http://www.z16388.top/2019/11/16/jsreplace/</id>
    <published>2019-11-16T22:03:56.000Z</published>
    <updated>2026-04-18T12:45:50.160Z</updated>
    
    <content type="html"><![CDATA[<p>在处理爬虫爬取下来的数据时，遇到了在文字中出现了经过转义的换行符，在文中显示出了\n，很影响观赏效果。因此，我对内容做了处理。</p><p>但是在刷库的过程中，我发现，我总不能一次处理完所有的数据。后来发现是JavaScript的Replace函数的问题，这个函数默认只能替换第一个匹配到的项目。如果需要处理全部的，需要使用正则表达式：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">string.replace(<span class="regexp">/\\n/g</span>, <span class="string">"\n"</span>)</span><br></pre></td></tr></table></figure><p>除此之外，下面是一些处理爬取内容常用操作，包含了html的转义：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">string.replace(<span class="regexp">/&amp;nbsp;/g</span>, <span class="string">' '</span>)</span><br><span class="line">string.replace(<span class="regexp">/&amp;lt;/g</span>, <span class="string">'&lt;'</span>)</span><br><span class="line">string.replace(<span class="regexp">/&amp;gt;/g</span>, <span class="string">'&gt;'</span>)</span><br><span class="line">string.replace(<span class="regexp">/&amp;amp;/g</span>, <span class="string">'&amp;'</span>)</span><br><span class="line">string.replace(<span class="regexp">/&amp;quot;/g</span>, <span class="string">'"'</span>)</span><br><span class="line">   string.replace(<span class="regexp">/&amp;#x3D;/g</span>, <span class="string">'='</span>)</span><br><span class="line">   string.replace(<span class="regexp">/\[.*?\]/g</span>,<span class="string">''</span>)</span><br><span class="line">   string.replace(<span class="string">"\\n"</span>,<span class="string">"\n"</span>)</span><br><span class="line">   string.replace(<span class="string">"\\t"</span>,<span class="string">""</span>)</span><br><span class="line">   string.replace(<span class="string">"\\r"</span>,<span class="string">""</span>)</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;在处理爬虫爬取下来的数据时，遇到了在文字中出现了经过转义的换行符，在文中显示出了&#92;n，很影响观赏效果。因此，我对内容做了处理。&lt;/p&gt;
&lt;p&gt;但是在刷库的过程中，我发现，我总不能一次处理完所有的数据。后来发现是JavaScript的Replace函数的问题，这个函数默认只能
      
    
    </summary>
    
    
      <category term="JavaScript" scheme="http://www.z16388.top/tags/JavaScript/"/>
    
  </entry>
  
  <entry>
    <title>JS使用Splice()函数操作数组</title>
    <link href="http://www.z16388.top/2019/11/16/jssplice/"/>
    <id>http://www.z16388.top/2019/11/16/jssplice/</id>
    <published>2019-11-16T21:59:56.000Z</published>
    <updated>2026-04-18T12:45:50.160Z</updated>
    
    <content type="html"><![CDATA[<p>在js的使用过程中，有一次需要对数组进行各种操作，一时间迫使我想要去使用链表。后来通过查阅资料，总结了下面的一些方法，主要使用了splice()函数。</p><p>下面的方法主要是使用下标进行操作。如果是用值的话，可以通过<code>indexOf()</code>函数来获取下标。若不存在则返回-1。</p><p>值交换</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">swap_arr</span>(<span class="params">a_list, index1, index2</span>) </span>&#123;</span><br><span class="line">    a_list[index1] = a_list.splice(index2, <span class="number">1</span>, a_list[index1])[<span class="number">0</span>];</span><br><span class="line">    <span class="keyword">return</span> a_list;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>置顶</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">up_arr</span>(<span class="params">a_list, index</span>)</span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(index!=<span class="number">0</span> &amp;&amp; index!=<span class="number">-1</span>)&#123;</span><br><span class="line">        a_list[index] = a_list.splice(index<span class="number">-1</span>, <span class="number">1</span>, a_list[index])[<span class="number">0</span>];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>下移</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">down_arr</span>(<span class="params">a_list, index</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(index!=a_list.length<span class="number">-1</span> &amp;&amp; index!=<span class="number">-1</span>)&#123;</span><br><span class="line">        a_list[index] = a_list.splice(index+<span class="number">1</span>, <span class="number">1</span>, a_list[index])[<span class="number">0</span>];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>插入</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">ins_arr</span>(<span class="params">a_list, index, a_data</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(index!=<span class="number">-1</span>)&#123;</span><br><span class="line">        <span class="keyword">if</span> (a_list.indexOf(a_data)==<span class="number">-1</span>) &#123;</span><br><span class="line">            a_list.splice(index+<span class="number">1</span>, <span class="number">0</span>, a_data);</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>在顶部插入</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">topins_arr</span>(<span class="params">a_list, a_data</span>) </span>&#123;</span><br><span class="line">    a_list.splice(<span class="number">0</span>, <span class="number">0</span>, a_data)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>删除元素</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">del_arr</span>(<span class="params">a_list, a_data_list</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">const</span> ele <span class="keyword">of</span> a_data_list) &#123;</span><br><span class="line">        <span class="keyword">let</span> index = a_list.indexOf(ele);</span><br><span class="line">        <span class="keyword">if</span>(index!=<span class="number">-1</span>)&#123;</span><br><span class="line">            a_list.splice(index, <span class="number">1</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;在js的使用过程中，有一次需要对数组进行各种操作，一时间迫使我想要去使用链表。后来通过查阅资料，总结了下面的一些方法，主要使用了splice()函数。&lt;/p&gt;
&lt;p&gt;下面的方法主要是使用下标进行操作。如果是用值的话，可以通过&lt;code&gt;indexOf()&lt;/code&gt;函数来
      
    
    </summary>
    
    
      <category term="JavaScript" scheme="http://www.z16388.top/tags/JavaScript/"/>
    
  </entry>
  
  <entry>
    <title>当你的程序连接Mysql然后崩溃时</title>
    <link href="http://www.z16388.top/2019/11/16/mysqltimeout/"/>
    <id>http://www.z16388.top/2019/11/16/mysqltimeout/</id>
    <published>2019-11-16T21:43:56.000Z</published>
    <updated>2026-04-18T12:45:50.160Z</updated>
    
    <content type="html"><![CDATA[<p>之前写过一个监控mysql数据库更新状态的预警程序，总是莫名其妙的报一个连接错误的错，然后程序死掉。后来在系统趋于稳定之后，我就没再继续维护这个工具了。</p><p>但是最近我在写另一个工具时，遇到了一个奇怪的问题，就是：tick总在27000多左右的时候崩溃。</p><p>我进行了一系列的猜测，比如tick的代码，或者是逻辑有问题，最后我把思路放在了之前遇到的这个错误上。查阅资料后发现，MySQL数据库在连接之后，如果超过一个设定的时间戳之后，会断开。这个值叫<code>WAIT_TIMEOUT</code>，默认值是28800，也就是说如果连上MySQL数据库之后，8小时内没有进行操作，这个连接便会断开。</p><p>网上很多连接MySQL数据库的代码没有处理过超时连接的问题，就连JS的官方代码好像也是在17年之后才更新的。以往这个问题，大家都是通过修改这个值来进行规避的。比如改成300天。修改有两种方式，一种是修改配置文件，这样在启动时便会使用这个配置；另一种是修改这个值，或者全局，或者当次生效。</p><p>下面是我在使用JavaScript语言链接MySQL数据库时，处理超时重连问题的代码：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">this</span>.config = &#123;</span><br><span class="line">    <span class="string">"host"</span>: <span class="string">"x.x.x.x"</span>,</span><br><span class="line"><span class="string">"port"</span>: xxxx,</span><br><span class="line"><span class="string">"user"</span>: <span class="string">"root"</span>,</span><br><span class="line"><span class="string">"password"</span>: <span class="string">"pass"</span>,</span><br><span class="line"><span class="string">"database"</span>: <span class="string">"name"</span><span class="string">"</span></span><br><span class="line"><span class="string">&#125;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">async connect() &#123;</span></span><br><span class="line"><span class="string">    let self = this;</span></span><br><span class="line"><span class="string">    console.log("</span>connect mysql success <span class="keyword">with</span><span class="string">", JSON.stringify(this.config))</span></span><br><span class="line"><span class="string">    // 创建连接</span></span><br><span class="line"><span class="string">    this.db_mysql = mysql.createConnection(</span></span><br><span class="line"><span class="string">        this.config</span></span><br><span class="line"><span class="string">    );</span></span><br><span class="line"><span class="string">    // 连接数据库</span></span><br><span class="line"><span class="string">    await this.db_mysql.connect();</span></span><br><span class="line"><span class="string">    // 错误处理</span></span><br><span class="line"><span class="string">    this.db_mysql.on('error', function(err) &#123;</span></span><br><span class="line"><span class="string">        if (err) &#123;</span></span><br><span class="line"><span class="string">            if (err.code === 'PROTOCOL_CONNECTION_LOST') &#123;</span></span><br><span class="line"><span class="string">                // 处理超时</span></span><br><span class="line"><span class="string">                console.warning("</span>start reconnect mysql<span class="string">");</span></span><br><span class="line"><span class="string">                self.connect();</span></span><br><span class="line"><span class="string">            &#125; else &#123;</span></span><br><span class="line"><span class="string">                console.error(err.stack || err);</span></span><br><span class="line"><span class="string">                console.warning("</span>start reconnect mysql<span class="string">");</span></span><br><span class="line"><span class="string">                self.connect();</span></span><br><span class="line"><span class="string">            &#125;</span></span><br><span class="line"><span class="string">        &#125;</span></span><br><span class="line"><span class="string">    &#125;);</span></span><br><span class="line"><span class="string">&#125;</span></span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;之前写过一个监控mysql数据库更新状态的预警程序，总是莫名其妙的报一个连接错误的错，然后程序死掉。后来在系统趋于稳定之后，我就没再继续维护这个工具了。&lt;/p&gt;
&lt;p&gt;但是最近我在写另一个工具时，遇到了一个奇怪的问题，就是：tick总在27000多左右的时候崩溃。&lt;/p&gt;

      
    
    </summary>
    
    
      <category term="JavaScript" scheme="http://www.z16388.top/tags/JavaScript/"/>
    
      <category term="MySQL" scheme="http://www.z16388.top/tags/MySQL/"/>
    
  </entry>
  
  <entry>
    <title>安卓应用闪屏</title>
    <link href="http://www.z16388.top/2019/11/16/AndroidSplash/"/>
    <id>http://www.z16388.top/2019/11/16/AndroidSplash/</id>
    <published>2019-11-16T21:19:56.000Z</published>
    <updated>2026-04-18T12:45:50.158Z</updated>
    
    <content type="html"><![CDATA[<p>去年在接入安卓SDK时，会有部分渠道有要求手写闪屏的情况，下面是当时的笔记，这只是最简单的一种方法。</p><h1 id="参考资料："><a href="#参考资料：" class="headerlink" title="参考资料："></a>参考资料：</h1><p>很好的例子：</p><p><a href="https://www.jianshu.com/p/a609f510b19a" target="_blank" rel="noopener">https://www.jianshu.com/p/a609f510b19a</a></p><p><a href="https://blog.csdn.net/l799069596/article/details/47094731" target="_blank" rel="noopener">https://blog.csdn.net/l799069596/article/details/47094731</a></p><p>安卓动画：<a href="https://blog.csdn.net/IO_Field/article/details/53101499" target="_blank" rel="noopener">https://blog.csdn.net/IO_Field/article/details/53101499</a></p><h1 id="背景："><a href="#背景：" class="headerlink" title="背景："></a>背景：</h1><p>除去游戏本身的闪屏之外，有的渠道会要求，有额外的渠道闪屏。为了使用一套资源出不同渠道包，我们可以对接渠道的AS工程进行处理，单独设置闪屏。</p><p>首先，创建一个闪屏Activity，为你的主Activity，这样在游戏的一开始你就可以看到闪屏了。</p><p>这里需要注意的是，你原先的Activit也需要在Manifest中注册打开日志，否则在打包的时候会找不到，报错：</p><p><a href="https://blog.csdn.net/qq_28301007/article/details/52265775" target="_blank" rel="noopener">https://blog.csdn.net/qq_28301007/article/details/52265775</a></p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">activity</span> <span class="attr">android:name</span>=<span class="string">"...Activity"</span>/&gt;</span></span><br></pre></td></tr></table></figure><p>下面是主Activity，也就是闪屏Activity的代码，需要根据AS的提示import缺少的部分。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> android.animation.ObjectAnimator;</span><br><span class="line"><span class="keyword">import</span> android.animation.ValueAnimator;</span><br><span class="line"><span class="keyword">import</span> android.app.Activity;</span><br><span class="line"><span class="keyword">import</span> android.content.Intent;</span><br><span class="line"><span class="keyword">import</span> android.os.Bundle;</span><br><span class="line"><span class="keyword">import</span> android.os.Handler;</span><br><span class="line"><span class="keyword">import</span> android.view.WindowManager;</span><br><span class="line"><span class="keyword">import</span> android.widget.ImageView;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">SplashActivity</span> <span class="keyword">extends</span> <span class="title">Activity</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> <span class="keyword">int</span> TimeAnimDurning = <span class="number">2000</span>;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> displayDeviceWidth;</span><br><span class="line">    ImageView iv_splash;</span><br><span class="line">    <span class="keyword">private</span> ObjectAnimator objAnim;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">onCreate</span><span class="params">(Bundle savedInstanceState)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>.onCreate(savedInstanceState);</span><br><span class="line">        displayDeviceWidth = getResources().getDisplayMetrics().widthPixels;</span><br><span class="line">        setContentView(R.layout.activity_splash);</span><br><span class="line">        iv_splash = (ImageView) findViewById(R.id.splash);</span><br><span class="line">        objAnim = ObjectAnimator.ofFloat(iv_splash,<span class="string">"alpha"</span>,<span class="number">1</span>,<span class="number">0</span>);</span><br><span class="line">        objAnim.setDuration(TimeAnimDurning);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">new</span> Handler().postDelayed(<span class="keyword">new</span> Runnable() &#123;</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">                objAnim.addUpdateListener(<span class="keyword">new</span> ValueAnimator.AnimatorUpdateListener() &#123;</span><br><span class="line">                    <span class="meta">@Override</span></span><br><span class="line">                    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onAnimationUpdate</span><span class="params">(ValueAnimator animation)</span> </span>&#123;</span><br><span class="line">                        <span class="keyword">if</span>((<span class="keyword">int</span>)animation.getAnimatedFraction() == <span class="number">1</span>)&#123;</span><br><span class="line">                            getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);</span><br><span class="line">                            startActivity(<span class="keyword">new</span> Intent(SplashActivity.<span class="keyword">this</span> , .YouActivity<span class="class">.<span class="keyword">class</span>))</span>;</span><br><span class="line">                            finish();</span><br><span class="line">                            <span class="keyword">return</span> ;</span><br><span class="line">                        &#125;</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;);</span><br><span class="line">                objAnim.start();</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">        &#125;, <span class="number">2000</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version="1.0" encoding="utf-8"?&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">RelativeLayout</span></span></span><br><span class="line"><span class="tag">    <span class="attr">xmlns:android</span>=<span class="string">"http://schemas.android.com/apk/res/android"</span></span></span><br><span class="line"><span class="tag">    <span class="attr">xmlns:tools</span>=<span class="string">"http://schemas.android.com/tools"</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_width</span>=<span class="string">"match_parent"</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_height</span>=<span class="string">"match_parent"</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:background</span>=<span class="string">"@color/white"</span></span></span><br><span class="line"><span class="tag">    <span class="attr">tools:context</span>=<span class="string">"com.unity3d.player.SplashActivity"</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">LinearLayout</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_width</span>=<span class="string">"match_parent"</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:layout_height</span>=<span class="string">"match_parent"</span></span></span><br><span class="line"><span class="tag">    <span class="attr">android:visibility</span>=<span class="string">"visible"</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">ImageView</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:id</span>=<span class="string">"@+id/splash"</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:layout_width</span>=<span class="string">"0dp"</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:layout_height</span>=<span class="string">"match_parent"</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:layout_weight</span>=<span class="string">"1"</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:scaleType</span>=<span class="string">"fitXY"</span></span></span><br><span class="line"><span class="tag">        <span class="attr">android:src</span>=<span class="string">"@drawable/splash"</span> /&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">LinearLayout</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">RelativeLayout</span>&gt;</span></span><br></pre></td></tr></table></figure><p>在上面控制闪屏格式的style.xml中，可以看到闪屏的背景色设置为了白色。这里有一些常用的颜色xml：<a href="https://blog.csdn.net/sundaysunshine/article/details/53509854" target="_blank" rel="noopener">https://blog.csdn.net/sundaysunshine/article/details/53509854</a></p><p>除了这两处之外，还需要根据style.xml中的配置，放好闪屏图片，设置闪屏背景。</p><p>整个闪屏的原理就是创建一个动画，在动画播放完成之后，去执行一个新的activity。在补全报错的部分之后，还是有一些细节部分需要注意的。</p><p>首先是结束时间的判定。判定时机总共有两种，一种是获取动画的进度，就像这里的例子，使用<code>(int)animation.getAnimatedFraction()</code>进行获取一个从0~1的数，来表示目前的动画的播放进度。除此之外还可以获取播放的时间，这个函数是：<code>getAnimatedValue()</code>，它可以获取属性的当前值。使用这两个函数可以很方便地控制动画的时间和动作。</p><p>除此之外，在调起另一个Activity之后，我结束了这个Activity。这是因为如果使用默认的LaunchMode，在重新唤醒应用时，闪屏会再次启动，然后走完动画，应用重启。这就造成了应用无法关闭的状况，只能后台强制杀掉。解决办法就是让闪屏只执行一次。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;去年在接入安卓SDK时，会有部分渠道有要求手写闪屏的情况，下面是当时的笔记，这只是最简单的一种方法。&lt;/p&gt;
&lt;h1 id=&quot;参考资料：&quot;&gt;&lt;a href=&quot;#参考资料：&quot; class=&quot;headerlink&quot; title=&quot;参考资料：&quot;&gt;&lt;/a&gt;参考资料：&lt;/h1&gt;&lt;p&gt;
      
    
    </summary>
    
    
      <category term="Android" scheme="http://www.z16388.top/tags/Android/"/>
    
  </entry>
  
  <entry>
    <title>安卓各渠道SDK接入体验</title>
    <link href="http://www.z16388.top/2019/11/12/mostsdk/"/>
    <id>http://www.z16388.top/2019/11/12/mostsdk/</id>
    <published>2019-11-12T23:00:23.000Z</published>
    <updated>2026-04-18T12:45:50.160Z</updated>
    
    <content type="html"><![CDATA[<p>去年的这个时候，我在忙于接入各种SDK。接渠道SDK，是一件十分薛定谔的事情。你觉得很容易，的确很容易，但是，也很容易遇到问题。然后我就陷入了长期的自闭状态，再加上偷懒，然后博客就断更了一年。现在回头来回忆一下，去年的这个时候，接入SDK时的那些体验。</p><blockquote><p>1.酷派</p></blockquote><p>充值之后，服务器收不到消息，对接也没有人。</p><p>现在看来很明显，已然黄了。</p><blockquote><p>2.应用宝</p></blockquote><p>传说中的5000人大群只有2个技术的大渠道。每天上午问问题会施舍你两句，下午是肯定不会回答问题的，团建能团建半个月。这个渠道我是使用聚合sdk接入的。需要注意的是，接入时有测试阶段，和正式阶段之分，游戏货币名不能修改，同时还必须接入腾讯的信鸽推送SDK，否则无法过审，手动接入成本极高。</p><blockquote><p>3.金立</p></blockquote><p>高版本会造成初次进入闪退，主动获取权限也不行，必须低版本编译。<br>华为手机会出现渲染错误，游戏变成紫红色。<br>需要安装支付插件。<br>现在也应该没有接入的必要了。</p><blockquote><p>4.华为</p></blockquote><p>相当棒的渠道，文档详细，对接起来体验也很不错。充值错误的时候，每一步骤，原因都会有显示。<br>但是不支持第三方工具接入。<br>需要安装支付插件。</p><blockquote><p>5.魅族</p></blockquote><p>商品id配置不明，会出现莫名的变动，很不靠谱。<br>支付回调生效需要1天的时间，需要对商品进行映射，对接很麻烦的渠道。<br>需要安装支付插件。</p><blockquote><p>6.360</p></blockquote><p>包体最大，足足有50多k的方法数，不分包就是死。</p><blockquote><p>7.百度</p></blockquote><p>方法数排名第二，仅次于360。<br>高版本编译会无法使用闪屏。<br>提审体验极差。说好的SDK不强用更，但是等到提审后告诉你不合格。</p><blockquote><p>8.联想</p></blockquote><p>商品id为自动生成，需要做好映射。<br>AnySDK接入需要注意参数顺序。</p><blockquote><p>9.UC</p></blockquote><p>无法使用第三方工具进行接入。<br>闪屏比较蛋疼，在sdk初始化时自动播放。首次运行时无法正常显示，时机不一定，容易和应用闪屏覆盖。</p><blockquote><p>10.OPPO、VIVO</p></blockquote><p>无法使用第三方工具进行接入。<br>需要安装支付插件。</p><blockquote><p>11.小七</p></blockquote><p>文档描述不明确，注意对登陆回调的处理方式，注重切换账号的测试。<br>SDK的Manifest中，最高宽高比设置为2.2。如果游戏中有对这个参数进行修改，需要进行统一。</p><blockquote><p>12.拇指玩</p></blockquote><p>sdk默认背景为透明，会造成有些版本的手机唤起sdk时会显示桌面为背景。或者是切换到主屏后，再回来，只有单独的sdk页面。<br>解决方式是把style.xml中的windowIsTranslucent值置为为false。<br>回调处理方式与其他sdk略有不同,Log与执行功能部分的代码进行了分离。<br>目前版本，无法使用qq登陆等方式，在登陆界面仍没有去掉该入口。</p><blockquote><p>其他:</p></blockquote><p>在运营过程中，小米、UC、应用宝和魅族会不同频率出现无法登录的问题，属正常现象，是他们的SDK服务器抽风了，会报一些很可怕的错误，比如应用不存在，应用id无效之类的。这时候只需要稳定好用户的心态即可，没有任何解决办法。 </p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;去年的这个时候，我在忙于接入各种SDK。接渠道SDK，是一件十分薛定谔的事情。你觉得很容易，的确很容易，但是，也很容易遇到问题。然后我就陷入了长期的自闭状态，再加上偷懒，然后博客就断更了一年。现在回头来回忆一下，去年的这个时候，接入SDK时的那些体验。&lt;/p&gt;
&lt;block
      
    
    </summary>
    
    
      <category term="Android" scheme="http://www.z16388.top/tags/Android/"/>
    
  </entry>
  
  <entry>
    <title>某微信爬虫工具多开方案</title>
    <link href="http://www.z16388.top/2019/11/12/most_wechat/"/>
    <id>http://www.z16388.top/2019/11/12/most_wechat/</id>
    <published>2019-11-12T21:15:53.000Z</published>
    <updated>2026-04-18T12:45:50.160Z</updated>
    
    <content type="html"><![CDATA[<p>之前因为需求找到了这个超级好用的微信爬虫工具<a href="https://github.com/striver-ing/wechat-spider" target="_blank" rel="noopener">https://github.com/striver-ing/wechat-spider</a>，目前已经开源。工具可以很方便地实现爬取微信文章，获取点赞、评论等功能。</p><p>最近，微信针对文章历史接口做了调整：PC版限制了爬取的次数，访问间隔应该控制在8分钟以上，移动端则是在两个月前直接干掉了这个功能。文章评论则没有改变。因此，这个工具目前最好的使用方式就是多开，分别爬不同的文章，再单开一个用来爬需要爬的评论。</p><p>工具的具体使用方法在原工程中都有提到，这里就不再赘述了。</p><p>在工具的使用方法中，我们知道，作者是使用全局代理，将所有的https消息都强制走了本机的8080端口，然后通过Python的mitmproxy来截取消息内容来实现的这个工具。那么，我可以使用局部代理，将制定的微信客户端，走制定端口，即可实现工具的多开。</p><p>有了这个思路，那么我们就只需要解决两个问题：</p><ol><li>微信的多开</li><li>多个微信走多个局部代理</li></ol><p>这里先说一下，我们无法使用微信PC客户端自带的代理功能。因为一旦这个功能开启，微信的所有链接都将进行加密，你得到的只会是一个格式如：<code>&lt;code&gt;</code><a href="https://xxx.xxx.xx.xx/mmtls/xxxxxx`" target="_blank" rel="noopener">https://xxx.xxx.xx.xx/mmtls/xxxxxx`</a>`的加密链接。</p><h1 id="微信的多开"><a href="#微信的多开" class="headerlink" title="微信的多开"></a>微信的多开</h1><p>微信多开的实现比较简单，直接使用bat脚本打开多个微信即可。需要注意的是，要以管理员模式运行。</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">@<span class="built_in">echo</span> off</span><br><span class="line">start /d <span class="string">"C:\Program Files (x86)\Tencent\WeChat\" WeChat.exe</span></span><br><span class="line"><span class="string">start /d "</span>C:\Program Files (x86)\Tencent\WeChat\" WeChat.exe</span><br><span class="line">start /d <span class="string">"C:\Program Files (x86)\Tencent\WeChat\" WeChat.exe</span></span><br><span class="line"><span class="string">start /d "</span>C:\Program Files (x86)\Tencent\WeChat\" WeChat.exe</span><br><span class="line">start /d <span class="string">"C:\Program Files (x86)\Tencent\WeChat\" WeChat.exe</span></span><br><span class="line"><span class="string">exit</span></span><br></pre></td></tr></table></figure><p>这样虽然可以打开多个微信，但是在设置局部代理时，工具无法区相同路径下的相同可执行文件。因此，我们需要把微信客户端拷贝多份，以应对后面的步骤。</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">@<span class="built_in">echo</span> off</span><br><span class="line">start /d <span class="string">"C:\Program Files (x86)\Tencent\WeChat\" WeChat.exe</span></span><br><span class="line"><span class="string">start /d "</span>C:\Program Files (x86)\Tencent\WeChatb\" WeChatb.exe</span><br><span class="line">start /d <span class="string">"C:\Program Files (x86)\Tencent\WeChatc\" WeChatc.exe</span></span><br><span class="line"><span class="string">start /d "</span>C:\Program Files (x86)\Tencent\WeChatd\" WeChatd.exe</span><br><span class="line">start /d <span class="string">"C:\Program Files (x86)\Tencent\WeChate\" WeChate.exe</span></span><br><span class="line"><span class="string">exit</span></span><br></pre></td></tr></table></figure><p>需要注意的是，这样配置之后的脚本将不一定百分百执行成功，可能只打开一个客户端。一般第二次即可执行成功。</p><h1 id="局部代理"><a href="#局部代理" class="headerlink" title="局部代理"></a>局部代理</h1><p>这里，我使用了Proxifier工具，进行局部代理。这个工具很容易获取，x度上很容易就可以获取到免费破解汉化的版本。</p><p>安装之后，我们开始配置工作。</p><blockquote><p>1.配置文件-&gt;代理服务器  这里地址填本机127.0.0.1，端口填你想要转发的端口，比如8080，8081，协议类型是HTTPS。你想开多少，就填多少个。</p></blockquote><blockquote><p>2.配置文件-&gt;代理规则    这里我们把默认的全局代理给关闭，双击条目，将“是否有效”取消勾选即可。然后添加微信的代理规则，点击添加，名称随意，应用程序浏览到微信的exe文件，目标主机清空，端口清空，然后在最下方的动作中选择你上一步配置的一个端口。那么这个路径下的客户端执行时，便会代理到这个端口下了。</p></blockquote><p>微信多开之后，我们会发现多开的这几个的微信的进程名是一样的，无法进行区分。这时候可以在任务管理器中使用切换到、最小化等功能确定哪个窗口是哪个进程，转到本地文件来确定他是哪个目录下的。在开多个的时候，一定要注意区分，以防登错账号，影响爬取。</p><p>爬虫的配置文件中，我们最好使用不同的mysql数据库，以免产影响。当然，如果你修改了原工具的代码，那就另当别论了。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;之前因为需求找到了这个超级好用的微信爬虫工具&lt;a href=&quot;https://github.com/striver-ing/wechat-spider&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/striver-in
      
    
    </summary>
    
    
      <category term="爬虫" scheme="http://www.z16388.top/tags/%E7%88%AC%E8%99%AB/"/>
    
  </entry>
  
  <entry>
    <title>U3D问题总结（七） lua</title>
    <link href="http://www.z16388.top/2019/10/29/unity7/"/>
    <id>http://www.z16388.top/2019/10/29/unity7/</id>
    <published>2019-10-29T23:00:07.000Z</published>
    <updated>2026-04-18T12:45:50.161Z</updated>
    
    <content type="html"><![CDATA[<h2 id="lua实现类的继承"><a href="#lua实现类的继承" class="headerlink" title="lua实现类的继承"></a>lua实现类的继承</h2><h2 id="lua遍历查找某个数"><a href="#lua遍历查找某个数" class="headerlink" title="lua遍历查找某个数"></a>lua遍历查找某个数</h2>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;lua实现类的继承&quot;&gt;&lt;a href=&quot;#lua实现类的继承&quot; class=&quot;headerlink&quot; title=&quot;lua实现类的继承&quot;&gt;&lt;/a&gt;lua实现类的继承&lt;/h2&gt;&lt;h2 id=&quot;lua遍历查找某个数&quot;&gt;&lt;a href=&quot;#lua遍历查找某个数&quot; cla
      
    
    </summary>
    
    
      <category term="Unity" scheme="http://www.z16388.top/tags/Unity/"/>
    
  </entry>
  
  <entry>
    <title>U3D问题总结（六） 优化</title>
    <link href="http://www.z16388.top/2019/10/29/unity6/"/>
    <id>http://www.z16388.top/2019/10/29/unity6/</id>
    <published>2019-10-29T23:00:06.000Z</published>
    <updated>2026-04-18T12:45:50.161Z</updated>
    
    <content type="html"><![CDATA[<h2 id="请简述GC（垃圾回收）产生的原因，并描述如何避免（？"><a href="#请简述GC（垃圾回收）产生的原因，并描述如何避免（？" class="headerlink" title="请简述GC（垃圾回收）产生的原因，并描述如何避免（？"></a>请简述GC（垃圾回收）产生的原因，并描述如何避免（？</h2><blockquote><p>GC回收堆上的内存<br>避免：1.减少new产生对象的次数<br>2.使用公用的对象（静态成员）<br>3.将String换为StringBuilder</p></blockquote><h2 id="如何优化内存？"><a href="#如何优化内存？" class="headerlink" title="如何优化内存？"></a>如何优化内存？</h2><blockquote><p>1.压缩自带类库；<br>2.将暂时不用的以后还需要使用的物体隐藏起来而不是直接Destroy掉；<br>3.释放AssetBundle占用的资源；<br>4.降低模型的片面数，降低模型的骨骼数量，降低贴图的大小；<br>5.使用光照贴图，使用多层次细节(LOD)，使用着色器(Shader)，使用预设(Prefab)。<br>6.代码中少产生临时变量</p></blockquote><h2 id="UNITY3d在移动设备上的一些优化资源的方法"><a href="#UNITY3d在移动设备上的一些优化资源的方法" class="headerlink" title="UNITY3d在移动设备上的一些优化资源的方法"></a>UNITY3d在移动设备上的一些优化资源的方法</h2><blockquote><p>1.使用assetbundle，实现资源分离和共享，将内存控制到200m之内，同时也可以实现资源的在线更新<br>2.顶点数对渲染无论是cpu还是gpu都是压力最大的贡献者，降低顶点数到8万以下，fps稳定到了30帧左右<br>3.只使用一盏动态光，不是用阴影，不使用光照探头<br>粒子系统是cpu上的大头<br>4.剪裁粒子系统<br>5.合并同时出现的粒子系统<br>6.自己实现轻量级的粒子系统<br>animator也是一个效率奇差的地方<br>7.把不需要跟骨骼动画和动作过渡的地方全部使用animation，控制骨骼数量在30根以下<br>8.animator出视野不更新<br>9.删除无意义的animator<br>10.animator的初始化很耗时（粒子上能不能尽量不用animator）<br>11.除主角外都不要跟骨骼运动apply root motion<br>12.绝对禁止掉那些不带刚体带包围盒的物体（static collider ）运动<br>NUGI的代码效率很差，基本上runtime的时候对cpu的贡献和render不相上下<br>13每帧递归的计算finalalpha改为只有初始化和变动时计算<br>14去掉法线计算<br>15不要每帧计算viewsize 和windowsize<br>16filldrawcall时构建顶点缓存使用array.copy<br>17.代码剪裁：使用strip level ，使用.net2.0 subset<br>18.尽量减少smooth group<br>19.给美术定一个严格的经过科学验证的美术标准，并在U3D里面配以相应的检查工具</p></blockquote><h2 id="场景优化"><a href="#场景优化" class="headerlink" title="场景优化"></a>场景优化</h2><blockquote><p>1.遮挡剔除（Occlusion Culling）                不显示被遮挡住的物体<br>2.LOD                                         根据相机距离远近显示不同精细程度的模型<br>3.大场景可以调节相机可视距离<br>4.小物体可以适当隐藏掉<br>5.使用光照贴图                                 避免动态实时的进行光照计算，提高效率</p></blockquote><h2 id="UI优化"><a href="#UI优化" class="headerlink" title="UI优化"></a>UI优化</h2><blockquote><p>1.将同一画面图片放到同一图集中<br>2.图片和文字尽量不要交叉，会产生多余drawcall（相同材质和纹理的UI元素是可以合并的）<br>3.UI层级尽量不要重叠太多<br>4.取消勾选不必要的射线检测RaycastTarget<br>5.将动态的UI元素和静态的UI元素放在不同的Canvas中，减少canvas网格重构频率</p></blockquote><h2 id="GC优化"><a href="#GC优化" class="headerlink" title="GC优化"></a>GC优化</h2><blockquote><p>1.字符串使用StringBuilder而不是string，stringBuilder在创建时会自动获取一个容量存储并逐渐扩充，string每一次改变都会创建一个新的对象。<br>2.访问物体tag的时候尽量使用Gameobject.CompareTag()，因为访问物体的tag属性会在堆上额外的分配空间<br>3.使用对象池缓存大量创建的物体<br>4.用for代替foreach，foreach每次迭代产生24字节垃圾内存</p></blockquote>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;请简述GC（垃圾回收）产生的原因，并描述如何避免（？&quot;&gt;&lt;a href=&quot;#请简述GC（垃圾回收）产生的原因，并描述如何避免（？&quot; class=&quot;headerlink&quot; title=&quot;请简述GC（垃圾回收）产生的原因，并描述如何避免（？&quot;&gt;&lt;/a&gt;请简述GC（垃圾
      
    
    </summary>
    
    
      <category term="Unity" scheme="http://www.z16388.top/tags/Unity/"/>
    
  </entry>
  
  <entry>
    <title>U3D问题总结（五） 渲染与光照</title>
    <link href="http://www.z16388.top/2019/10/29/unity5/"/>
    <id>http://www.z16388.top/2019/10/29/unity5/</id>
    <published>2019-10-29T23:00:05.000Z</published>
    <updated>2026-04-18T12:45:50.161Z</updated>
    
    <content type="html"><![CDATA[<h2 id="什么是渲染管道（？"><a href="#什么是渲染管道（？" class="headerlink" title="什么是渲染管道（？"></a>什么是渲染管道（？</h2><blockquote><p>是指在显示器上为了显示出图像而经过的一系列必要操作。 渲染管道中的很多步骤，都要将几何物体从一个坐标系中变换到另一个坐标系中去。主要步骤有：<br>本地坐标-&gt;视图坐标-&gt;背面裁剪-&gt;光照-&gt;裁剪-&gt;投影-&gt;视图变换-&gt;光栅化</p></blockquote><h2 id="对渲染管线的理解"><a href="#对渲染管线的理解" class="headerlink" title="对渲染管线的理解"></a>对渲染管线的理解</h2><blockquote><p>渲染流水线流程：<br>1.应用阶段（由CPU负责，输出是渲染所需要的几何信息，即渲染图元。然后发起Draw Call，进入GPU流水线）<br>2.几何阶段（由GPU负责，处理渲染图元，这阶段中最重要的就是把顶点坐标变换屏幕空间中，交给光栅器处理<br>这阶段输出的是屏幕空间中二维顶点坐标、每个顶点对应的深度值、着色等相关信息）<br>3.光栅化阶段（由GPU，负责这一阶段会使用上个阶段传递的数据来产生屏幕上的像素，并渲染出最终的图像）<br>细节过程<a href="https://zhuanlan.zhihu.com/p/97498781" target="_blank" rel="noopener">https://zhuanlan.zhihu.com/p/97498781</a></p></blockquote><h2 id="什么是DrawCall？DrawCall高了又什么影响？如何降低DrawCall？"><a href="#什么是DrawCall？DrawCall高了又什么影响？如何降低DrawCall？" class="headerlink" title="什么是DrawCall？DrawCall高了又什么影响？如何降低DrawCall？"></a>什么是DrawCall？DrawCall高了又什么影响？如何降低DrawCall？</h2><blockquote><p>Unity中，每次引擎准备数据并通知GPU的过程称为一次Draw Call。DrawCall越高对显卡的消耗就越大。降低DrawCall的方法：</p><ol><li>Dynamic Batching</li><li>Static Batching</li><li>高级特性Shader降级为统一的低级特性的Shader。</li></ol></blockquote><h2 id="什么是DrawCall，有什么方法可以减少DrawCall"><a href="#什么是DrawCall，有什么方法可以减少DrawCall" class="headerlink" title="什么是DrawCall，有什么方法可以减少DrawCall"></a>什么是DrawCall，有什么方法可以减少DrawCall</h2><blockquote><p>CPU通过调用绘制命令来告诉GPU开始进行一个渲染过程(一次DrawCall)。<br>CPU方面减少DrawCall：<br>1、使用Draw Call Batching 、Dynamic Batching动态批处理<br>2、纹理打包成图集减少材质使用<br>3、少用反光、阴影<br>4、设置一个合适的Fixed Timestep<br>5、不要使用网格碰撞器(Mesh Collider)<br>6、大量或频繁的字符串连接操作一定要用StringBuilder<br>7、某些可能情况，使用结构体代替类<br>8、使用对象池重复利用空间<br>9、尽量不要用foreach，用for<br>10、不要直接访问GameObjcet的tag属性<br>11、不要频繁使用GetComponent，访问一次后保留其引用<br>12、使用OnBecameVisible()和OnBecameInVisible()，控制物体update()函数的执行减少开销<br>13、使用内建数组，如Vector3.zero而不是new Vector3(0,0,0)<br>14、使用ref关键字对方法的参数进行优化<br>15、关闭所有update中的log操作<br>16、不在update中调用GetComponent、SendMessage、FindWithTag等方法<br>17、不在update中使用临时变量</p></blockquote><h2 id="GPU方面减少DrawCall"><a href="#GPU方面减少DrawCall" class="headerlink" title="GPU方面减少DrawCall"></a>GPU方面减少DrawCall</h2><blockquote><p>1、使用纹理图集代替一系列单独小贴图<br>2、保持材质数目尽可能少<br>3、如果使用纹理图集和共享材质，用Renderer.sharedMaterial代替Renderer.material<br>4、使用光照纹理(lightmap)而非实时灯光<br>5、使用LOD<br>6、使用mobile版的shader<br>7、尽可能减少顶点数、背面删减<br>8、压缩图片，减少显存带宽压力</p></blockquote><h2 id="什么是material，什么是shader，二者有什么关系"><a href="#什么是material，什么是shader，二者有什么关系" class="headerlink" title="什么是material，什么是shader，二者有什么关系"></a>什么是material，什么是shader，二者有什么关系</h2><blockquote><p>材质系统定义了如何渲染物件表面信息。shader里面使用材质信息加自身操作，最终呈现物体渲染。shader是material一部分，是根据计算即时演算生成贴图的程序，叫着色器。常用处理无法用固定贴图表现的模型。material是模型的材质，包含贴图、shader、顶点、凹凸等信息。</p></blockquote><h2 id="如何在Unity3D中查看场景的面数，顶点数和Draw-Call数？如何降低Draw-Call数"><a href="#如何在Unity3D中查看场景的面数，顶点数和Draw-Call数？如何降低Draw-Call数" class="headerlink" title="如何在Unity3D中查看场景的面数，顶点数和Draw Call数？如何降低Draw Call数"></a>如何在Unity3D中查看场景的面数，顶点数和Draw Call数？如何降低Draw Call数</h2><blockquote><p>在Game视图右上角点击Stats。降低Draw Call 的技术是Draw Call Batching<br>这个在5.0以后在window-》Profiler下面，快捷键是cmd + 7（ctl + 7</p></blockquote><h2 id="DrawCall和SetPass-Call"><a href="#DrawCall和SetPass-Call" class="headerlink" title="DrawCall和SetPass Call"></a>DrawCall和SetPass Call</h2><blockquote><p>DrawCall：meshes网格绘制应用批处理后的总数。请注意，在多次呈现对象(例如，由像素灯照明的对象)，每个在一个单独的渲染结果绘制调用。</p></blockquote><blockquote><p>SetPass Call：渲染改变（ passes）次数。每个改变 需要Unity运行时绑定一个新的渲染器（shader），它可能会引入 CPU 开销。</p></blockquote><h2 id="Unity3D-Shader分哪几种，有什么区别"><a href="#Unity3D-Shader分哪几种，有什么区别" class="headerlink" title="Unity3D Shader分哪几种，有什么区别"></a>Unity3D Shader分哪几种，有什么区别</h2><blockquote><p>表面着色器的抽象层次比较高，它可以轻松地以简洁方式实现复杂着色。表面着色器可同时在前向渲染及延迟渲染模式下正常工作。<br>顶点片段着色器可以非常灵活地实现需要的效果，但是需要编写更多的代码，并且很难与Unity的渲染管线完美集成。<br>固定功能管线着色器可以作为前两种着色器的备用选择，当硬件无法运行那些酷炫Shader的时，还可以通过固定功能管线着色器来绘制出一些基本的内容。</p></blockquote><h2 id="有A和B两组物体，有什么办法能够保证A组物体永远比B组物体先渲染？"><a href="#有A和B两组物体，有什么办法能够保证A组物体永远比B组物体先渲染？" class="headerlink" title="有A和B两组物体，有什么办法能够保证A组物体永远比B组物体先渲染？"></a>有A和B两组物体，有什么办法能够保证A组物体永远比B组物体先渲染？</h2><blockquote><p>把A组物体的渲染队列大于B物体的渲染队列，通过shader里面的渲染队列来渲染</p></blockquote><h2 id="问一个Terrain，分别贴3张，4张，5张地表贴图，渲染速度有什么区别？为什么？"><a href="#问一个Terrain，分别贴3张，4张，5张地表贴图，渲染速度有什么区别？为什么？" class="headerlink" title="问一个Terrain，分别贴3张，4张，5张地表贴图，渲染速度有什么区别？为什么？"></a>问一个Terrain，分别贴3张，4张，5张地表贴图，渲染速度有什么区别？为什么？</h2><blockquote><p>没有区别，因为不管几张贴图只渲染一次。</p></blockquote><h2 id="LOD是什么，优缺点"><a href="#LOD是什么，优缺点" class="headerlink" title="LOD是什么，优缺点(?"></a>LOD是什么，优缺点(?</h2><blockquote><p>LOD(Level of detail)多层次细节，是最常用的游戏优化技术。它按照模型的位置和重要程度决定物体渲染的资源分配，降低非重要物体的面数和细节度，从而获得高效率的渲染运算。缺点是增加了内存。</p></blockquote><h2 id="MipMap是什么，作用"><a href="#MipMap是什么，作用" class="headerlink" title="MipMap是什么，作用(?"></a>MipMap是什么，作用(?</h2><blockquote><p>MipMapping：在三维计算机图形的贴图渲染中有常用的技术，为加快渲染进度和减少图像锯齿，贴图被处理成由一系列被预先计算和优化过的图片组成的文件，这样的贴图被称为MipMap。</p></blockquote><h2 id="什么是LightMap"><a href="#什么是LightMap" class="headerlink" title="什么是LightMap"></a>什么是LightMap</h2><blockquote><p>LightMap:就是指在三维软件里实现打好光，然后渲染把场景各表面的光照输出到贴图上，最后又通过引擎贴到场景上，这样就使物体有了光照的感觉。</p></blockquote><h2 id="alpha-blend工作原理"><a href="#alpha-blend工作原理" class="headerlink" title="alpha blend工作原理"></a>alpha blend工作原理</h2><blockquote><p>Alpha Blend 实现透明效果，不过只能针对某块区域进行alpha操作，透明度可设。</p></blockquote><blockquote><p>alpha blend 用于做半透明效果。Color = (源颜色 <em>    源系数) OP (   目标颜色</em> 目标系数);其中OP（混合方式）有加，减，反减，取最小，取最大</p></blockquote><h2 id="Unity的Shader中，Blend-SrcAlpha-OneMinusSrcAlpha这句话是什么意思"><a href="#Unity的Shader中，Blend-SrcAlpha-OneMinusSrcAlpha这句话是什么意思" class="headerlink" title="Unity的Shader中，Blend SrcAlpha OneMinusSrcAlpha这句话是什么意思"></a>Unity的Shader中，Blend SrcAlpha OneMinusSrcAlpha这句话是什么意思</h2><blockquote><p>作用就是Alpha混合。公式：最终颜色 = 源颜色 x 源透明值 + 目标颜色 x（1 - 源透明值）</p></blockquote><h2 id="alpha-test在何时使用？能达到什么效果"><a href="#alpha-test在何时使用？能达到什么效果" class="headerlink" title="alpha test在何时使用？能达到什么效果"></a>alpha test在何时使用？能达到什么效果</h2><blockquote><p>Alpha Test ,中文就是透明度测试。简而言之就是V&amp;F shader中最后fragment函数输出的该点颜色值（即上一讲frag的输出half4）的alpha值与固定值进行比较。AlphaTest语句通常于Pass{}中的起始位置。Alpha Test产生的效果也很极端，要么完全透明，即看不到，要么完全不透明。</p></blockquote><h2 id="Vertex-Shader是什么，怎么计算"><a href="#Vertex-Shader是什么，怎么计算" class="headerlink" title="Vertex Shader是什么，怎么计算"></a>Vertex Shader是什么，怎么计算</h2><blockquote><p>顶点着色器是一段执行在GPU上的程序，用来取代fixed pipeline中的transformation和lighting，Vertex Shader主要操作顶点。<br>Vertex Shader对输入顶点完成了从local space到homogeneous space（齐次空间）的变换过程，homogeneous space即projection space的下一个space。在这其间共有world transformation, view transformation和projection transformation及lighting几个过程。</p></blockquote><h2 id="写出光照计算中的diffuse（漫反射）的计算公式"><a href="#写出光照计算中的diffuse（漫反射）的计算公式" class="headerlink" title="写出光照计算中的diffuse（漫反射）的计算公式"></a>写出光照计算中的diffuse（漫反射）的计算公式</h2><blockquote><p>diffuse = Kd x colorLight x max(N*L,0)；<br>Kd 漫反射系数、colorLight 光的颜色、N 单位法线向量、L 由点指向光源的单位向量、其中N与L点乘，如果结果小于等于0，则漫反射为0。</p></blockquote><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">答：漫反射光(diffuse)计算公式为：Idiffuse = Dintensity*Dcolor*N.L ; (Dintensity表示漫反射强度，Dcolor表示漫反射光颜色，N为该点的法向量，L为光源向量)</span><br><span class="line"></span><br><span class="line">  其他，3D渲染中，物体表面的光照计算公式为：</span><br><span class="line"></span><br><span class="line">I = 环境光(Iambient) + 漫反射光(Idiffuse) + 镜面高光(Ispecular);</span><br><span class="line"></span><br><span class="line">  其中，环境光(ambient)计算公式为：</span><br><span class="line"></span><br><span class="line">Iambient= Aintensity* Acolor; (Aintensity表示环境光强度，Acolor表示环境光颜色)</span><br><span class="line"></span><br><span class="line">  漫反射光(diffuse)计算公式为：</span><br><span class="line"></span><br><span class="line">Idiffuse = Dintensity*Dcolor*N.L ; (Dintensity表示漫反射强度，Dcolor表示漫反射光颜色，N为该点的法向量，L为光源向量)</span><br><span class="line"></span><br><span class="line">镜面光照(specular)计算公式为：</span><br><span class="line"></span><br><span class="line">Ispecular = Sintensity*Scolor*(R.V)n; (Sintensity表示镜面光照强度，Scolor表示镜面光颜色，R为光的反射向量，V为观察者向量)</span><br><span class="line"></span><br><span class="line">综上所得：整个光照公式为：</span><br><span class="line"></span><br><span class="line">I = Aintensity* Acolor+ Dintensity*Dcolor*N.L + Sintensity*Scolor*(R.V)n ;</span><br><span class="line"></span><br><span class="line">将一些值合并，并使用白色作为光照颜色，则上述公式可简化为：</span><br><span class="line"></span><br><span class="line">I = A + D*N.L + (R.V)n</span><br></pre></td></tr></table></figure><h2 id="MeshRender中material和sharedmaterial的区别"><a href="#MeshRender中material和sharedmaterial的区别" class="headerlink" title="MeshRender中material和sharedmaterial的区别(?"></a>MeshRender中material和sharedmaterial的区别(?</h2><blockquote><p>修改sharedMaterial将改变所有物体使用这个材质的外观，并且也改变储存在工程里的材质设置。不推荐修改由sharedMaterial返回的材质。如果你想修改渲染器的材质，使用material替代。</p></blockquote><h1 id="简述水面倒影的渲染原理"><a href="#简述水面倒影的渲染原理" class="headerlink" title="简述水面倒影的渲染原理"></a>简述水面倒影的渲染原理</h1><blockquote><p>原理就是对水面的贴图纹理进行扰动，以产生波光玲玲的效果。用shader可以通过GPU在像素级别作扰动，效果细腻，需要的顶点少，速度快</p></blockquote><h2 id="什么叫动态合批？跟静态合批有什么区别"><a href="#什么叫动态合批？跟静态合批有什么区别" class="headerlink" title="什么叫动态合批？跟静态合批有什么区别"></a>什么叫动态合批？跟静态合批有什么区别</h2><blockquote><p>如果动态物体共用着相同的材质，那么Unity会自动对这些物体进行批处理。动态批处理操作是自动完成的，并不需要你进行额外的操作。<br>区别：动态批处理一切都是自动的，不需要做任何操作，而且物体是可以移动的，但是限制很多。静态批处理：自由度很高，限制很少，缺点可能会占用更多的内存，而且经过静态批处理后的所有物体都不可以再移动了。</p></blockquote><h2 id="两种阴影判断的方法、工作原理。"><a href="#两种阴影判断的方法、工作原理。" class="headerlink" title="两种阴影判断的方法、工作原理。"></a>两种阴影判断的方法、工作原理。</h2><blockquote><p>本影：景物表面上那些没有被光源直接照射的区域（全黑的轮廓分明的区域）。<br>半影：景物表面上那些被某些特定光源直接照射但并非被所有特定光源直接照射的区域（半明半暗区域）<br>工作原理：从光源处向物体的所有可见面投射光线，将这些面投影到场景中得到投影面，再将这些投影面与场景中的其他平面求交得出阴影多边形，保存这些阴影多边形信息，然后再按视点位置对场景进行相应处理得到所要求的视图（利用空间换时间，每次只需依据视点位置进行一次阴影计算即可，省去了一次消隐过程）</p></blockquote><h2 id="Unity提供了几种光源，分别是什么"><a href="#Unity提供了几种光源，分别是什么" class="headerlink" title="Unity提供了几种光源，分别是什么"></a>Unity提供了几种光源，分别是什么</h2><blockquote><p>四种。<br>平行光：Directional Light<br>点光源：Point Light<br>聚光灯：Spot Light<br>区域光源：Area Light</p></blockquote><h2 id="实时点光源的优缺点是什么"><a href="#实时点光源的优缺点是什么" class="headerlink" title="实时点光源的优缺点是什么"></a>实时点光源的优缺点是什么</h2><blockquote><p>可以有cookies – 带有 alpha通道的立方图(Cubemap )纹理。点光源是最耗费资源的。</p></blockquote><h2 id="GPU的工作原理"><a href="#GPU的工作原理" class="headerlink" title="GPU的工作原理"></a>GPU的工作原理</h2><blockquote><p>简而言之，GPU的图形（处理）流水线完成如下的工作：（并不一定是按照如下顺序） 顶点处理：这阶段GPU读取描述3D图形外观的顶点数据并根据顶点数据确定3D图形的形状及位置关系，建立起3D图形的骨架。在支持DX8和DX9规格的GPU中，这些工作由硬件实现的Vertex Shader（定点着色器）完成。 光栅化计算：显示器实际显示的图像是由像素组成的，我们需要将上面生成的图形上的点和线通过一定的算法转换到相应的像素点。把一个矢量图形转换为一系列像素点的过程就称为光栅化。例如，一条数学表示的斜线段，最终被转化成阶梯状的连续像素点。 纹理帖图：顶点单元生成的多边形只构成了3D物体的轮廓，而纹理映射（texture mapping）工作完成对多变形表面的帖图，通俗的说，就是将多边形的表面贴上相应的图片，从而生成“真实”的图形。TMU（Texture mapping unit）即是用来完成此项工作。 像素处理：这阶段（在对每个像素进行光栅化处理期间）GPU完成对像素的计算和处理，从而确定每个像素的最终属性。在支持DX8和DX9规格的GPU中，这些工作由硬件实现的Pixel Shader（像素着色器）完成。 最终输出：由ROP（光栅化引擎）最终完成像素的输出，1帧渲染完毕后，被送到显存帧缓冲区。<br>总结：GPU的工作通俗的来说就是完成3D图形的生成，将图形映射到相应的像素点上，对每个像素进行计算确定最终颜色并完成输出。</p></blockquote><h1 id="图形学"><a href="#图形学" class="headerlink" title="图形学"></a>图形学</h1><h2 id="光照模型有哪些"><a href="#光照模型有哪些" class="headerlink" title="光照模型有哪些"></a>光照模型有哪些</h2><h2 id="3维模型组成"><a href="#3维模型组成" class="headerlink" title="3维模型组成"></a>3维模型组成</h2><p>Mesh</p><h2 id="Mesh下面有哪些字段"><a href="#Mesh下面有哪些字段" class="headerlink" title="Mesh下面有哪些字段"></a>Mesh下面有哪些字段</h2><h2 id="如向将文理贴在模型上"><a href="#如向将文理贴在模型上" class="headerlink" title="如向将文理贴在模型上"></a>如向将文理贴在模型上</h2><h2 id="图片向格式有那些"><a href="#图片向格式有那些" class="headerlink" title="图片向格式有那些"></a>图片向格式有那些</h2>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;什么是渲染管道（？&quot;&gt;&lt;a href=&quot;#什么是渲染管道（？&quot; class=&quot;headerlink&quot; title=&quot;什么是渲染管道（？&quot;&gt;&lt;/a&gt;什么是渲染管道（？&lt;/h2&gt;&lt;blockquote&gt;
&lt;p&gt;是指在显示器上为了显示出图像而经过的一系列必要操作。 渲染
      
    
    </summary>
    
    
      <category term="Unity" scheme="http://www.z16388.top/tags/Unity/"/>
    
  </entry>
  
</feed>
