<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    
    <title>OWNSELF</title>
    
    
    <description>Welcome to OWNSELF</description>
    
    <link></link>
    <atom:link href="/feed.xml" rel="self" type="application/rss+xml" />
    
    
      <item>
        <title>Setup Neovim for Unity development</title>
        <description>
          
          &lt;p&gt;这篇文章是应一位Reddit网友编写的，因此以英文为主了，中文版在&lt;a href=&quot;#前情及动机&quot;&gt;后半段&lt;/a&gt;&lt;/p&gt;

&lt;h1 id=&quot;background--motivation&quot;&gt;Background &amp;amp; Motivation&lt;/h1&gt;

&lt;p&gt;I’m a game development engineer, mainly working on client-side development using engines such as Unity or Unreal (which unfortunately means my working platform is almost always locked to Windows 😢). Over the past many years, my choice of programming tools has gone through several major evolutions, roughly falling into the following stages:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Visual Studio / CodeWarrior / Xcode&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;During the first four years of my career, I primarily worked on console game development for platforms like PSP and Wii. At that time, I mostly used the officially recommended tools for each platform—essentially “out of the box” solutions. However, editors of that era were nowhere near today’s standards in terms of code intelligence or debugging capabilities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sublime Text&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Later on, I started learning Vim. The emergence of Sublime Text, along with its decent support for Vim motions, allowed me to enter the Vim world with a relatively gentle learning curve. For about six years, Sublime Text was my main editor for daily development. Only when debugging was absolutely necessary would I reluctantly open Visual Studio (yes, I’m a logger).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Visual Studio / Rider&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the following years, I frequently had to switch between different projects, and intelligent code completion became increasingly important. As a result, I returned to Visual Studio (with VsVim). Around 2020, I discovered Rider and was genuinely impressed. At that time, Rider felt like a perfect blend of intelligence, speed, and aesthetics. Its Vim plugin, IdeaVim, was among the best I had used—remarkably, it even supported function navigation in Unity shaders. Coding during those years was truly enjoyable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Neovim&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;During the GVim era, I never invested serious effort into configuration. While it offered a first-class Vim experience, but it lagged far behind in many other aspects. The emergence of Neovim changed this dramatically, thanks to its support for LSP and DAP (credit to VSCode). Over roughly a year and a half of gradual tweaking, I managed to configure Neovim into a highly usable state. Meanwhile, Rider started performing worse and worse in my work projects—slow startup times, frequent memory usage exceeding 10 GB, and even memory leak issues in recent versions…&lt;/p&gt;

&lt;p&gt;So by the end of 2025, I finally made the decision to officially replace Rider with Neovim as my primary “IDE” in my work environment.&lt;/p&gt;

&lt;h1 id=&quot;neovim-basic-setup&quot;&gt;Neovim Basic Setup&lt;/h1&gt;

&lt;p&gt;Everyone’s Neovim setup is different, and that’s precisely its biggest charm—customizing appearance, keymaps, and essential plugins. If we were to explain everything in detail from scratch, it could easily turn into tens of thousands of words. Therefore, this article won’t cover the basics.&lt;/p&gt;

&lt;p&gt;If you’re new to Neovim, I highly recommend watching Josean’s YouTube tutorials:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=6pAG3BHurdM&quot;&gt;How I Setup Neovim To Make It AMAZING in 2024: The Ultimate Guide&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=oBiBEx7L000&quot;&gt;How to Setup Neovim LSP Like A Pro in 2025 (v0.11+)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;His videos are very beginner-friendly and detailed, and should be more than enough to get you started with a solid base configuration.&lt;/p&gt;

&lt;h1 id=&quot;lsp-and-dap&quot;&gt;LSP and DAP&lt;/h1&gt;

&lt;p&gt;If you want Neovim to work well with Unity projects, this is the core part of the article. In fact, there aren’t many related articles online—probably because I guess there are only very few Unity developers use Neovim as their primary development tool 😆.&lt;/p&gt;

&lt;p&gt;LSP stands for Language Server Protocol, which provides intelligent code features such as completion and navigation. DAP stands for Debug Adapter Protocol, a standardized interface for debuggers. Both protocols were proposed and popularized by VS Code. Because they are open standards, they benefit many modern open-source editors, including Neovim, Helix, and Zed. Their support for code intelligence and debugging relies heavily on LSP and DAP.&lt;/p&gt;

&lt;p&gt;The key to making Neovim work well for Unity development lies in configuring LSP and DAP properly.&lt;/p&gt;

&lt;h3 id=&quot;lsp-roslynnvim&quot;&gt;LSP: Roslyn.nvim&lt;/h3&gt;

&lt;p&gt;When I first configured C# support in Neovim, I used OmniSharp. The experience was not very satisfying, mainly in terms of performance. In slightly larger projects, jumping to a function definition could take 1–2 seconds.&lt;/p&gt;

&lt;p&gt;I’m not entirely sure whether this was due to my own misconfiguration (since OmniSharp now also uses Roslyn internally), but at the time, it felt inadequate for serious use.&lt;/p&gt;

&lt;p&gt;&lt;del&gt;Later, I discovered a relatively new Neovim LSP plugin based on Roslyn : &lt;a href=&quot;https://github.com/seblyng/roslyn.nvim&quot;&gt;Roslyn.nvim&lt;/a&gt;&lt;/del&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Update 2026/03/09: The original Roslyn.nvim plugin was primarily built for .NET projects. It has some issues with Unity project support, and the original author does not want to significantly change the plugin’s logic (via PRs). So I made many Unity-focused changes in my fork, and I now recommend using the version from my forked repository.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At the moment, the recommended approach is to use the Roslyn LSP–based plugin &lt;a href=&quot;https://github.com/ownself/roslyn.nvim&quot;&gt;Roslyn.nvim&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Unity-focused optimizations and improvements in this plugin compared to the upstream repository:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A more robust sln/csproj selection mechanism&lt;/li&gt;
  &lt;li&gt;When it can’t automatically choose among multiple sln/csproj files, it shows a popup asking the user to select one&lt;/li&gt;
  &lt;li&gt;Proper support for opening multiple sln files within the same session&lt;/li&gt;
  &lt;li&gt;Provides &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Roslyn config&lt;/code&gt; to dynamically switch the project configuration&lt;/li&gt;
  &lt;li&gt;By default, code guarded by inactive macros is highlighted in “gray”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Its initialization speed and function navigation performance are impressive, and it also supports advanced LSP features such as inlay hints.&lt;/p&gt;

&lt;p&gt;Ramboe has some excellent videos on his YouTube channel introducing this plugin:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=yXhOgiqa0hI&quot;&gt;Neovim + C# in 2025: Roslyn LSP Changes Everything&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=yJc4AWf0TNs&quot;&gt;Neovim + C# in 2025: The Actually Improved Setup : roslyn.nvim + rzsl.nvim&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;His videos also cover some DAP configuration, but it mainly targets .NET projects rather than Unity. Still, they are very helpful for understanding how DAP works, which will be useful later.&lt;/p&gt;

&lt;p&gt;Back to LSP: fortunately, Roslyn.nvim supports both .NET and Unity projects. Below is how I configure Roslyn.nvim in my Neovim setup.&lt;/p&gt;

&lt;p&gt;First, you need to add Roslyn to your Mason configuration (Josean’s first video explains Mason in detail). Because currently, Roslyn is not officially included in Mason’s default registry.&lt;/p&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;mason&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;registries&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&quot;github:mason-org/mason-registry&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&quot;github:Crashdummyy/mason-registry&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After that, you can open the Mason menu with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Mason&lt;/code&gt; and install Roslyn.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2026/MasonRoslyn.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Then, add the Roslyn.nvim plugin via Lazy:&lt;/p&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;seblyng/roslyn.nvim&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ft&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;cs&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;opts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;-- your configuration comes here; leave empty for default settings&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;filewatching&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;off&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;-- currently other options lead huge performance dropping&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The default value of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filewatching&lt;/code&gt; is “auto”, which has been the main issue I’ve encountered with Roslyn.nvim so far. In my work project, there are already over 100,000 C# source files. With the default setting, every file save causes a 2–3 second freeze. For now, I work around this by disabling file watching.&lt;/p&gt;

&lt;p&gt;The trade-off is that after certain file changes, I occasionally need to manually restart the LSP server using a keymap:&lt;/p&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keymap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;n&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;leader&amp;gt;lr&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;LspRestart&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;noremap&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Restart LSP Server and enable Copilot&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Finally, you may want to configure the detailed LSP settings in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;after/lsp/roslyn.lua&lt;/code&gt; (the Neovim 0.11+ approach; see Josean’s second video):&lt;/p&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;settings&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;csharp|inlay_hints&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;csharp_enable_inlay_hints_for_implicit_object_creation&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;csharp_enable_inlay_hints_for_implicit_variable_types&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;csharp_enable_inlay_hints_for_lambda_parameter_types&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;csharp_enable_inlay_hints_for_types&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;dotnet_enable_inlay_hints_for_indexer_parameters&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;dotnet_enable_inlay_hints_for_literal_parameters&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;dotnet_enable_inlay_hints_for_object_creation_parameters&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;dotnet_enable_inlay_hints_for_other_parameters&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;dotnet_enable_inlay_hints_for_parameters&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;dotnet_suppress_inlay_hints_for_parameters_that_differ_only_by_suffix&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;dotnet_suppress_inlay_hints_for_parameters_that_match_argument_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;dotnet_suppress_inlay_hints_for_parameters_that_match_method_intent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;-- so far we use symbol-usage.nvim for this function&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;-- [&quot;csharp|code_lens&quot;] = {&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;-- 	dotnet_enable_references_code_lens = true,&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;-- },&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;dap-nvim-dap&quot;&gt;DAP: nvim-dap&lt;/h3&gt;

&lt;p&gt;Ramboe’s videos already cover the basics of setting up nvim-dap. Installing and using the plugin itself is not particularly difficult. What tends to be intimidating is installing and configuring the language-specific DAP tools.&lt;/p&gt;

&lt;p&gt;Fortunately, the nvim-dap team maintains an official &lt;a href=&quot;https://codeberg.org/mfussenegger/nvim-dap/wiki/Debug-Adapter-installation&quot;&gt;Debug Adapter installation Wiki&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In general, the process involves downloading the DAP tool for your language (usually adding it to your PATH), and then using the default configuration provided in the wiki. I say “barely works” because for many languages—such as C#, Rust, and C++—you still need to manually specify the executable to debug when launching a session.&lt;/p&gt;

&lt;p&gt;If you look closely, you’ll also find a section in the wiki describing how to set up a &lt;a href=&quot;https://codeberg.org/mfussenegger/nvim-dap/wiki/Debug-Adapter-installation#unity&quot;&gt;Unity Dap Debugger&lt;/a&gt;. Unfortunately, in my experience, that method is already outdated. The Unity debugger used by VS Code has transitioned from a Unity-authored tool to a Microsoft-maintained
&lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=visualstudiotoolsforunity.vstuc&quot;&gt;Visual Studio Tools for Unity extension&lt;/a&gt;
.&lt;/p&gt;

&lt;p&gt;The configuration has also changed accordingly. Thankfully, after a lot of digging through forums (and with some help from ChatGPT), I eventually managed to get Unity debugging working in Neovim!&lt;/p&gt;

&lt;h1 id=&quot;nvim-dap-unity&quot;&gt;nvim-dap-unity&lt;/h1&gt;

&lt;p&gt;During my research, I noticed that plugins aimed at “improving Unity DAP deployment” were basically nonexistent. So I decided to go a step further and package my work into a plugin to share with others.&lt;/p&gt;

&lt;p&gt;Although I don’t expect many Unity developers to use Neovim as their primary tool (Rider is still objectively the better choice), I hope it can help fellow Neovim enthusiasts like myself.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/ownself/nvim-dap-unity&quot;&gt;nvim-dap-unity&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2026/nvim-dap-unity.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This plugin mainly does three things to ensure an “out-of-the-box” Unity debugging experience:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Automatically downloads the VS Code Tools for Unity debugger and extracts it into the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nvimdata&lt;/code&gt; directory (Windows / macOS / Linux).
    &lt;ul&gt;
      &lt;li&gt;Installed automatically when using Lazy, or manually via the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NvimDapUnityInstall&lt;/code&gt; command.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Configures default launch configurations for nvim-dap (e.g. “Attach Unity Editor”).
    &lt;ul&gt;
      &lt;li&gt;Also supports merging with existing C# (.NET) DAP configurations.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Automatically searches for and loads the appropriate DLLs from the Unity project when starting a debug session.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The plugin has been tested on Windows, macOS, and even Linux (the Linux testing took me quite some time 😂).&lt;/p&gt;

&lt;p&gt;Finally for reference, here is my nvim-dap.lua configuration:&lt;/p&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;mfussenegger/nvim-dap&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;dependencies&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&quot;nvim-neotest/nvim-nio&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&quot;rcarriga/nvim-dap-ui&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&quot;ownself/nvim-dap-unity&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;-- to make sure install and setup &quot;vscodedebugger&quot; for unity&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;build&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
                &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;nvim-dap-unity&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;install&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;-- Lazy loading key&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;F5&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;dap&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;continue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;DAP Continue&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;n&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;F8&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;dapui&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;toggle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;DAP UI Toggle&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;n&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;F9&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;dap&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;toggle_breakpoint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;DAP Toggle Breakpoint&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;n&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;F10&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;dap&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;step_over&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;DAP Step Over&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;n&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;F11&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;dap&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;step_into&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;DAP Step Into&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;n&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;F12&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;dap&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;step_out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;DAP Step Out&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;n&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;-- Lazy loading cmd&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cmd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Dap&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;DapContinue&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;DapStepOver&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;DapStepInto&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;DapStepOut&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;DapToggleBreakpoint&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;DapUI&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;DapLaunch&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;DapAttach&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

        &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dap&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;dap&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dapui&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;dapui&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;dapui&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;-- initialize dapui&lt;/span&gt;

        &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;nvim-dap-unity&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;-- Dap UI&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;dap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;listeners&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;after&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event_initialized&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;dapui_config&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;dapui&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;dap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;listeners&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;after&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event_terminated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;dapui_config&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;dapui&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;dap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;listeners&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;after&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event_exited&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;dapui_config&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;dapui&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;-- Dap keymaps&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keymap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;n&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;F5&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;continue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keymap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;n&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;F8&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dapui&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;toggle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keymap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;n&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;F9&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;toggle_breakpoint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keymap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;n&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;F10&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;step_over&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keymap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;n&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;F11&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;step_into&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keymap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;n&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;F12&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;step_out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you have any questions or suggestions, feel free to leave a comment, send me an email, or open an issue on GitHub.
Thanks for reading and for using the plugin!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2026/NeovimDebugger.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h1 id=&quot;前情及动机&quot;&gt;前情及动机&lt;/h1&gt;

&lt;p&gt;我是一个游戏开发工程师，主要是在客户端相关的领域，使用Unity或者Unreal这样的引擎（因此我的工作平台似乎永远的被限制在了Windows上 😢），在过去许多年里我的编程工具组合发生过多轮的演化，但主要分为以下几个阶段：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Visual Studio / Code Warrior / Xcode : 在我刚开始职业生涯的4年间，主要从事PSP/Wii平台的Console游戏的开发，这个阶段我基本使用平台推荐的开发工具（开箱即用），但那个年代的编辑器无论是语法智能还是调试工具都无法和现在的工具同日而语&lt;/li&gt;
  &lt;li&gt;SublimeText : 之后我开始接触和学习Vim，而ST的出现以及对Vim Motion的不错的支持，让我可以以较低的学习曲线走进Vim的世界。大约6年的时间里我以SublimeText为主力编辑器来进行我的开发工作，只有偶尔需要Debug的时候，我才会迫不得已的用一下Visual Studio（对，我是Log党）&lt;/li&gt;
  &lt;li&gt;VS / Rider : 之后的几年里我经常需要在不同的项目之间做切换，智能联想对我开始变得更加重要和有用起来，于是我又回到了Visual Studio（VisVim）中，大约在2020年左右接触到了Rider，是有些被惊艳到的，可以说那时候的Rider集智能、速度、美观于一体，而且其Vim插件IdeaVim也是我用过的几个编辑器里面做的比较优秀的一个，甚至还能支持Unity Shader的函数跳转，那几年的编码体验无疑是幸福的&lt;/li&gt;
  &lt;li&gt;Neovim : GVim时代我一直没有太认真的花力气去配置，虽然它有着一等公民的Vim体验，但其他方面确实还是落后太多了，而Neovim的出现让这一差距不再明显，因为它有了对LSP和DAP的支持（感谢VSCode），断断续续的一年半的时间，我逐渐将Neovim配置到了一个非常可用的状态，而此时Rider在我工作的项目中开始表现越来越糟糕，启动缓慢，占用内存经常性的达到10GB，有几个特定的版本甚至还有内存泄漏问题……&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;于是在2025年年底，我终于正式使用Neovim代替Rider作为我在工作环境下使用的”IDE”&lt;/p&gt;

&lt;h1 id=&quot;neovim-basic-setup-1&quot;&gt;Neovim Basic Setup&lt;/h1&gt;

&lt;p&gt;每个人的Neovim的设定都不尽相同，这也是Neovim最大的魅力，制定外观、Keymap以及必要的插件等等，如果我们从头详尽的说起，可能需要写上几万字，因此这篇小文不会覆盖这部分的说明了，如果你是Neovim的新手，我推荐你观看Josean的Youtube教程：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=6pAG3BHurdM&quot;&gt;How I Setup Neovim To Make It AMAZING in 2024: The Ultimate Guide&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=oBiBEx7L000&quot;&gt;How to Setup Neovim LSP Like A Pro in 2025 (v0.11+)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;他的视频对新手非常友好，而且内容详尽，相信足以帮助大家上手基础的配置&lt;/p&gt;

&lt;h1 id=&quot;lsp和dap&quot;&gt;LSP和DAP&lt;/h1&gt;

&lt;p&gt;想要让Neovim可以很好的在Unity的工程中工作，这部分将是这篇文章主要讲解的，确实在网上也并不能找到很多相关的文章（大概很少有Unity开发者会使用Neovim来作为主力开发工具吧笑）&lt;/p&gt;

&lt;p&gt;LSP全称是Language Server Protocal，主要用于不同语言的智能联想支持的，DAP全称是Debug Adapter Protocol，适用于调试器的接口规范，这两个协议都是VSCode提出并发扬光大的，由于是开放协议它也造福了一众现代开源的代码编辑器，包括Neovim、Helix还有Zed，它们对智能联想和调试功能的支持都是依托于LSP和DAP&lt;/p&gt;

&lt;p&gt;而让Neovim很好支持Unity的开发关键在于如何配置好LSP和DAP！&lt;/p&gt;

&lt;h3 id=&quot;lsp--roslynnvim&quot;&gt;LSP : Roslyn.nvim&lt;/h3&gt;

&lt;p&gt;我最早配置的Neovim的C#支持的时候，使用的是OmniSharp，其表现并不是很令人满意，主要是速度方面，稍微大一点的工程跳转个函数定义都要1~2秒才能有反应&lt;/p&gt;

&lt;p&gt;当然我现在也不确定是不是我自己的配置不当造成的原因（因为现在OmniSharp项目实际上也是使用Roslyn作为后台了），但当时的使用体验感觉OmniSharp难堪重任&lt;/p&gt;

&lt;p&gt;&lt;del&gt;直到后来发现了一个比较新的使用Roslyn的Neovim LSP插件：&lt;a href=&quot;https://github.com/seblyng/roslyn.nvim&quot;&gt;Roslyn.nvim&lt;/a&gt;&lt;/del&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;2026/03/09更新：原始的Roslyn.nvim插件主要是为Dotnet项目服务，对于Unity的项目支持上是存在一些问题的，且原作者不希望大幅改变插件的逻辑（PR），所以我在我的Fork中做了很多围绕Unity的改动，现在推荐大家使用我的Fork仓库的版本&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;目前更推荐的方式是使用基于Roslyn LSP的插件&lt;a href=&quot;https://github.com/ownself/roslyn.nvim&quot;&gt;Roslyn.nvim&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;这个插件对比上游仓库的针对Unity的部分优化改动：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;更健壮的sln/csproj选择机制&lt;/li&gt;
  &lt;li&gt;当无法在多个sln/csproj中自动选择时，会弹窗提示用户进行选择&lt;/li&gt;
  &lt;li&gt;真正意义上支持同一个Session打开多个sln&lt;/li&gt;
  &lt;li&gt;提供了:Roslyn config来动态切换工程的配置&lt;/li&gt;
  &lt;li&gt;默认支持不生效的宏所包含的代码使用“灰色”的语法高亮&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;此外，这个插件的初始化速度以及函数跳转都令人印象深刻，而且还支持像”Inlay hints”这样的高级LSP功能&lt;/p&gt;

&lt;p&gt;Ramboe在他的Youtube频道中有关于这个插件的非常不错的介绍：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=yXhOgiqa0hI&quot;&gt;Neovim + C# in 2025: Roslyn LSP Changes Everything&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=yJc4AWf0TNs&quot;&gt;Neovim + C# in 2025: The Actually Improved Setup roslyn.nvim + rzsl.nvim&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;在他的视频里也介绍了DAP的一些配置，但他的配置主要是为了Dotnet项目所服务的，而非Unity项目。不过你仍然可以从他的视频中了解到DAP是如何工作的，为我们后面的配置做准备&lt;/p&gt;

&lt;p&gt;让我们回到LSP上，所幸Roslyn.nvim是同时支持Dotnet和Unity项目的，以下是我的Neovim中的Roslyn.nvim的配置方式：&lt;/p&gt;

&lt;p&gt;首先你需要在你的Mason的配置中（Josean的第一个视频教程中有关于Mason的讲解）添加Roslyn（目前Roslyn还没有正式被Mason收录）&lt;/p&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;mason&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;registries&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&quot;github:mason-org/mason-registry&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&quot;github:Crashdummyy/mason-registry&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这之后你就可以使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:Mason&lt;/code&gt;来打开菜单并安装Roslyn了：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2026/MasonRoslyn.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;之后通过Lazy添加Roslyn.nvim插件本身：&lt;/p&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;seblyng/roslyn.nvim&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ft&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;cs&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;opts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;-- your configuration comes here; leave empty for default settings&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;filewatching&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;off&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;-- currently other options lead huge performance dropping&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这里的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filewatching = &quot;off&quot;&lt;/code&gt;默认值是”auto”，这也是我目前使用Roslyn.nvim主要遇到的一个问题，我工作的项目中C#的源代码文件已经超过10万了，如果使用默认值的话每次保存文件都会引起2~3秒的卡顿，因此我暂时通过这个设置来解决问题，代价是我偶尔在文件改动后需要通过Keymap来手动启动一下LSP Server：&lt;/p&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keymap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;n&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;leader&amp;gt;lr&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cmd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;LspRestart&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;noremap&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Restart LSP Server and enable Copilot&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;最后你可能还需要在配置目录的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;after/lsp/roslyn.lua&lt;/code&gt;中设定LSP的具体功能（Neovim 0.11+的方式，可以参考Josean的第二个视频）：&lt;/p&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;settings&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;csharp|inlay_hints&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;csharp_enable_inlay_hints_for_implicit_object_creation&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;csharp_enable_inlay_hints_for_implicit_variable_types&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;csharp_enable_inlay_hints_for_lambda_parameter_types&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;csharp_enable_inlay_hints_for_types&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;dotnet_enable_inlay_hints_for_indexer_parameters&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;dotnet_enable_inlay_hints_for_literal_parameters&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;dotnet_enable_inlay_hints_for_object_creation_parameters&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;dotnet_enable_inlay_hints_for_other_parameters&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;dotnet_enable_inlay_hints_for_parameters&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;dotnet_suppress_inlay_hints_for_parameters_that_differ_only_by_suffix&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;dotnet_suppress_inlay_hints_for_parameters_that_match_argument_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;dotnet_suppress_inlay_hints_for_parameters_that_match_method_intent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;-- so far we use symbol-usage.nvim for this function&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;-- [&quot;csharp|code_lens&quot;] = {&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;-- 	dotnet_enable_references_code_lens = true,&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;-- },&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;dap--nvim-dap&quot;&gt;DAP : nvim-dap&lt;/h3&gt;

&lt;p&gt;在Ramboe的视频中已经有了一些如何设置nvim-dap的基础内容，插件本身的安装和使用并不算太复杂，但比较让人生畏的是对应语言的dap工具的安装以及配置&lt;/p&gt;

&lt;p&gt;所幸nvim-dap的官方组织了一个&lt;a href=&quot;https://codeberg.org/mfussenegger/nvim-dap/wiki/Debug-Adapter-installation&quot;&gt;Wiki页面&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;大致的流程是你需要下载你所使用的语言的dap工具（大部分情况需要添加到PATH环境变量中），之后使用Wiki中默认配置就已经可以勉强工作了，之所以说勉强是因为很多语言例如C#、Rust、C++在你启动调试的时候，还需要你手动指定所要调试的可执行文件的位置&lt;/p&gt;

&lt;p&gt;细心的话，在上面nvim-dap的Wiki中也已经找到了介绍了Unity的&lt;a href=&quot;https://codeberg.org/mfussenegger/nvim-dap/wiki/Debug-Adapter-installation#unity&quot;&gt;Dap Debugger如何设置&lt;/a&gt;，不过遗憾的在我的尝试中发现官方Wiki介绍的方法实际上已经是过时的了，因为VSCode中的Unity Debugger已经从Unity编写的工具改为了微软自家维护的&lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=visualstudiotoolsforunity.vstuc&quot;&gt;Unity插件&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;而且配置方式也有些不同，所幸最终在各种论坛+ChatGPT的帮助下，我还是成功的让Unity的Debugger在Neovim下跑通了！&lt;/p&gt;

&lt;h3 id=&quot;nvim-dap-unity-1&quot;&gt;nvim-dap-unity&lt;/h3&gt;

&lt;p&gt;调研的过程中，我发现似乎“改进Unity-Dap部署”类型的插件在市面上还是个空白，于是决定再接再厉，干脆把我的工作封装成一个插件分享出来，虽然我想可能不会有太多Unity开发者会使用Neovim作为它们的主力开发工具（Rider确实还是目前更好的选择），但总还是有可能帮到一些像我一样的Neovim爱好者的吧&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/ownself/nvim-dap-unity&quot;&gt;nvim-dap-unity&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2026/nvim-dap-unity.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;这个插件主要做了三件工作以确保你可以有一个“开箱即用”的Unity Debug体验：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;自动下载vscode tool for unity并解压至nvimdata目录（Windows/MacOS/Linux全平台）
    &lt;ul&gt;
      &lt;li&gt;使用Lazy安装时会自动安装，或者可以使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NvimDapUnityInstall&lt;/code&gt;命令来手动安装&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;为nvim-dap配置好默认的启动命令（”Attatch Unity Editor”）
    &lt;ul&gt;
      &lt;li&gt;同时支持与现有的C#的（dotnet）dap配置进行合并&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;启动调试的时候自动搜索并加载Unity工程下对应的dll文件&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;插件我在Windows、MacOS甚至是Linux（Linux下的测试可是花了不少时间，笑）都进行过测试了&lt;/p&gt;

&lt;p&gt;为了便于参考，以下是我的nvim-dap.lua的配置文件：&lt;/p&gt;

&lt;div class=&quot;language-lua highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;mfussenegger/nvim-dap&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;dependencies&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&quot;nvim-neotest/nvim-nio&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&quot;rcarriga/nvim-dap-ui&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&quot;ownself/nvim-dap-unity&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;-- to make sure install and setup &quot;vscodedebugger&quot; for unity&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;build&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
                &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;nvim-dap-unity&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;install&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;-- Lazy loading key&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;F5&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;dap&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;continue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;DAP Continue&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;n&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;F8&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;dapui&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;toggle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;DAP UI Toggle&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;n&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;F9&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;dap&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;toggle_breakpoint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;DAP Toggle Breakpoint&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;n&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;F10&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;dap&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;step_over&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;DAP Step Over&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;n&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;F11&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;dap&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;step_into&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;DAP Step Into&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;n&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;F12&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;dap&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;step_out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;DAP Step Out&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;n&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;-- Lazy loading cmd&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cmd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Dap&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;DapContinue&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;DapStepOver&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;DapStepInto&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;DapStepOut&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;DapToggleBreakpoint&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;DapUI&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;DapLaunch&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;DapAttach&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

        &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dap&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;dap&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;local&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dapui&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;dapui&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;dapui&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;-- initialize dapui&lt;/span&gt;

        &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;nvim-dap-unity&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;-- Dap UI&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;dap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;listeners&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;after&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event_initialized&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;dapui_config&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;dapui&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;dap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;listeners&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;after&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event_terminated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;dapui_config&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;dapui&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;dap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;listeners&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;after&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event_exited&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;dapui_config&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;dapui&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;-- Dap keymaps&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keymap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;n&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;F5&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;continue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keymap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;n&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;F8&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dapui&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;toggle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keymap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;n&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;F9&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;toggle_breakpoint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keymap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;n&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;F10&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;step_over&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keymap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;n&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;F11&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;step_into&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keymap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;n&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;F12&amp;gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;step_out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;如有问题和建议欢迎留言，或者给我发邮件，也可以直接在Github上提issue，感谢关注和使用！&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2026/NeovimDebugger.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

        </description>
        <pubDate>Wed, 14 Jan 2026 21:53:41 +0000</pubDate>
        <link>/2025/setup-neovim-for-unity-development.html</link>
        <guid isPermaLink="true">/2025/setup-neovim-for-unity-development.html</guid>
      </item>
    
      <item>
        <title>SublimeText LSP-Roslyn</title>
        <description>
          
          &lt;p&gt;Sublime Text（以下简称ST）曾经在2012~2018年之间是我日常开发中的主力代码编辑器，在那时刚刚开始了解Vim Motion的我，曾经为它简洁的设计、快如闪电的性能表现和兼顾了Vim模式与漂亮的视觉表现的特性而惊艳不已&lt;/p&gt;

&lt;p&gt;以致于直到今天，我的代码编辑器的Keymap中依然保留着很多ST的影子&lt;/p&gt;

&lt;h1 id=&quot;流派之争&quot;&gt;流派之争&lt;/h1&gt;

&lt;p&gt;代码编辑器一直有两个流派：IDE vs Code Editor&lt;/p&gt;

&lt;p&gt;IDE（Integrated Development Environment，集成开发环境）就是以Visual Studio， JetBrain等为代表的一站式开发工具，一般自带了开发环境、代码编辑器和调试器，还支持代码的智能联想、性能分析器等各种高级功能，其理念就是不断地添加“高级和智能”的各种开发功能，力争让用户仅一次“傻瓜式”安装即可得到完整的开发环境，非常适合初学者上手。&lt;/p&gt;

&lt;p&gt;当然，代价就是IDE一般体积巨大，轻松上GB，而且内存占用高企，启动和运行都会被那些庞杂的高级工具们所拖累，即使90%的情况下你并不会用到它们（笑）&lt;/p&gt;

&lt;p&gt;Code Editor则是以Vim/Emacs为代表的另一种流派，追求极致的性能和编写代码的速度，关于这个话题可以吹好久好久，这里就不展开说了，总之这个流派一直很偏极客，使用者往往追求更流畅的编写代码的体验，而宁愿舍弃智能联想这类“先进”的工具&lt;/p&gt;

&lt;h1 id=&quot;sublimetext&quot;&gt;SublimeText&lt;/h1&gt;

&lt;p&gt;但是Vim和Emacs太硬核了，学习曲线和上手难度都非常反人类，在当年我觉得除非你是服务器程序员，不可避免地需要在SSH环境下编写代码，只能被迫上手Vim外，桌面环境下的程序员很难有动力去走上这条道路&lt;/p&gt;

&lt;p&gt;ST的出现在当年就是为所有在桌面环境下编程的程序员搭了这么一个“梯子”，一方面它有着现代的漂亮的界面；另一方面性能又非常优秀，无论是启动还是在海量文件的工程中跳转搜索，都要优于当时市面上大部分的代码编写工具；而真正吸引我的是它自带了Vim模式的支持，这让当时正在入门Vim世界的我来说是非常好的敲门砖了&lt;/p&gt;

&lt;p&gt;ST本身也没有限定特定的语言环境，这使得无论你使用哪门语言，都可以在ST中找到很不错的开发体验，可以说ST的出现让“Code Editor”这一流派从之前的服务器开发环境中破圈而出&lt;/p&gt;

&lt;h1 id=&quot;vscode&quot;&gt;VSCode&lt;/h1&gt;

&lt;p&gt;之后VSCode的出现则是更大的一次破圈了，而且我觉得VSCode真正具有里程碑意义的是，他提出了LSP（Language Server Protocol）和DAP（Debugger Adapter Protocol）两个造福全(程)人(序)类(员)的规范，让代码智能感知和调试器这两种通常是IDE杀手锏的功能进入“Code Editor”这一流派中成为了可能&lt;/p&gt;

&lt;p&gt;当然VSCode有它自己的问题，由于使用了Electron框架，其糟糕的性能一直为“Code Editor”原教旨主义者所诟病，我也因此从来没有将VSCode当作过自己的主力编程工具&lt;/p&gt;

&lt;p&gt;但瑕不掩瑜，要知道更现代的”Code Editor”流派中的编辑器：Neovim、Zed、Helix都是依托LSP和DAP来实现相关的功能的，甚至Claude Code这样的编程工具现在也都在遵循LSP协议了（笑）&lt;/p&gt;

&lt;h1 id=&quot;lsp-roslyn&quot;&gt;LSP-Roslyn&lt;/h1&gt;

&lt;p&gt;当VSCode出现后，因为其开源和出色的易用性，迅速大放光彩，而那时候ST也显得有些过时了，即使其性能表现明显更优，而虽然ST后来（大约2018）也加入了LSP协议的支持，但是那时候ST已经不再是我的主力开发工具了，就我有限的测试，其LSP的支持与使用体验，也确实无法与VSCode相比较&lt;/p&gt;

&lt;p&gt;因此在整整6年的ST使用生涯中，对于LSP功能的缺失，一直算是我对ST的热爱的一种遗憾和缺失吧&lt;/p&gt;

&lt;p&gt;借着AI在今年对编程方式产生翻天覆地变革的浪潮，我也琢磨着用AI编程练习着开发点什么自己并不擅长的领域中的小工程/工具呢？于是在思来想去，这个插件就问世了！&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/ownself/LSP-Roslyn&quot;&gt;https://github.com/ownself/LSP-Roslyn&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2026/lsp-roslyn.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;ST其对C#的LSP的支持直到今天都是基于OmniSharp的，而OmniSharp就我在Neovim中的使用经验来看，性能和表现确实不如直接基于Roslyn来的好，刚好在ST的社区中这还算是个空缺，于是就尝试利用Agent Coding来开发试试&lt;/p&gt;

&lt;p&gt;工具使用的是Claude Code + Sonnect 4.5，后期功能改进使用了Open Code + Opus 4.5，开发的过程AI的表现确实是赏心悦目，这种级别的插件写起来真的是信手拈来，也是实实在在的让我感受到了“大人！时代变了！”&lt;/p&gt;

&lt;p&gt;甚至GitHub上的配图都是GPT5.1帮忙生成的：）等于这个插件就没有一行我自己手写的内容&lt;/p&gt;

&lt;p&gt;插件在Sublime Text最新版4200下测试功能均正常，Dotnet工程或Unity项目均可支持&lt;/p&gt;

&lt;p&gt;此外看了下，ST的LSP插件一直是在官方的组织中开发和维护的，不像普通的ST的插件，感觉如果要发布到ST官方的插件仓库里可能难度不小，而且现在ST的社区也确实大不如前了，真的还有人在用ST来开发C#项目吗？这个插件会不会真的帮助到别人只能等一手有缘人吧（笑）~&lt;/p&gt;

        </description>
        <pubDate>Tue, 06 Jan 2026 06:27:51 +0000</pubDate>
        <link>/2025/sublime-text-plugin-lsp-roslyn.html</link>
        <guid isPermaLink="true">/2025/sublime-text-plugin-lsp-roslyn.html</guid>
      </item>
    
      <item>
        <title>关于编程字体的思考</title>
        <description>
          
          &lt;p&gt;我有一款使用超过十二年的编程字体，但是我一直也没敢逢人便安利，因为我知道字体这个东西每个人可能都有属于自己的品味和喜好&lt;/p&gt;

&lt;p&gt;这些年间，我也时不时在各处看到有人推荐一些新晋流行的编程字体，什么Consolas、Source Code Pro、Menlo，还有最近随着编辑器一起流行起来的JetBrain Mono，同一个字体使用久了，我也渴望换一换心情，于是便找来试用，但这么多年下来，这些“新鲜”的字体大多没有能让我坚持超过三个小时的……&lt;/p&gt;

&lt;p&gt;到今年，想了想这款字体我已经使用了超过12年了，我想我应该已经有推荐它的资格了吧&lt;/p&gt;

&lt;h1 id=&quot;m-font&quot;&gt;M+ Font&lt;/h1&gt;

&lt;p&gt;这款字体就是”M+ Font”中的编程版本字体——M+ 1mn&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://mplusfonts.github.io/&quot;&gt;M+ Font官网&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;这是一款来自日本设计师森下浩司的作品（我其实也是这次写作才知道作者的名字，惭愧……），最早发布于2003年，并于2008年被Smashing Magazine评选为「当月字体」并开始收到关注。我在2012年左右接触到这款字体，一经试用便爱不胜收，从此之后，我在工作中更换过数款编程使用的IDE：Visual Studio -&amp;gt; Sublime Text -&amp;gt; VSCode -&amp;gt; Rider，还有一直离不开的(Neo)Vim，但无一例外的，均使用着”M+ 1mn”这款系列字体中专为编程所设计的等宽版本&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2025/m+1mn.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;当我真准备要推荐这款编程字体的时候，我倒是应该系统地好好想想，究竟什么样的编程字体才算是好的编程字体呢？&lt;/p&gt;

&lt;h1 id=&quot;编程字体需要什么&quot;&gt;编程字体需要什么&lt;/h1&gt;

&lt;p&gt;JetBrain也是老牌的IDE生产力工具厂商了，他们最近几年开始大放异彩，我在工作环境下的IDE也换成了Rider。题外讲一句Rider确实好用，可以说是目前游戏开发者的不二选择，无论你是使用Unity还是Unreal引擎。至少在目前，它是综合体验最好的IDE，速度也比VS要快上不少。要说缺点，就是编辑器刚打开工程时处理的时间比较长（要做缓存和索引），此外，内存占用也是个问题，大一点的工程，5GB+的占用轻轻松松&lt;/p&gt;

&lt;p&gt;我们说回字体，JetBrain在2020年的时候推出了他们自己的编程字体JetBrain Mono，用来作为自家编辑器的默认字体，这几年间看到过很多国外的Up主都在用这款字体，我也试用并研究过一阵子。说来有趣，我虽然用了好多年的M+ 1nm，但是从来都只是在直觉上觉得它看着“舒服”，看着“喜欢”，可你让我说出些门门道道来，我还真说不出来，直到看了JetBrains吹他们字体的设计思路，我似乎才更明白了一些为啥我一直离不开”M+ 1mn”，也对一款编程字体真正需要什么特质有了更多的思考：&lt;/p&gt;

&lt;h3 id=&quot;一辨识性&quot;&gt;一、辨识性&lt;/h3&gt;

&lt;p&gt;编程字体之所以是编程字体，那么它一定是有着区别于其他字体的一些特性的，首先就是相似字符的辨识性，英语的大小写字符以及标点符号中有一些长得很像的字符，例如”l”和”I”，还有”0”和大小写的”O”啊，人在阅读英文单词时，即使个别字符不易分辨，我们也可以靠着“脑补”来无障碍的完成文章内容的识别，但在代码环境中，比起单词本身，会出现更多字符数字混编的情况，一行行的代码与文章中的排列迥异，变量名的组成也与我们日常阅读的单词不尽相同，这就要求这类字符之间需要能有明显的特点区分，即使脱离词句的环境，也可以让我们的大脑可以相对轻松的做出精确识别&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2025/m+1mn_chars.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;不过在这一点上，其实现代编程字体几乎都做得很好，之间也很难拉开差距，这并不是我喜爱”M+ 1mn”的主要原因&lt;/p&gt;

&lt;h3 id=&quot;二等宽&quot;&gt;二、等宽&lt;/h3&gt;

&lt;p&gt;这个也算是编程字体的一个硬性要求，因为“缩进”一直是编码规范中一个充满争议的话题，你想程序员是一群连“Tab vs Space”都要吵个没完没了的群体，你可以想象当争吵的双方如果同时看到一个不用等宽字体的程序员突然出现在他们的视野中场面都安静下来的喜剧感（实际上也是有很多人在编程环境中使用非等宽字体的，并不绝对的）&lt;/p&gt;

&lt;p&gt;字体的等宽和缩进一样也都是属于改善代码的阅读性的范畴，当你阅读代码时，等宽的字体除了美观外，还可以帮你减轻很多诸如“对比字符串长度”，“变量名长度”等等下意识活动的负担&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=oRva7UxGQDw&quot;&gt;电视剧《硅谷》中经典的Tab vs Space桥段&lt;/a&gt;【其实我也更倾向于Tab，但是我是Vim Guy】&lt;/p&gt;

&lt;h3 id=&quot;三可阅读性&quot;&gt;三、可阅读性&lt;/h3&gt;

&lt;p&gt;因为我同时也是个电子阅读器的爱好者，家里的墨水屏设备已经7、8个了。而每一个电子阅读器的爱好者也一定会对阅读时使用的字体“千挑万选”，我自不例外，在这个过程中，势必会接触到一些字体设计上的知识，而在“可阅读性”上，我觉得很重要的一点其实是——“衬线”（Serif）&lt;/p&gt;

&lt;p&gt;所谓衬线就是指字体在比划的“边角”上适当添加的装饰，最有名的中文衬线字体就是宋体了，不要小看那比划末尾的那一点点“冗余”！当初宋体最早是作为活版印刷的字体而出现的，其设计理念中很重要的一点就是节省成本（油墨），因此比划会倾向于尽可能细，但太细会让可辨识性大打折扣，阅读一会儿眼睛就会疲劳，甚至大脑宕机（笑），而聪明的先人们发现，其实只要在关键的比划位置增加这一点点“冗余”，那么就可以在几乎不多费油墨的同时，大幅提升字体的可阅读性，而且还让字体变得更具艺术感也更活泼&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2025/serif_font.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;那么既然衬线字体这么好为什么我们手机和电脑上的主流字体全都是黑体呢？这个主要是受电子显示设备的局限，印刷行业的最低要求是300PPI，而24寸的1080P显示器，只有可怜的92PPI，在这样的设备上显示小号字体时会大量丢失像“衬线”这一类的细节，更别说走样也会让字体原本的美感荡然无存，也因此早期计算机的字体都是采用点阵的方式来设计字体，这也是类黑体在电脑设备上如此普及的重要原因&lt;/p&gt;

&lt;p&gt;不过现在随着高分辨率显示设备的发展，这一情况正在得到改善，只要屏幕的PPI能够接近300这一人眼观察的“阈值”，而且你并非是“小字号”爱好者，那么字体带有一些“衬线装饰”是绝对会帮助提升可阅读性的，因为你要记得，人类阅读文字的过程，终究是一个“图像模式识别”的过程，更多一些的字符特性会更利于大脑做出准确的识别判断&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2025/fonts_compare.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;字体在衬线上的设计往往带有鲜明的个性，对于衬线的帮助，我们有时也需要辩证的看待，太过“花里胡哨”反而可能会分散我们阅读时的注意力，变得矫枉过正，更要记得字体的渲染依然还在受着液晶屏幕的物理限制。对于这一块，我其实更倾向于相信我们的直觉，只要你知道这背后隐藏的门门道道，剩下的，就交给自己的“眼缘”来判断吧（也可以前后对比着切换的使用几个小时试试看）&lt;/p&gt;

&lt;h3 id=&quot;四瘦且长&quot;&gt;四、”瘦且长“&lt;/h3&gt;

&lt;p&gt;JetBrain Mono的设计理念中首当其冲的的是小写字母高度设计，在保持字符宽度的同时，适当的提高小写字母的高度，会有利于代码的阅读。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2025/jbmono.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;最早看到这一展示时，我“恍然大悟”——原来这就是我试用很多流行字体坚持不了三个小时的主要原因吗？因为直觉上我用的M+ 1mn字体也是一种“瘦且长”的字体，而后当我进一步仔细对比了JetBrain Mono和M+ 1mn时，我似乎又有了新的思考……&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2025/jbvsm+1mn.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;我们正常阅读使用的字体为啥不是等宽的呢？（仅限英文，因为中文本来就都是等宽的）其实原因也很直白，就是因为非等宽的字体更紧凑，更利于阅读；这时你再加上“编程字体需要等宽”的条件，是不是可以得出这样一个结论：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;在等宽的基础上，字体越紧凑，可阅读性就越好！&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;JetBrain Mono提升小写字符高度的做法其实是在这一方向上做的视觉努力，而M+ 1mn则是直接将字体做的更紧凑而已&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2025/fonts_compare2.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;如果单独把每一个字体配合上漂亮的配色在现代的IDE中做展示，我相信都很漂亮，但是当你把他们排在一起对比是，你就会开始对可阅读性有一个更直观的对比&lt;/p&gt;

&lt;h1 id=&quot;结论&quot;&gt;结论&lt;/h1&gt;

&lt;p&gt;我并无意表示M+ 1mn就是最好的编程字体了，因为字体的选择归根到底还是Personal Preference，只是在有了上面这些思考后，看起来我还会继续坚守这个字体一阵子了，写这篇文字的目的也是希望能激发大家的一些思考，如果你天天都要面对都要使用的东西，谁不希望有自己更懂更偏好的选择呢？&lt;/p&gt;

&lt;h1 id=&quot;附&quot;&gt;附&lt;/h1&gt;

&lt;p&gt;在写这篇文字的时候，我才从M+的官网发现，他们的字体设计上发生了一些变化（我一直使用备份在自己的Github上的旧版本），再追溯Github的历史，发现这一变化大概是从2019年开始的，我能注意到的是以下几点：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;字体的官方名称从M+ 1/2改为了M Plus 1/2&lt;/li&gt;
  &lt;li&gt;适用于编程的字体由M+ 1mn改为了M Plus 1 Code&lt;/li&gt;
  &lt;li&gt;我不知道是刻意为之还是无心之过，新版的Medium Weight的字体要比以前更粗一些……（可以对比上图前两行之间细微的差别）&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;如果你和我一样对旧版的粗细度更钟情，我这里提供了旧版的下载，有原始版本和打了Nerd Font Patch的版本，以方便你在编程和终端两个环境下使用 :-)&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/assets/2025/M+1mnNerdFont-Medium.ttf&quot;&gt;M+ 1mn Medium&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/assets/2025/M+1mnNerdFont-Medium.ttf&quot;&gt;Patch过Nerd Font的M+ 1mn Medium&lt;/a&gt;&lt;/p&gt;

        </description>
        <pubDate>Sat, 17 May 2025 14:05:10 +0000</pubDate>
        <link>/2025/thinking-of-programming-font.html</link>
        <guid isPermaLink="true">/2025/thinking-of-programming-font.html</guid>
      </item>
    
      <item>
        <title>[书评] 内耗论</title>
        <description>
          
          &lt;p&gt;我的父亲是公务员，长期从事党内理论研究相关工作，当过党校的老师，做过党内刊物的编辑，也写过几本相关的理论书籍，而这本书是我父亲写过的其中一本，但非常惭愧的是，我直到去年才拿起来这本书认真的读完。&lt;/p&gt;

&lt;p&gt;这本书带有着鲜明的时代色彩，背景是改革开放大刀阔斧的90年代，以内耗现象为中心讨论我国社会发展以及改革开放中存在的各种问题，并进行了如何去解决这些问题的一些讨论。&lt;/p&gt;

&lt;p&gt;如果放在今天去看，这些问题都似乎是过去时了，那些在改革开放初期让人迷茫的一些问题，现在也都顺利的解决了，不过如果你想象一下把自己重新置回那个波澜壮阔的年代，面对那些从来没有人有过经验的问题，谁又有十足的把握能坦然面对呢？&lt;/p&gt;

&lt;p&gt;不过这本书终究不是一本通俗读物，书中有接近一半的内容还是我们小时候在政治书上看到过的那种社会主义语法（按我的话说就是那种让人摸不着头脑的车轱辘话，笑），但每章这部分讲完后，我父亲会开始举一些历史上的故事来做例证，每次看到这里，我记忆中那个博古通今的父亲又回来了，我小时候最喜欢听他讲历史故事了，直到今天阅读这本书我还能发现父亲知道那么多我不知道的事情！&lt;/p&gt;

&lt;p&gt;读这本书时我还能再次体会到父亲的思想脉络，父亲的处事态度温和，否定极端的行事风格，无论是保守还是激进，主张兼听则明，鼓励学习西方的先进理论与技术，但同时拥抱中国古典中优秀的传统与思想。这本书也很敢言，直言不讳的批评了大跃进、文化大革命是建国以来最大的内耗行为。&lt;/p&gt;

&lt;p&gt;这本书一共四位共著者，父亲是第二作者，第一作者是他多年的老领导，但实际上包括另一本他也作为第二著者的书都是95%以上的内容是由我父亲独立完成的，这可能就是当年体制内的行事规则吧。&lt;/p&gt;

&lt;p&gt;父亲喜欢熬夜写作，我还记得小时候他经常写作一宿后天亮钻进我刚刚起床的被子，说这样被子就是已经暖好的了（笑）；我还记得父亲熬夜写作时喜欢吸烟帮助思考，常常会一夜抽掉整包烟，中间母亲担心过他的身体，让他换成瓜子来代替，结果早上父亲说一晚上什么都没写出来，光顾着嗑瓜子了（笑）&lt;/p&gt;

&lt;p&gt;算到今年父亲已经离开我们十年了，我成为了父亲精神的继承者，我的性格、思想中处处都是他的影响，在我成长过程中，那些他对我说过的话和道理，也深深的刻在我的内心深处。&lt;/p&gt;

&lt;p&gt;如今我也成为了一位父亲，我希望在父亲这一角色上，我也能与我父亲当年给予我的一样，成为孩子的心中的榜样和信念根源，我不奢望自己可以达到他的高度，只是心怀敬仰的照着他的样子努力而笨拙的学着。&lt;/p&gt;

&lt;p&gt;这本书市面上应该已经绝版了，于是我花了些时间制作了电子版，希望能让父亲的作品也可以在互联网的世界中继续流传：&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/assets/2024/内耗论.epub&quot;&gt;下载内耗论EPUB格式&lt;/a&gt;&lt;/p&gt;

&lt;h1 id=&quot;笔记&quot;&gt;笔记&lt;/h1&gt;

&lt;p&gt;内耗论
刘锦棠&lt;/p&gt;

&lt;h2 id=&quot;第一章-内耗整体小于部分之和&quot;&gt;第一章 内耗:整体小于部分之和&lt;/h2&gt;

&lt;p&gt;总结：内耗是什么&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;发生内耗的直接原因,是系统内部失去协同,是由于各组成部分在总体运行过程中步调混乱和无序。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;那么内耗,就是指事物处于某种无序或不协调状态下,其系统内各组成部分之间的作用相互抑制和相互冲突,从而使各种有用力量相互抵消的现象。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;一个民族和国家要振兴、要发展,就一定要实现内部的安定团结,赢得一个稳定的国内局面与和平的国际环境。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;因为并非任何矛盾和斗争都会引发内耗,这需要作出具体分析。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;古人曾用“萧墙之忧,惨于戎敌”,来说明同室操戈、手足相残造成的恶果远甚于外部敌对势力入侵所带来的灾难。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;协同,或者说合作、协调、同步、互补,也是事物发展的动力源泉之一。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;缺乏竞争的协同和失去活力的有序,只能是一潭死水,不是真正意义上的协同和有序。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;我们提倡正常的竞争,并不是要否定它可能带来的副作用,而是相对于缺少竞争和开展不正常竞争所造成的内耗更大而言,这种正常竞争能够尽可能地减少内耗。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;第二章-世界至善论的破灭&quot;&gt;第二章 “世界至善论”的破灭&lt;/h2&gt;

&lt;p&gt;总结：内耗普遍存在&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;正如《周易》上说的“事不穷,善不纯,理不尽”,至善至美的事物是不存在的。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;人的认识和实践活动并非都在理性思维的指导下自觉地、有意识地进行的,那些受本能驱使的欲望等潜意识往往倒是人们行为的先导,其中某些非逻辑环节如灵感、直觉还在科技发展史上起过重要作用。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;任何社会制度都无法做到调动一切人的积极性,总有消极、落后和腐朽力量的存在。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;迄今为止的各种国家形态中,公共权力还都未能交由全社会的公众去直接行使,而只能以某种方式通过社会的代表去间接集中行使&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;公共权力就异化为私有权力,产生询私枉法、权钱交易、官商勾结、警匪勾结等权力腐败现象。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;人类总体能力的发展是以牺牲大多数个体,甚至牺牲整个阶级的发展机会为代价的。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;异化就是对人的劳动的占有,对人的本质的否定。奴隶制度是赤裸裸的占有和否定,封建专制制度是以宗教和国家等为中介的占有和否定。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;大多数人必须整日进行辛勤劳作,为社会创造剩余产品,去供少数人从事政治、科学、文化、艺术的活动,创造新的文明。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;注 | 机器的出现应该是对此有正面帮助的&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;一个阶级的任何新的解放,必然是对另一个阶级的新的压迫&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;那就是发展必然打破旧的平衡而出现新的不平衡。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;改革必然使社会原有的利益格局发生重大调整&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;第三章-走出伊甸园的人类&quot;&gt;第三章 走出伊甸园的人类&lt;/h2&gt;

&lt;p&gt;总结：举例说明社会中的各种内耗现象&lt;/p&gt;

&lt;h3 id=&quot;一楚王好细腰宫女多饿死&quot;&gt;一、楚王好细腰,宫女多饿死&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;制度中相当大一部分社会行为规则是由社会强制执行的,所以只有符合制度要求的思想和行为才能不遭受惩罚,也才能在人们的脑神经上留下深刻的印记。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;从最低标准看,评判一个制度好坏的标尺就是看该制度是否提供了作恶而不受惩罚的机会和缝隙。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;不规范的制度生产着不规范的社会行为。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;各个制度都有其基本的利益分配机制,如资本主义制度的按资分配,社会主义的按劳分配。无论那种制度,利益协调的实质都是解决公平与效率的矛盾问题。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;公平总是相对的,永远不可能有彻底的绝对的公平。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;社会财富的分配有三次:第一次通过市场机制来分配,按经济上的公平原则进行,劳动者按其劳动投入获得报酬,投资者按其收益获取利息。第二次是按政治上的公平原则进行的,国家通过财政税收形式进行国民收入的再分配和调节&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;第三次是按道德上的公平原则进行的,人们出于同情心和道义的感召,捐助一些资金给教育和福利机构,帮助老弱病残。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;二社会演进中的瓶颈期社会危机与内耗&quot;&gt;二、社会演进中的“瓶颈”期社会危机与内耗&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;中国历史上的几乎所有封建政权在它们建立后的 40 年左右,都要发生一次政权危机,即进入瓶颈期。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;这种主观失误的背后却隐藏着政治经济体制的很大缺陷,就是权力高度集中,权力缺少制衡和监督系统,从而导致权力使用者的主观意志膨胀和滥用权力以及由此造成的非科学化决策。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;社会危机分为经济危机、政治危机和文化危机。从广义文化论的角度看,任何社会都是包含着三个层次的同心圆:最外是物器层,即指人们创造的物质产品及其经济再生产过程;中间是制度层,包括人际关系及其规范化了的社会制度,关键是政治制度和政治设施;最内层是文化观念层,包括价值观念、理论体系和国民意识以及在这些观念意识指导下的行为准则。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;个体意识是人的自主性、创造性的动力源泉。而社会意识政治化则抹杀了个体意识,以过于单一的、泛化的、抽象的某种政治意识形态来取代或涵盖生动的丰富的具体的文化思想,造成个体和群体无意识,造成愚民和盲从,造成理论脱离生活实际,从而扼杀思想自由,窒息了人的主动性和创造力。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;社会意识政治化还可能服从于某些政治权威的某种政治目的,而将人们引入一场政治斗争的旋涡之中。例如,文化革命就是“阶级斗争”这种政治意识极度膨胀的产物,它虽然是由“意识形态领域内的革命”引起的,后来却演变成一场内战式的“武化革命”。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;在一元化政治意识的绝对权威一旦丧失情况下,则一种无秩序、无主导、多元化的文化价值格局必然代之而起。社会意识对社会精神取向的指导和整合功能骤然解体,人们失却了应有的人生信仰和价值标准,造成普遍的心态紊乱和行为失范,甚至发生人格解组和道德滑坡。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;这是因为文化是一种世代之间的社会遗传机制,它以符号基因形式浓缩着一个民族创造物质财富的全部智慧,录制着一个社会组织的结构信息。当一个社会组织及其物质基础崩溃后,只要一部分社会成员幸存下来,那么文化作为社会遗传机制就表现出巨大的自我复制能力。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;三潘多拉魔盒的打开社会转型与内耗&quot;&gt;三、“潘多拉魔盒”的打开社会转型与内耗&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;高犯罪率是转型社会的明显特征,其产生的历史背景就是权威真空和社会控制功能的弱化。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;四人类互相残杀的怪物战争是人类社会内耗的最激烈形式&quot;&gt;四、人类互相残杀的怪物战争是人类社会内耗的最激烈形式&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;人的侵犯性分为内向和外向两种形式,自杀是人的侵犯性行为的内向表现,即把暴力用于自己的心灵和肉体;凶杀是侵犯性的外向表现,亦即用暴力侵犯他人生命。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;第四章-人类进化大风歌&quot;&gt;第四章 人类进化“大风歌”&lt;/h2&gt;

&lt;p&gt;总结：内耗与社会发展之间的关系&lt;/p&gt;

&lt;h3 id=&quot;二人类文明进化之风&quot;&gt;二、人类文明进化之风&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;列举了地球上曾经存在过的 21 个人类文明中有 15 个灭亡的情况,究其失败的原因也正是他们当初成功的原因,&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;中国封建社会就属于这种封闭的稳定态系统,它对外闭关锁国,实行海禁,对内限制工商业发展,推行重农抑商政策,内外都缺少流动性,近似凝固状态。由于极端封闭,它不能吸收世界各国的先进文化和科学技术,系统内部也无法产生新的社会组织结构;相反,内外封闭使它的内熵不断积累—— 冗官、冗兵、苛税、土地兼并、统治集团内讧以及阶级矛盾和民族矛盾日益尖锐化。在这种情况下,它就产生了上述自组织运动:通过周期性崩溃来消除无序力量(每一周期循环约二三百年),但这种周期巨涨落并未产生出新的有序结构,而是恢复和保存了旧结构。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;自秦至清 2000年的封建社会中,分裂、战乱的时期总加起来,竟有 800 年之久。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;社会系统要减少内耗,增加有序度,就必须充分对外开放,以取得足够的负熵流即信息(包括技术信息、制度信息和文化信息)。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;人类进化主要依靠文化进化,即文化信息的选择与重构。人类在改造客观世界的过程中,对外部环境的有关信息加以接收、选择、浓缩、保存和重组,以概念、原理的形式固定下来,就成为人类特有的文化信息。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;社会主义模式。这种模式更接近于“他组织”,即以自主调节为主要手段,而相应地缺少社会的自发调节。这种单纯的自主调节也导致了两大弊端:①注重政治公平,而忽视了效率。它虽然通过政治革命铲除了阶级压迫和剥削的不公平现象,可是随之形成了政经一体化的人治管理体制,排斥市场竞争机制,造成平均主义“大锅饭”的低效率。②经济过程充满了人为意志左右的影响。高度集中的计划指令不仅造成宏观运行僵硬和微观无活力,而且由于官僚主义瞎指挥和穷折腾而导致经济大起伏、大涨落。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;腐败的实质是以权谋私,即运用公共权力来谋取私利,而以权谋私的核心则是权钱交易。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;17 世纪的荷兰就因各种冒牌货、劣质品流行于世,被人描绘为“一幅背信弃义、贿赂、残杀和卑鄙行为的绝妙图画”。同样的图画在当时的英国也存在。德国是一个后起的市场经济国家,在 19 世纪流行的著名原则是:先给人们送上一些好的样品,然后再把蹩脚货物发出去。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;有的学者用“劣币驱逐良币”来说明破坏性因子的扩张现象。人们在市场上购物,总是急于把污损、残破的货币脱手出去,而喜欢保存整洁、崭新的货币,这样,流通中往往是劣币多于良币。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;草民意识指缺乏政治参与的义务和权利,只具有群体意识,不具备个体或主体意识。有的学者指出,这种草民是灵魂自我与肉体行为割裂的人,除非依附于某个大人物或社会群体,否则,将无所适从。这种人极易盲从,极易走极端,缺乏自律和自我免疫能力。当依附关系强时,表现得极其顺从和效忠,所谓“国泰天心顺,官清民自安”;一旦失去依附,却又可能忘乎所以,甚至无法无天。从政治学角度讲,就是专制主义和无政府主义乃一母同胞。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;注 | 受过教育的人民&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;如果说草民是人治的产物,那么公民则是个法制的概念,指的是在法律上承担权利和义务的主体。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;人必自辱而后人辱之,物必自腐而后蛆虫生。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;第五章-蝼蚁之穴溃堤千里&quot;&gt;第五章 蝼蚁之穴,溃堤千里&lt;/h2&gt;

&lt;p&gt;总结：讲因素性内耗&lt;/p&gt;

&lt;h3 id=&quot;二行政黑洞和挖沟现象&quot;&gt;二、行政黑洞和“挖沟”现象&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;美国人杜拉克在谈到机构臃肿会降低效率时,举了个例子说,在他上小学一年级的算术入门书中,有这样一个问题:“两个人挖一条水沟要用两天时间,如果四个人合作,要用几天才能完成?”这对于小学生来说,答案是“一天”。但杜拉克认为,在管理上,两个人挖两天完成,四个人挖可能要四天才能完成,甚至有可能“永远也完成不了”。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;唐太宗曾说,“人主唯有一心,而攻之者甚众。或以勇力,或以辩口,或以谄谀,或以奸诈,或以嗜欲,辐凑攻之,各求自售,以取宠禄。人主少懈,而受其一,则危亡随之。”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;table&gt;
    &lt;tbody&gt;
      &lt;tr&gt;
        &lt;td&gt;权力越是集中,君主越是神秘,这个君主就越是容易被人操纵和愚弄。注&lt;/td&gt;
        &lt;td&gt;这句话可是不得了&lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;
  &lt;/table&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;马克思在总结巴黎公社的经验时,曾提出建立“廉价政府”的主张。这一主张包括:①以武装的人民代替常备军。②以普选产生的、随时受监督并可以罢免的、只拿工人薪金的代表制,取代拥有特权的官吏制。③以自下而上的全国民主集中制,取代以官僚独裁为基础的中央集权制。只有这样,才能“给共和国奠定了真正民主制度的基础”,才能防止“国家和国家机关由社会公仆变为社会主人”的现象。② 由于许多原因,后来的社会主义政权并未实现上述主张,但是马克思恩格斯提出的廉价政府则应该是社会主义政权建设的本质特征所在。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;官吏委任制是上面的赏识提拔,使下级误认为权力是上级赐予的,眼睛向上看,可以不对人民负责。而且由于近亲繁殖,上下勾联,官官相护,很容易形成一种带有浓厚封建色彩的宗法关系,裙带关系。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;三橄榄球的发明与行为失范&quot;&gt;三、橄榄球的发明与行为失范&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;“党是我的妈,厂是我的家,没钱向妈要,没物到家拿”。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;四惋惜埃及人的肉锅和汉阴叟抱瓮&quot;&gt;四、“惋惜埃及人的肉锅”和汉阴叟抱瓮&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;怀旧心理的产生,是有深刻的社会根源的,其重要原因之一,就是改革牵动了人们利益关系的大调整。从长远看,改革将促进生&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;生产力巨大发展,会给全国人民带来更大利益。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;我们应主要靠市场经济这只“无形的手”去治“乱”,靠价值规律这所大学校给人们上课,而不是靠行政命令去治“乱”,靠恢复计划经济的旧秩序去治“乱”。否则,回到旧体制,那就无异于饮鸩止渴,因噎废食。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;组成人体蛋白的八种氨基酸(蛋氨酸、赖氨酸、白氨酸、异白氨酸、苯丙氨酸、苏氨酸、色氨酸、缬氨酸)中,只要有一种含量不足,其他七种氨基酸就不能组成蛋白质,只能变为热能,可以说是一种浪费。所以各种氨基酸的营养价值取决于含量最低的那种氨基酸。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;现代科技革命正加剧着这种消极后果,高度自动化的生产技术给人类带来丰富物质生活的同时,又使人日益成为机器的附庸,人的个性和感情也被“机械化”和“自动化”,即由于知识和理性的过度扩张而导致精神贫乏,人们普遍存在着孤独、冷漠、抑郁、自私、享乐的倾向。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;第六章-袖里珍奇光五色他年要补天西北&quot;&gt;第六章 袖里珍奇光五色,他年要补天西北&lt;/h2&gt;

&lt;p&gt;总结：讲结构性内耗&lt;/p&gt;

&lt;h3 id=&quot;三简单同名数相加与影子重合&quot;&gt;三、“简单同名数相加”与“影子重合”&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;在体制上,以皇权为中心的君主专制是以父权为中心的家长制的放大;在伦理上,臣民对君主的“忠”是小农家庭中子对父的“孝”的放大,&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;计划体制却把社会变为“一个大工厂”、“大生产车间”,利用僵硬的无所不包的行政指令直接干预企业经济活动。结果在中国普遍发生了“市长与厂长错位”的怪现象:市长办厂长的事,厂长办市长的事,地位和作用互相倒置,谁也干不好,出现了社会分工的紊乱。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;古人曾讲:“骏马能历险,力田不如牛。坚车能载重,渡河不如舟。舍长以就短,智者不为谋。生才贵适用,慎勿多苛求”。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;我们中国人历来就有歧视和压抑个性的陋习。在家庭,我们喜欢孩子“乖”,让孩子低眉顺眼,善解人意,唯大人马首是瞻。在学校,我们喜欢学生“从”,制定若干条条框框,削足适履,让学生就范。在社会人们喜欢“同”,随大流,求同从众,稍有不同者,即视为异端,大加戕伐。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;四铁笼子里的经济植物人&quot;&gt;四、铁笼子里的“经济植物人”&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;五十年代中期以来实行的户籍制度,造成了壁垒性的地域封闭,使人们尤其是农民失去了自由迁移、自由择业的基本权利,他们的生存空间被凝固化了。几亿农民被束缚在土地上,土里刨食搞饭吃,不得不忍受长期贫穷的生活。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;这种不平等还由于“户口”的世袭性而传之代际被固定化了。“工之子恒为工,农之子恒为农”,可以说出生在哪里将决定一个人一生的命运。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;不合理的竞争开始蔓延发展,各种人情网、裙带风、关系学、马屁术、行贿赂、找靠山等徇私舞弊现象愈演愈烈。这好比一场没有规则的马拉松赛跑,人们不是努力提高自己的竞技水平,而是千方百计地去缩短跑道,结果培养了一批驽马。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;第七章-奥狄浦斯的困惑&quot;&gt;第七章 奥狄浦斯的困惑&lt;/h2&gt;

&lt;p&gt;总结：功能性内耗&lt;/p&gt;

&lt;h3 id=&quot;二弗朗肯斯坦的魔影&quot;&gt;二、“弗朗肯斯坦”的魔影&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;系统具有多种功能,即使对于某一种功能,也往往具有多方面影响。当系统与环境相互作用时,不可能使所有功能和每一功能的所有方面都耦合、协调起来,必然有一些功能是不协调的。如果这些不协调的功能暂时无害,或一时达不到危害主要功能的正常发挥的程度,那就不会危及系统与环境的关系。但是这些功能总是要发挥作用的,它们长期作用终将会带来一系列积累性的不可逆变化的,从而对主要功能造成损害,恶化系统与环境的关系。因此,功能异化将不可避免。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;尽管从名义上讲国家仍是全民资产的所有者,可是国家作为资产的所有者是抽象的,事实上造成国有产权的虚设。但在现实的经济活动中,产权是不能被虚化的,于是国家的各级行政机构和职能部门成为国有资产的实际所有者,导致政企合一与政企不分的现象(即母子连体)。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;产权行政化的结症还在于,它的权、责、利相分离,行使权力和享受利益、承担义务不对称。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;我国每年仅公款吃喝就达1000 亿元,比全年的教育投资还多。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;旧的行政性产权结构体系虽然有很多弊病,但它曾为我国进行了快速的资本原始积累,为我国提供了一个比较完善的工业体系和拥有近 4 万亿元固定资产的 50 万家国营企业&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;马克思在谈到劳动创造的意义时,曾指出劳动有三种功能:作为生存的条件,劳动是人谋生的手段;作为人的基本特征,劳动是个人生命的表现和个人创造性的发挥,也即是一种个人乐趣;作为给他人及社会生产所需要产品的活动,劳动创造又是个人社会本质的自我实现,是为社会做贡献的行为。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;四西西费斯的徒然消耗&quot;&gt;四、西西费斯的徒然消耗&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;物质财富本身并不是最终目的,而只是发展人的能力的手段。如果物质财富不是用来提高人的素质、发展人的能力,那就不是真正的财富,而是“财穷”。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;每一个人都有同等的实现自身发展的机会,任何人的发展都不应以损害另一个人的发展为前提,也就是说,人的发展需要保持社会公正。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;第八章-时间的浪费是最大的浪费&quot;&gt;第八章 时间的浪费是最大的浪费&lt;/h2&gt;

&lt;p&gt;总结：时序性内耗&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;在世间一切事物中,时间是一种最宝贵、最特殊的资源。说它最宝贵,是因为这种资源最稀有,找不到任何替代品,正如古人所说“寸金难买寸光阴”;说它最特殊,是因为时间具有一维性,只会逝去,不会倒流,“时乎时乎不再来”。因此,时间的浪费是最大的浪费,时间造成的损失更是无法挽回的。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;二羽翼迟迟不能丰满的蜻蜓&quot;&gt;二、羽翼迟迟不能丰满的“蜻蜓”&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;并非说必须按部就班地遵循典型资本主义国家所经历的那些传统发展阶段。因为那将意味着永远步人后尘。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;落后国家虽然可以通过革命形式绕过资本主义生产关系去建立社会主义制度,但却不能绕过资本主义所达到的先进生产力水平去建立新的生产方式,生产力发展阶段是不能跨越的。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;四英雄遗恨滑铁卢&quot;&gt;四、英雄遗恨滑铁卢&lt;/h3&gt;

&lt;p&gt;注 | 逆水行舟，不进则退&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;在人类一切活动中,时间的节约是最大的节约,时间的浪费是最大的浪费。浪费时间,对于个人来说就是浪费生命,对于社会来说就是延误了发展进程。一个民族在时间上的落后就面临着被开除“球籍”的境地,一个国家在时间上的差距就意味着被动挨打。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;第九章-论语加算盘的启示&quot;&gt;第九章 《论语》加算盘的启示&lt;/h2&gt;

&lt;p&gt;总结：如何减少内耗&lt;/p&gt;

&lt;h3 id=&quot;一由加法的全体转变为乘法的全体&quot;&gt;一、由加法的全体转变为乘法的全体&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;我们现在向市场体制转变,正是为了使人格独立,个性解放,提高人的素质。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;社会作为整体大系统,包括政治、经济、文化三个子系统&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;造成的总结果,就是政治支配一切。人们在政治垄断下过着照本宣科来办事,听从命令齐步走的兵营式生活,看来整齐划一,但政治的无边法力带来的低效率、瞎指挥却屡次导致社会的失稳和失衡,这就是线性作用的恶果。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;市场的逻辑就是资本无休止地自我增殖,它带着原始的贪婪本性,要把一切产品变为商品。然而,政治权力和道德、良心并不能买卖;技术成果可以进入市场,但基础性科学和许多文化产品也不能进入市场;否则,文化将遵循适销对路原则迎合市场胃口,使高雅文化失去空间,而一些精神毒品则会泛滥。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;我国在改革以前最惨痛的教训之一,就是过多地强调斗争,而忽视了协调。“文化大革命”就是“斗争哲学”的怪胎,与天斗,与地斗,与人斗,斗个没完没了,结果吃尽了苦头。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;二社会协调机制的拟人化规律&quot;&gt;二、社会协调机制的拟人化规律&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;这场巨大内耗不仅造成数千亿元的损失,而且冤狱遍地,社会风气败坏,人际关系扭曲,带来了数不清的后遗症。历史再清楚不过地说明,毫无进步意义的争斗和冲突并非是什么革命和动力,只有重视协调关系,才有利于社会的健康发展。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;以往计划经济的“失效”之处正在于绕过了金融调节这一中间层次,以抽象的具有法律强制力的政府指令来直接取代无数具体的企业契约关系,把法律的抽象性与契约的具体性混为一谈。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;伦理文化强调整体原则,重视合群,提倡为他人、为社会奉献的集体主义精神。它以人伦本位为核心,把社会看成一个大家庭,“天下一家”、“天下为公”是它追求的价值观念。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;科学文化强调功利主义,推崇竞争,形成强者的哲学。如“英雄的道德最公正”,“强权即公理”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;伦理文化具有入世精神,重视对人生、社会、道德的探求,强调“德性就是力量”,忽视对自然科学的探求,所以有求善求美而忽视求真的倾向。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;科学文化则注重用契约原则和法律来规范人际关系。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;科学文化重点解决人与自然的关系,强调天人对立,主客二分,对自然采取了冷漠态度。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;儒家的伦理文化是一种“和文化”,西方的科学文化是一种“争文化”。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;第十章-开发最稀缺的资源&quot;&gt;第十章 开发最稀缺的资源&lt;/h2&gt;

&lt;p&gt;总结：政府在减少内耗上的作用&lt;/p&gt;

&lt;h3 id=&quot;一管理是社会系统的粘合剂&quot;&gt;一、管理是社会系统的粘合剂&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;发展中国家的政府应为国家的繁荣和幸福承担更大的责任,必定要在经济发展中起着越来越大的主导作用。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;我们必须消除一个误解,即认为单靠市场配置资源的作用就能自动地优化产业结构。事实上,产业结构的转换涉及区域迁移、行业调整、技术更新等大动作,并伴随着大批企业倒闭、失业等社会问题,单靠企业自身的力量是难以解决的。如果没有政府的宏观控制和引导,其产生的剧烈动荡将使社会难以承受。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;平等、根除贫困、确保人类自由、维护生态平衡和实现民众参与决策,是社会发展的五个价值关键。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;我国改革开放前,作为最高领导人的毛泽东既是一个思想家,又是一个政治家,当他把他的阶级斗争学说贯彻于经济建设实际时,就造成了“大跃进”、“文革”等一系列的决策失误。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;依靠制度创新来根治腐败是最有效的,在这方面不少发达国家的经验值得借鉴,如实行政府官员家庭财产申报制度、“高薪养廉”制度(使官员享有高工资收入而不再谋取“外快”)、成立专门机构审查官员们在公职以外的金融秘密等&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;随着新闻媒介的普及,新闻监督成为社会监督的主要形式,不少国家已把新闻机构列为立法、行政、司法之外的“第四权力机构”。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;第十一章-把握全球性主题信息&quot;&gt;第十一章 把握全球性主题：信息&lt;/h2&gt;

&lt;p&gt;总结：利用信息反馈来了解社会内耗情况&lt;/p&gt;

&lt;h3 id=&quot;二防止浮夸风反对策和暗箱操作&quot;&gt;二、防止浮夸风、反对策和暗箱操作&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;政治系统的暗箱操作最容易导致为政不廉、权力腐败现象。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;通常的情况是,执行系统过于强大,而立法和反馈系统过于孱弱。这并不是说没有立法,而是指立法很可能成为权力执行者的附庸(又称“橡皮图章”)。极端条件下,就可能出现集立法、执行、反馈等三者于一身的情况。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;连古代圣贤也是懂得的,“狂夫之言,圣人择之”,“刍尧之傲,先民询之”。“街谈巷议,必有可采;击辕之歌,应有风雅;匹夫之思,未可轻弃也。”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;著名心理学家阿尔伯特·明翰伯恩的公式:整个信息传递量= 7% 的语言+ 38% 的语气+ 55% 的面部表情。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;无纸贸易将成现实。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;你可以坐在自己的“电子小屋”里,进行“电子购物”、“电子学习”、打“可视电话”、开“电子会议”、阅读“电子日报”、进行“电子医疗”……&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;近代中国的封建社会正是经历了这样一个过程。封闭锁国,使它落伍于现代工业文明而茫然无知,只是在战乱频仍、分合交替的周期震荡中不断复制自身。封闭锁国,造成了它的文化单一性及其与之相伴随的僵化和凝固,而一旦国门洞开,它就像一具木乃伊在外来新鲜空气的冲击下骤然面临着解体的厄运。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;第十二章-在扩大开放中锻造我国的合金文化&quot;&gt;第十二章 在扩大开放中锻造我国的“合金文化”&lt;/h2&gt;

&lt;p&gt;总结：改革开放是减少内耗的根本途径&lt;/p&gt;

&lt;h3 id=&quot;一中国甲午战争失败的背后&quot;&gt;一、中国“甲午战争”失败的背后&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;深层次开放,即是不只限于物器层或经济的开放,引进产品、资金和科学技术,而且还要深入到制度层、核心层,把发达国家有益的管理体制、思想文化及价值观念都吸收进来。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;批判的武器毕竟不能代替武器的批判。一个严酷的事实是,只要人类社会继续存在和发展,矛盾和斗争就不会完全消失,这种斗争可以是政治角逐、军事对抗,也可以是经济竞争、科技交锋,表现形式尽管不同,但其实质都是实力的抗衡,落后总要挨打。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;从宏观上说,北边的万里长城只是一面放大了的盾牌,东南的万里海岸线也是锁国的链条,加上西部世界屋脊的天然屏障,形成了大一统中国的对外封闭。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;对中西文化的差异,我国近代启蒙大师严复在他的《论世变亡亟》中有过精彩的论述:“中国最重三纲,而西人首明平等;中国亲亲,而西人尚贤;中国以孝治天下,而西人以公治天下;中国尊主,而西人隆民;中国贵一道而同风,而西人喜党居而州处;中国多忌讳,而西人重讥评。其于财用也,中国重节流,而西人重开源;中国追淳朴,而西人求欢虞。其于接物也,中国美谦屈,而西人多发舒;中国尚节文,而西人乐简易。其于为学也,中国夸多识,而西人尊新知。其于灾祸也,中国委天数,而西人恃人为。”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;在开放和引进问题上,邓小平同志表现出一位政治战略家的胆识和胸怀。他在南巡谈话中提出了“不搞争论”的观点,并大胆破除禁区,以是否有利于发展生产力、有利于增强综合国力、有利于提高人民生活水平为标准,来学习和吸收包括西方资本主义文化在内的一切世界文明成果。这不仅坚持了实践第一的马克思主义观点,而且把开放和引进上升到社会主义发展的必然规律的高度。可以说,这是中华民族彻底觉悟的呐喊,它必将以雷霆之势冲破数千年城墙文化所设置的牢固藩篱,为中国走向世界、实现腾飞提供持久的精神动力。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;无论是美国克莱因公式,还是英国汤普逊公式:国家实力=(人力+资源)×意志,都指明了精神因素的重要性。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;除了学习发达国家市场制度中的先进经验外,也需要吸收它们政治制度中的合理因素,例如分权制衡原则、文官制度、弹劾制以及政府宏观管理制度等。应当承认,这些制度成果中包含着人类文明的共同性。只要在坚持社会主义制度大前提下有选择地吸收利用,将有利于促进我国政治体制改革,建立起资本主义所无法比拟的社会主义政治文明&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;第十三章-尾声托起明天的太阳&quot;&gt;第十三章 尾声:托起明天的太阳&lt;/h2&gt;

&lt;p&gt;总结：升华主题&lt;/p&gt;

&lt;p&gt;真敢写啊……&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;延安整风曾使党实现了空前的团结一致。&lt;/p&gt;
&lt;/blockquote&gt;

        </description>
        <pubDate>Sun, 07 Jan 2024 06:42:40 +0000</pubDate>
        <link>/2024/book-theory-of-internal-friction.html</link>
        <guid isPermaLink="true">/2024/book-theory-of-internal-friction.html</guid>
      </item>
    
      <item>
        <title>2023年度总结</title>
        <description>
          
          &lt;p&gt;其实前几年开始流行年终总结这个东西的时候，就很想写的，但因为各种各样的原因未能成笔（其实主要就是懒吧），今年抖擞下精神，简单记录一下~&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2023/review-of-2023.png&quot; alt=&quot;&quot; class=&quot;align-center&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;母亲&quot;&gt;母亲&lt;/h3&gt;

&lt;p&gt;如果说2023年最重要的一件事，大概就是为母亲治病，母亲2022年突如其来的病情打乱了家里往日平静的生活，II期结肠癌是我之前怎么也很难和母亲挂上关系的病症，从发病到手术住了一个月的院，而且当时疫情未结束解封，整整一个月都是生活在医院的病房中，精神和情绪上的压力难以言表，顺利完成手术后又是跨度一整年每20天一次的化疗，由于我在上海工作，给这一切又造成的更大的困难，所幸最终的结果几乎是当初所能够设想中的最好的结果了。&lt;/p&gt;

&lt;p&gt;母亲在整个患病和治疗期间表现的非常的乐观积极坚强平静，并且始终还在为我考虑，尽可能的在减少我的负担。我还要感谢兰君、姥姥姥爷还有杨叔叔在背后付出的所有关心和帮助，感谢公司的领导和同事在得知我家人生病时给予的帮助和理解。&lt;/p&gt;

&lt;p&gt;当然我最应该感谢的是天津市人民医院的大夫、护士们，为我母亲操刀手术的专家团队：张锡朋主任、张明庆主任和井浩人大夫，尤其是井大夫，作为我母亲的住院医师，和我们打的交道最多，他的专业和热情深深地感染着病房里的每一个人，每次看到他工作的状态，都不由让人充满踏实和信任的感觉，病房里的每一家庭都无不认同井大夫将来会是一位非常非常了不起的医生。&lt;/p&gt;

&lt;p&gt;井大夫热爱跑步，时常可以听到他在早上查房的时候和同事分享跑步的经验，这让我想起一件很让我震撼的事情便是住院期间井大夫每天早上都会准时查房，周末假日过年无不例外，风雨无阻，并且每天都能保持饱满的精神和专注的态度，仿佛工作和人生对他来说也是一种长跑一般！可以说井大夫的专注和敬业给我留下了极为深刻的印象，让我真切的看到了有人可以这样的为社会和他人发光发热，他不仅治好了我母亲的病，还成为了我学习的一个榜样。&lt;/p&gt;

&lt;p&gt;我很想更多的感谢张主任和井大夫，无论是精神的还是物质的，但是又不知该如何合理的去表达这份感激之情，住院期间读到的《病人家属，请来一下》中说过到最好的方式是和大夫当朋友一样去相处，但在过去的一年里似乎我们能做的也只能是积极的配合治疗，尽可能地减轻医生的负担，少添不必要的麻烦，但还是希望能在将来有机会真真切切的去回报这份恩情。&lt;/p&gt;

&lt;h3 id=&quot;心动小镇&quot;&gt;心动小镇&lt;/h3&gt;

&lt;p&gt;工作上2023年一整年我都在支持心动小镇项目了，从年初调至项目组时临危受命来处理技术组存在各种冲突，到平稳内存性能问题重构资源系统，再到年底的本地化的功能开发，总的来说还是在往正规上发展，我给自己定的目标始终是要在保证本职工作良好完成的情况下，尽可能多的支持到其他新的工作中去，不仅仅是性能优化，只要是能帮助到项目的，减轻其他同事负担的，我都可以努力去做。&lt;/p&gt;

&lt;p&gt;在小镇这边也认识了很多有趣的新同事，日常的合作也充满了欢乐，可以说2023年是我来心动以后工作最充实快乐的一年了（可能我还是更适合在项目中做事哈）&lt;/p&gt;

&lt;p&gt;明年小镇要正式上线了，也许是人生中又一次大考，尽人事，听天命~！&lt;/p&gt;

&lt;p&gt;不过想想小镇项目目前只有30多号人，但是一定程度上又要和蛋仔派对、元梦之星这种级别的产品同场竞技，拼功能是一定会吃大亏的，感觉还是得先在自己优势的点上发力，先吸引到一定的用户后，有了更多的资源再去尝试扩大影响。&lt;/p&gt;

&lt;p&gt;此外，《铃兰之剑》在23年也顺利上线了！我支持的工作虽然不算很多，但也是今年值得记录的一件成绩！&lt;/p&gt;

&lt;h3 id=&quot;家庭&quot;&gt;家庭&lt;/h3&gt;

&lt;p&gt;笑笑又大了一岁，明显能感觉到他自己的意识更独立了，我已经开始调整自己的教育方式了，从命令与要求努力转变为沟通与建议，还试着通过“睡前阅读”来和孩子一起分享一些教育方面的书，都是第一次做父母，也只能是摸着石头过河。&lt;/p&gt;

&lt;p&gt;孩子对零用钱的需求长期被压抑着，这是现代孩子面临的转变之一，我和兰君都是很小时候开始就有每天几毛钱的零花钱了，而且可以在学校的小卖部或者上下学的路上开始体验“金融法则”，但现在无现金消费让小朋友的金钱观发生了翻天覆地的改变，笑笑这种年纪的孩子现在一切花销全部仰仗于“乞求”父母，丝毫没有自由度可言。上个月我给他设计了一个“数字钱包”的游戏规则，希望能改变这一情况，逐渐培养他正确的金钱消费观念。&lt;/p&gt;

&lt;p&gt;疫情结束放开后，我们还没太远的旅行和出门机会，今年短途去了上海周边的平湖、杭州和滴水湖，但是工作和生活这么忙碌，不知道2024年有没有机会带孩子去更远的地方游玩游玩。&lt;/p&gt;

&lt;p&gt;家门口的山姆开业对兰君的生活上多了一份有趣的消遣，步行几步就能到确实省去了很多交通和购物的成本，虽然我还不能非常准确的Get乐趣所在，但能从她脸上洋溢的笑容能感受到那份快乐，去逛一逛，试吃各种新品，周末再去带回一把花。&lt;/p&gt;

&lt;h3 id=&quot;自己&quot;&gt;自己&lt;/h3&gt;

&lt;p&gt;这一年自己的生活上感觉更加“老年人”了（笑），睡眠从保持了接近15年的12：00睡，调整为了10：30睡，游戏和电影的用时越来越少，看书的时间越来越多，今年仅微信读书上就读完了超过100本……不过基本都是闲书，24年精力允许的情况下要努力看更多的专业书，这一点上这几年虽然读书总量越来越高，但专业书的占比却越来越低-_-。&lt;/p&gt;

&lt;p&gt;说到看书的话，我现在最新的爱好便是把玩各种电子阅读器了，光今年就买了两款（明年要再买就得出出旧的了&amp;gt;_&amp;lt;），虽然我很喜欢逛实体书店，但现在让我捧一本实体书读完可太苦了，我是真心觉得电子阅读器更方便，便携不说，你可以设置自己更喜爱的字体与排版，还可以更方便的标注与搜索，我承认拿着实体书读书更有感觉一些，但一旦用惯了电子阅读器，那些方便的功能确实很难再离开，今年年中试过几本去读实体书，都最后都中途换回了电子版。&lt;/p&gt;

&lt;p&gt;今年持续改进完善自己的笔记系统，受《Build your second brain》这本书启发很大，下半年又融入了日记，每天不管怎样记录几笔，确实会帮助我更不容易去“糊弄”过这一天。总觉得有一些生活学习上的习惯，我学会的太晚了，这也许就是普通人吧（笑），只能用亡羊补牢，未为晚也来安慰自己了。&lt;/p&gt;

&lt;p&gt;不过身体上今年开始感觉到精力大不如前了，第一次明显感觉到那种下了班到家只想睡觉的状态，体检也是浑身上下各种结节和小毛病，不服老不行的，有时想想确实是像歌词里一样，心里觉得自己还是那个吃着冰棒玩着FC的小孩子，但现实里已经是上有老下有小的中年人了。&lt;/p&gt;

&lt;p&gt;现在时间上也感觉越过越快，一天天唰唰的没啊，过去的不能再改变，对于未来的日子，也不再想做那些激动人心的鼓励，就是踏踏实实的生活，诚诚恳恳的工作，尽力享受生活中的每一份美好，积极的面对每一次挑战。&lt;/p&gt;

        </description>
        <pubDate>Sun, 31 Dec 2023 13:50:08 +0000</pubDate>
        <link>/2023/review-of-2023.html</link>
        <guid isPermaLink="true">/2023/review-of-2023.html</guid>
      </item>
    
      <item>
        <title>[书评] 贫穷的本质</title>
        <description>
          
          &lt;p&gt;作者是一位印度裔的麻省理工经济学教授，后来发现还是2019年诺贝尔经济学奖得主，这本书几年前曾经看了前面几章，在豆瓣上似乎很多人诟病翻译的质量，当时感觉确实读起来略显枯燥，最近重新捡起来努努力读完了，不过其实大部分是利用闲散时间听完的，算不上是精读。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2023/book-Poor-Economics.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;这本书讨论的并非个人层面上的贫穷原因的分析，而是国家、社会大层面上的贫穷问题，重点分章节讨论了下列几个因素对贫穷问题的影响：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;食物与饥饿：作者认为饥饿并非造成贫困的主因，现代农业已经可以确保我们生产出足够全球人口的粮食&lt;/li&gt;
  &lt;li&gt;流行病与健康问题：穷人总是在健康上花费更多，因为他们将钱更多的花费在治疗而非预防，而这样做的原因根源在于信息的匮乏&lt;/li&gt;
  &lt;li&gt;教育的投入：教育其实是一种长期投资，而对于极端贫穷的人来说，其周期可能过长而往往无法承受&lt;/li&gt;
  &lt;li&gt;子女生育：在质与量的取舍间，穷人往往会选择多生（类似买彩票，买便宜的彩票，多买几张），而多生则又会进一步降低每个子女的平均教育投入&lt;/li&gt;
  &lt;li&gt;保险与社会职责：穷人的抗风险能力非常差，而社会则不倾向于为该群体提供足够的保障&lt;/li&gt;
  &lt;li&gt;针对穷人的贷款机制：由于穷人有着更高的违约率，正规的借贷机构会逐渐无法维持一个合理的利率来贷款给穷人，也因此才会出现穷人更多使用高利贷的现象&lt;/li&gt;
  &lt;li&gt;穷人的心理：过度贫穷往往使得人们无法满足一些在我们看来最基本的快乐的追求，这也使得穷人的心理和意志更薄弱，对比一段时间长期的投入来获取更丰厚的回报，穷人更倾向于即时的快乐&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;针对每一个议题，作者都通过一系列的社会数据和在印度和非洲部分国家的抽样实验来分析造成社会贫穷问题的潜在原因，同时还列举了一些其他著名经济学家针对贫穷问题的不同的观点，书中的表述更多的是各种观点的讨论，而非结论的断言，因此对于贫穷的解决的办法也只进行了有限度讨论。&lt;/p&gt;

&lt;p&gt;作者的很多分析与讨论都是基于印度国内的贫穷问题，有趣的是作者在书中还举例了许多中国解决贫穷问题的例子，似乎我国已经俨然成为了正面的榜样。&lt;/p&gt;

&lt;h1 id=&quot;笔记&quot;&gt;笔记&lt;/h1&gt;

&lt;p&gt;《贫穷的本质：我们为什么摆脱不了贫穷（修订版）》
阿比吉特·班纳吉 埃斯特·迪弗洛
70个笔记&lt;/p&gt;

&lt;h2 id=&quot;前言&quot;&gt;前言&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;自打贫穷一出现，我们就产生了某种以约定俗成的方式来贬低穷人的冲动。穷人频繁地出现在社会理论及文学作品中，他们被描述得有时懒惰，有时上进；有时高尚，有时鬼祟；有时愤怒，有时顺从；有时无助，有时自强。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;要想知道穷人是怎样生活的，你就要想象如何在迈阿密或莫德斯托每天只靠99美分生活。要用这点钱购买你一天所需（除了住房），这并不容易。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;第一章-再好好想想&quot;&gt;第一章 再好好想想&lt;/h2&gt;

&lt;p&gt;2023/12/23发表想法
人们对于个人的救助意愿要远大于对群体的救助！&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;大多数人在面对贫穷等问题时的感觉。我们的本能反应是慷慨，特别是在面对一个身陷困境的7岁小女孩时。然而，正如宾夕法尼亚大学的学生们一样，我们在重新考虑之后常常失去信心：我们捐的那点儿钱不过是沧海一粟，而且这些善款的安全性也得不到保障&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;这些国家往往都气候炎热、土地贫瘠、疟疾肆虐、四周被陆地所包围。因此，如果没有大量的原始投资助其解决这些地方性问题，这些国家很难提高自己的生产力。然而，这些国家却因为贫穷，无法支付投资回报——这就是经济学家们所谓的“贫穷陷阱”。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;他们都认为，援助的弊大于利：援助使人们停止寻找自己解决问题的方法，腐蚀地方机构并削弱其作用，导致一些援助机构形同虚设。对于贫穷国家来说，最好遵循一个简单的原则：只要有自由市场和恰当的奖励机制，人们就能自己找到解决问题的方法，避免接受外国人或自己政府的施舍&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;哲学家彼得·辛格曾写过关于拯救陌生人的道德准则，他评论说，大多数人都愿意牺牲一件价值1 000美元的衣服，换取一个落水儿童的性命。辛格还认为，这名落水儿童就是那些每年活不到5岁的900万儿童之一。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;他们认为，如果人们不花钱就得到了蚊帐，那么他们就不会对其加以珍惜，因而也就不会去用。即使他们用了，也可能会因此对施舍习以为常，在以后需要自己花钱购买蚊帐时便会退缩，或是在需要其他物品时也不愿自己花钱，而是等着别人免费赠送。这种情况会摧毁运转良好的市场。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;2023/12/23发表想法
和公租房廉租房的情况很想像啊&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;不过，情况也可能恰恰相反：免费得到蚊帐的人社会关系优越，而穷人由于封闭只好以全价购买。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;你今天的收入会影响将来的收入，这个将来可能是明天、下个月，也可能是下一代；你今天有多少钱决定着你能吃多少，有多少钱用来买药、支付你孩子的教育费、为自家田地买来化肥或更好的种子，所有这些都决定着你明天会有多少钱。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;对于处于“贫穷陷阱”地带的穷人来说，将来的收入低于今天的收入：曲线低于对角线&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;第二章-饥饿人口已达到10亿&quot;&gt;第二章 饥饿人口已达到10亿？&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;如果完全去除烟酒及节日性花费，一般的贫困家庭花在食物上的钱比实际多30%。穷人似乎有更多的选择，他们并不推崇将所有的钱都用来买吃的。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;当穷人可以多买一点儿食物时，他们并不注重用所有投入换取更多能量。相反，他们会选择买一些口味更好的、价钱更高的食品。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“贫穷陷阱”可能不存在的一个原因就是，大多数人都能吃饱饭。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;研究表明，在18世纪到19世纪期间，土豆的出现使世界人口增长了12%。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;饥饿的确存在于当今世界，但只是人类食物分配方式的一种结果。绝对的食物匮乏并不存在&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;在16世纪中期至19世纪时期，曾盛行“杀死女巫”活动。当时农作物歉收的现象十分普遍，渔业也不发达。女巫们大都是单身女性，其中以寡妇居多。S形曲线的逻辑表明，当资源紧缺时，通过牺牲某些人，让余下的人能吃饱，使其具备劳动能力，为生存而赚钱，这从经济角度来看是合理的。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;尽管对于个人成长来说，基因构成的确至关重要，但人类在身高方面的基因差别是极其微小的。如果第一代母亲的孩子身材依然十分矮小，那么部分原因可能在于，这一代母亲在童年时就营养不良，因此才会生下身材较为矮小的孩子。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;然而，事实上，有大量证据支持这一观点，即童年时期的营养不良会直接影响成人的处世能力。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;因此，穷人在选择食品时，主要考虑的并不是价格是否便宜，也不是有无营养价值，而是食品的口味怎么样。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;2023/12/06发表想法
其实一定程度的眼前的幸福和快乐，也是人的基本需求之一&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;人类对于美好生活的基本需求，或许可以解释为什么印度的食品消费一直都在下降。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;穷人会更加怀疑那些想象中的机遇，怀疑其生活产生任何根本改变的可能性。他们的行为常常反映出这样一种想法，即任何值得做出的改变都要花很长时间。这也可以解释，为什么他们只关注当前，尽可能把日子过得愉快，在必要的场合参加庆祝活动。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;2023/12/06发表想法
很难看到改变的希望，不如抓住当下的幸福&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;穷人会更加怀疑那些想象中的机遇，怀疑其生活产生任何根本改变的可能性。他们的行为常常反映出这样一种想法，即任何值得做出的改变都要花很长时间。这也可以解释，为什么他们只关注当前，尽可能把日子过得愉快，在必要的场合参加庆祝活动。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;在印度看到的那样，穷人即使在自己收入增加的情况下，也不会吃得更多更好；除了食物之外，他们需要面对太多其他的压力和欲望。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;第三章-提高全球居民健康水平容易吗&quot;&gt;第三章 提高全球居民健康水平容易吗？&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;因此，问题并不在于穷人为健康花了多少钱，而是他们的钱究竟花到哪儿去了。他们常常把钱花在昂贵的治疗上，而不是廉价的预防上。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;实际上，存在着一种“心理沉没成本”——人们更有可能会利用他们为之支付很多钱的东西。此外，人们可能会根据价格来判断质量：恰恰是由于某物品是廉价的，人们便有可能认为它没有价值。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;2023/12/23发表想法
穷人可怕的是不仅仅在经济上贫瘠，在知识和信息上更贫瘠&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;西方国家的人们可以随时洞悉世界顶尖科学家们的观点，即使他们很难依此做出选择；对于几乎没什么信息来源的穷人来说，他们的选择该有多难呢？人们会根据自己的理解做出选择，但如果大多数人连基本的高中生理知识都不具备，就像我们看到的那样，他们就没理由去相信医生的能力与专长，因而他们的决定在很大程度上就是无的放矢。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;穷人之所以会坚持那些看起来漏洞百出的信念，还有一个潜在的原因：在他们无能为力的情况下，希望变得至关重要。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;不要贿赂别人去做你认为他们应该做的事。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;穷人所陷入的困境与我们其他人的困扰似乎是一样的——缺乏信息、信念不坚定、拖延。的确，我们并不贫穷，受过良好的教育，见多识广，但我们与穷人的差别其实很小，因为我们的认识比我们想象中的要少得多。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;第四章-全班最优&quot;&gt;第四章 全班最优&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;教育不过是另一种形式的投资：人们投资于教育，就像投资于任何其他领域一样，目的是挣到更多的钱，增加未来的收入。将教育看成一种投资所带来的一个明显问题就是，做出投资的是家长，而未来获得收益的是他们的孩子&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;借钱供自己10岁的孩子上学，并指望他在20岁时能挣到钱，这简直就是一个白日梦。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;2023/12/23发表想法
教育对于一个国家意味着未来&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;为什么公立学校的教师表现得这么差。不过，教育所特有的一个关键问题就是，对于教育成果的具体期望会歪曲家长们的需求。这种期望包括公立及私立学校的价值、孩子们的成就，以及随之而来的巨大浪费。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;这条S形曲线表明，除非家长们愿意平等地对待每一个孩子，否则他们只能孤注一掷，将所有希望都寄托在他们认为最有前途的那个孩子身上，确保这个孩子接受足够的教育，而不是将教育投资分摊给所有的孩子。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;很多教师非常不愿意到偏远或“落后”的村庄去，一个现实原因就是交通不便，或是偏远村庄的生活设施太差&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;第五章-帕克苏达诺的大家庭&quot;&gt;第五章 帕克·苏达诺的大家庭&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;当今生育率较高的国家更穷这个事实并不完全因为生育率高。真正的原因可能是，生育率高恰恰是由贫穷引起的，或是有第三个原因导致了高生育率及贫穷。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;贝克称，每个家庭都面临着一种所谓的“质与量的取舍”，也就是说，一旦有了更多的孩子，每个孩子的“质”就会降低，因为父母为每个孩子投入的食物及教育资源就会更少。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;穷人或许无力控制自己的生育，一个原因就是，他们可能接触不到一些现代的避孕措施。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;当我们思考生育这一选择时，立即会产生一个问题，即生育是谁的选择？生育决定是由一对夫妇做出的，但女性最终将付出生孩子的大部分身体代价。毫无疑问，她们对于生育的选择与男人迥然不同。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;一种可能的解释就是，在女人有财产权的情况下，她就会在家中获得更多的话语权，因而在决定家庭成员数量上拥有更大的权威性。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;对于很多父母来说，孩子就是他们的经济未来：一种保障政策、一款存储产品，也是某种福利彩票，这些东西被统统装进了一个大方便袋。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;真正负责养家糊口的是女人，丈夫会给她一定量的家用，她的任务就是想出怎样充分利用这些钱。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;第六章-赤脚的对冲基金经理&quot;&gt;第六章 赤脚的对冲基金经理&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;穷人就像对冲基金经理一样——他们的生活充满了风险，而唯一的不同点就在于二者的收入水平。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;在很大程度上，对于穷人来说，事情似乎并不比往年更遭，因为他们的境况一直都很糟。他们正在面对一些非常熟悉的问题。在穷人看来，每一年都过得像身处一场巨大的金融危机一样。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;失去希望，感到没有出路，这会大大降低人们渡过难关所需的自控力。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;穷人怎样应付这些风险呢？在面临工资或收入下降时，穷人的一个自然反应就是，增加工作量。然而，这有时是一种自欺欺人的做法。如果在时局不好时（例如一场旱灾或成本价格上涨），所有的穷人都想增加自己的工作量，他们会相互竞争，导致工资水平进一步下降。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;穷人降低风险的另一种方式是，保守地经营他们的农场或生意。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;帮助别人支付医疗费用这类情况已经超出了互助行为的界限：鉴于医疗费用极为昂贵，很多家庭将不得不因此倾家荡产。因此，将健康问题列在助人为乐的基本道德责任之外，还是说得通的。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;可信度始终是保险产品所面临的一个重要问题，因为保险合同要求一个家庭预付一些钱，而他们将来能否得到补偿则是由保险公司决定的，所以这个家庭一定要完全信任该保险公司。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;第七章-贷款给穷人不那么简单的经济学&quot;&gt;第七章 贷款给穷人：不那么简单的经济学&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;为什么有些人需要支付高利率？一个标准的解释就是，他们违约的概率更高。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;穷人因此会向那些一旦违约就会真正伤害他们的人借款，因为这些贷方无须花那么多时间去监督（借款人不敢犯错），因而贷款会更便宜一些。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;第八章-节省一砖一瓦&quot;&gt;第八章 节省一砖一瓦&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;如果穷人仍然一砖一瓦地节省，那么原因一定是，他们没有省钱的更好方式。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;拥有财富可以激励人们投入时间，变得更有耐心。其言外之意就是，贫穷会永久性地腐蚀人的耐心。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;他向我们解释说，他总是提前购买化肥，因为他知道，钱放在家里根本存不住。他说，只要钱一放在家里，就总会有事情发生，钱就会被花掉。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;人脑会以不同的方式对现在和未来进行处理。本质上，我们似乎可以预见自己将来的行动，但这常常与我们今天的行为方式不一致。这种“时间矛盾”的一种表现形式就是，我们在花钱的同时，也在计划着将来省钱。换句话说，我们希望，“明天的自己”比“今天的自己”更有耐心。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;“时间矛盾”的另一个表现形式就是，买下我们今天想要的东西（酒、糖或脂肪类食品，小饰品等），但计划着明天将钱花在一些更合理的地方（学费、蚊帐、修缮屋顶等）。换句话说，我们想象着会在将来购买的东西，并不总是我们今天已经买下的东西。从这一意义上讲，酒对于很多人来说具有很大的诱惑力，它会使我们立即产生反应，却不会给我们带来任何预想的快感。相反，电视机或许不是一种有诱惑力的产品，但很多穷人都会为了买一台电视机，计划并存上几个月或几年的钱。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;诱惑是生理需求（性、糖、脂肪类食品、烟等）的表现。在这种情况下，富人更容易满足“受到诱惑的自己”。在决定是否存钱时，他们认为，任何为将来而存的钱都会用于实现长期目标。因此，如果糖和茶是一种诱惑物的原型，那么富人不太可能会有所困扰——他们并不是不会受到诱惑，而是无须担心多喝一杯茶就会花掉自己辛苦赚来的钱。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;对于穷人来说，存钱的吸引力更小，因为在他们看来，目标太遥远了，而且他们知道一路上会遇到很多诱惑。不过，如果不存钱，他们会一直穷下去。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;而我们认为，在很大程度上，情况恰恰相反：当你想要的一切看上去都很遥远时，你很难感受到动力。将目标设置得更近一些，或许是穷人实现这些目标的有效方式。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;第九章-不情愿的企业家们&quot;&gt;第九章 不情愿的企业家们&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;这就是真正的企业家精神：如果你所拥有的不多，那么就用你的聪明才智，做到从无到有。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;如果这一收益不足以抵消你在这上面花的时间及成本，而且你认为情况不会很快得到改善，那么你就应停工。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;这就是穷人和他们所做生意的矛盾之处：他们精力充沛，拥有丰富的资源，而且努力地做着白手起家的生意。但他们的大部分精力都花在了很小的生意上，而且他们同周围很多其他人都在做着相同的生意。结果，他们失去了过上一种富裕生活的机会。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;对于政府工作的特别强调表明穷人对于稳定的一种向往，因为这类工作虽然不那么激动人心，但一般都非常稳定。而且，实际上，工作稳定似乎是中产阶层与穷人之间的一个界限。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;第十章-政策政治&quot;&gt;第十章 政策，政治&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;而另一方面，杰弗里·萨克斯则认为腐败是一种“贫穷陷阱”，这并不奇怪。贫穷会引起腐败现象，而腐败现象的发生必然会促使贫穷的产生。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;腐败的制度往往会滋生更加腐败的制度，形成恶性循环，这就是所谓的“寡头政治铁律”。当政的领导者倾向于制定能够为他们谋取财富的经济政策，而他们一旦变富，又可以利用手中的财富，提前阻止可能对他们的权力构成威胁的人。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;这就是我们所谓的三大问题：意识形态、无知和惯性。这个问题瓦解着可以帮助穷人的各种努力。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;这两个例子表明，大规模的浪费及政策失败之所以会发生，常常是因为政策规划阶段的懒惰思想，而不是任何深层次的结构问题。对于有效的政策来说，有效的政治或许是必要的，或许不是。当然，这还不够。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;总结&quot;&gt;总结&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;第一，穷人通常缺少信息来源，相信那些错误的事情。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;第二，穷人肩负着生活中的多种责任。你越富有，越容易做“正确”的决定。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;第三，一些服务于穷人的市场正在消失，或是在这些市场中，穷人处于不利地位。穷人存款所得的利息（如果有幸拥有一个账户的话）是负利息，但贷款的利息却很高。针对穷人的医疗保险市场尚未健全，尽管医疗问题给他们的生活带来了很大影响。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;第五，对于人们能做什么或不能做什么，最终常变为自我实现的预言。&lt;/p&gt;
&lt;/blockquote&gt;


        </description>
        <pubDate>Sun, 24 Dec 2023 03:31:38 +0000</pubDate>
        <link>/2023/book-Poor-Economics.html</link>
        <guid isPermaLink="true">/2023/book-Poor-Economics.html</guid>
      </item>
    
      <item>
        <title>滴水湖天文馆游记</title>
        <description>
          
          &lt;p&gt;上海天文馆种草很久了，尤其是有了车以后，考虑到浦东滴水湖的距离，确实可以来一场“说走就走”的旅行，但是很不幸的是突如其来的疫情直接让这个“说走就走”推迟了足足三年……&lt;/p&gt;

&lt;p&gt;前几天突然又想起了这个事情，而且抱着试试看的态度“抢”到了上海天文馆的票（疫情前刚开那会儿确实很难抢），于是这个“说走就走”终于要成行了……&lt;/p&gt;

&lt;p&gt;说起来没太研究攻略，后来发现上海天文馆的抢票规则变过几次，现在的套路是9：30抢门票，如果抢到的话，10：00还要抢球幕电影票，球幕电影目前有三部，一天五场，但是抢票还挺复杂，下单前有一个强制冷却倒计时，同一场同一个座位一旦有另一个人也选择了的话，抢票失败后再去换别的场次或座位就会很被动，所幸最后还是抢到了当天最后一场的球幕电影，￥40一张票。&lt;/p&gt;

&lt;p&gt;生活在上海的话，去滴水湖玩本可以来个早上去晚上归，不过我和兰君都是慢性子懒散型的，所以都宁愿在那边住一晚也不愿意行程太赶，最终她订了就位于滴水湖的洲际酒店。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2023/20231210_0947_hotel.jpg&quot; alt=&quot;&quot; class=&quot;align-center&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;出发&quot;&gt;出发&lt;/h1&gt;

&lt;p&gt;周六早上拖到差不多11点出发，路上总的来说比较顺利，天气晴朗，只是发现去临港的交通还不如去苏州或者杭州的路好开，沪芦高速只有双车道（这个方向走的少，也可能别的路线好开些？），到了临港去酒店前先在附近的港城新天地解决了午餐，简单吃了个麦当劳，等餐的时候大概看了下这个商圈，人气还可以的，只是地方不大，而且旁边的小区似乎看上去很新，干干净净的，不知道入住率怎么样。&lt;/p&gt;

&lt;p&gt;吃饱奔向酒店办入住，这个季节明显已经不是旅游旺季了，但没想到这天酒店还挺热闹，正好赶上了中街冰点（就是中街1984那个雪糕品牌）的年会，酒店设计的蛮有意思的，从天空看是个花瓣造型。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2023/20231209_142845_阳台外景.jpg&quot; alt=&quot;&quot; class=&quot;align-center&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2023/20231209_143541_屋内.jpg&quot; alt=&quot;&quot; class=&quot;align-center&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2023/20231209_143555_minibar.jpg&quot; alt=&quot;&quot; class=&quot;align-center&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2023/20231209_143607_阳台.jpg&quot; alt=&quot;&quot; class=&quot;align-center&quot; /&gt;&lt;/p&gt;

&lt;p&gt;虽然已经是12月份了，但这个周末天气很不错，可能是今年冷之前最后一个接近20℃的周末了，于是决定不要浪费白天的时间，出去转转。&lt;/p&gt;

&lt;h1 id=&quot;滴水湖&quot;&gt;滴水湖&lt;/h1&gt;

&lt;p&gt;考虑到滴水湖一圈也有好几公里，我们决定还是先开车转一圈了解下情况，结果发现滴水湖本体似乎还没有建设的特别完善，只是完成了道路的基建，湖边还几乎没有商业，比较原生态，而且比较要命的是也没有任何便利的停车点，估计当初设计的时候，主要是希望游客通过自行车来作为绕湖游玩的交通工具。&lt;/p&gt;

&lt;p&gt;一直开到湖北边，发现很多车都直接停在路边，估计在目前游人还不多的情况下，这就算是“停车场”了吧，停好车，我们也到湖边转一转，吹吹风，感受下时光的惬意。&lt;/p&gt;

&lt;p&gt;然后，我们非常失败的选择了哈罗的“共享四轮车”，起租￥40一小时，解锁之后骑上就开始后悔，非常难骑，自重非常大，骑起来费力不说，速度还没走得快……&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2023/20231209_161920_哈罗双车.jpg&quot; alt=&quot;&quot; class=&quot;align-center&quot; /&gt;
&lt;em&gt;就是这货千万别碰&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;在滴水湖北面这边就会发现这面湖边（接近120°的弧度）几乎全部都在热火朝天的建设中，场面颇有几分宏大。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2023/20231209_155051_建设中.jpg&quot; alt=&quot;&quot; class=&quot;align-center&quot; /&gt;&lt;/p&gt;

&lt;p&gt;还抓拍到快下山的夕阳穿过云层打在湖面上，波光粼粼，煞是好看。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2023/20231209_163607_夕阳斜照.jpg&quot; alt=&quot;&quot; class=&quot;align-center&quot; /&gt;
&lt;em&gt;为了抓拍这张跳下车狂奔200米&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;吹了会儿湖风，上车继续绕湖开，南边又发现了一块地方的路边停了很多车，看上去湖边有很多儿童活动的设施（后来听法兰克说应该是个溜娃的公园），之后兜兜转转，顺着导航又到了南汇嘴观海公园，不过这时候天基本已经黑了，而且海水落潮，并没太多值得看的。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2023/20231209_170821_南汇观海.jpg&quot; alt=&quot;&quot; class=&quot;align-center&quot; /&gt;&lt;/p&gt;

&lt;p&gt;晚饭搜了搜附近，没做攻略也没发现特别的惊喜，就又回到港城新天地这边，尝了下中午就看上的陕西面馆“手擀兄弟”，面条质量还不错，物美价廉（是的，我还是只有吃面这点出息XD）&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2023/20231209_174913_decoration.jpg&quot; alt=&quot;&quot; class=&quot;align-center&quot; /&gt;
&lt;em&gt;夸父炸串的店内装修是80s复古风格&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;晚上回到酒店，和兰君围着酒店转了一圈，抬头看去依然看不到很多星星，看起来即使在滴水湖这边光污染也很严重，湖面静悄悄，映射着远处的霓虹灯光，如同海市蜃楼一般迷幻。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2023/20231209_203305_海市蜃楼.jpg&quot; alt=&quot;&quot; class=&quot;align-center&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;天文馆&quot;&gt;天文馆&lt;/h1&gt;

&lt;p&gt;早上起床，去酒店大堂吃个自助早餐，考虑到今天要在天文馆待一天中午可能吃不好，所以吃饱了以后硬着头皮又喝了碗馄饨，吃了几个煎饺。&lt;/p&gt;

&lt;p&gt;今天和以往不同，我们早上出发就得先把酒店的房退了，办理的时候机智的问了一下大堂小姐姐去天文馆的交通建议，果断选择了把车停在酒店，然后打车去的方案。&lt;/p&gt;

&lt;p&gt;我们差不多提前半个多小时到达天文馆，还没开馆但是已经有不少人在排队了，等待的时候手机上搜了搜馆内游玩攻略，才发现早排队是有意义的，因为馆内有些项目每天限定人数，而且必须要求检票进场后才能在手机上预约当日的项目，数了数前面排着的人，感觉我们应该很有希望，这样看我们今天来的时间几乎刚刚好。&lt;/p&gt;

&lt;p&gt;但是时间上不允许我再临时学习下可以预约的项目都是什么了，检票进场后，随机预约了个“穿越银河系”，约好了以后倒是有点后悔，发现还有个时长40分钟的“火星探险”项目（不过后来发现笑笑实际上是不满足该项目身高1米5的要求的）&lt;/p&gt;

&lt;p&gt;场内的活动按顺序是从一楼的“家园”展厅开始，之后转到“宇宙”展厅，我们逛的比较慢，差不多上午逛完了这两部分，声光效果制作的都挺精美的，真的很适合带孩子来看。11点半我们按照预约的时间去看了“穿越银河系”，这个其实就是儿童版的“飞跃地平线”（迪斯尼项目），出来重新回到二楼继续参观“征程”部分，说实话也才玩了一上午，但这时候已经感觉腿要断了……&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2023/20231210_110841_旋转楼梯.jpg&quot; alt=&quot;&quot; class=&quot;align-center&quot; /&gt;
&lt;em&gt;大厅这个旋转楼梯孩子们很喜欢&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2023/20231210_095746_气态星.jpg&quot; alt=&quot;&quot; class=&quot;align-center&quot; /&gt;
&lt;em&gt;上面的气流团会随着自转而滚动起来，非常逼真&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2023/20231210_102722_宇宙展厅.jpg&quot; alt=&quot;&quot; class=&quot;align-center&quot; /&gt;&lt;/p&gt;

&lt;p&gt;逛完“征程”，我们去逛了礼品店，之后又去看了一楼的附加展馆“中华问天”，下午体力确实开始跟不上了，走几步就想坐下来休息一会……&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2023/20231210_140630_地球冰淇凌.jpg&quot; alt=&quot;&quot; class=&quot;align-center&quot; /&gt;
&lt;em&gt;二楼小卖部的地球冰淇凌不错，来玩的话不要错过！&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;大厅中央有个非常大的傅科摆，每当快要击倒一个新的标杆时往往会聚集很多人围观，也蛮有意思的。之前在一本科普书上看到过讲解傅科摆和科里奥利力的故事，刚好对着老婆孩子一通显摆&amp;gt;_&amp;lt;：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2023/20231210_151943_傅科摆.jpg&quot; alt=&quot;&quot; class=&quot;align-center&quot; /&gt;&lt;/p&gt;

&lt;p&gt;最后是预约到的最后一场的球幕电影，效果还是挺赞的，但是开场还没5分钟，就发现妈妈已经安详的睡着了……（太累了结果错过了整场电影哈哈），影片最后快结束时讲到宇宙大爆炸时一声巨响，我和笑笑下意识齐齐扭头看妈妈惊醒的样子可太搞笑了。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2023/20231210_152439_球幕影院.jpg&quot; alt=&quot;&quot; class=&quot;align-center&quot; /&gt;
&lt;em&gt;上面这个球其实就是球幕影院&lt;/em&gt;&lt;/p&gt;

&lt;h1 id=&quot;回程&quot;&gt;回程&lt;/h1&gt;

&lt;p&gt;回去的路上稍微有些不好开，导航还是推荐我们走沪芦高速，大车很多，还下着雨又是黑天……&lt;/p&gt;

&lt;p&gt;到家后在家门口的时时炭火烧去吃了日式烧串，有阵子没吃了，寿喜锅、京葱鸡肉串、牛肋条，还是那么美味呢！&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2023/20231210_191156_时时碳火烧.jpg&quot; alt=&quot;&quot; class=&quot;align-center&quot; /&gt;&lt;/p&gt;

        </description>
        <pubDate>Sun, 10 Dec 2023 01:41:42 +0000</pubDate>
        <link>/2023/dishuilake-planetarium-trip.html</link>
        <guid isPermaLink="true">/2023/dishuilake-planetarium-trip.html</guid>
      </item>
    
      <item>
        <title>[书评] 自卑与超越</title>
        <description>
          
          &lt;p&gt;这应该是可以算是西方心理学经典之一吧，作者是阿尔弗雷德•阿德勒，十九世纪著名心理学家和心理医生。这本书的英文原名是《What life should mean to you》，但中文的译名整出了个《自卑与超越》，我个人觉得还不如像《生命对你意味着什么》的直译来的更恰当。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2023/book-what-life-should-mean-to-you.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;最早发现这本书是在公司项目组的公共书架上，刚好微信读书上也有电子版的，于是就结合着读了一读。这本书一开始读着略显枯燥，但很快就发现这本书金句非常非常多，以至于我最终摘抄出了1万4千多字的笔记……&lt;/p&gt;

&lt;p&gt;这本书的核心观点非常正能量，&lt;strong&gt;主张奉献、关心他人并与他人合作是我们应赋予个人生活意义的真正正确方式，强调人类是社会性动物，脱离社会的人注定无法生存，也注定是不快乐的，融入社会并为社会有用、为他人做出贡献是我们存在的意义的根本，并且只有这样，个人才能获得真正的快乐！&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;作者认为自卑感是我们每个人与生俱来的，并且实际上自卑感是我们前进的根本动力；而优越感则是我们一切行动的最终目的。&lt;/p&gt;

&lt;p&gt;书中对于家庭、学校对人成长过程中的论述可以说是我认为全书中最精彩的，虽然受其时代制约，部分观点会显得略微偏向父权，但总的来说我是高度认同的，比如：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;家庭中不应该出现任何一方权威，只有家庭成员间真正的平等，才能发展出真正的“合作”&lt;/li&gt;
  &lt;li&gt;养育孩子和家务活的贡献与作用被社会大大低估了&lt;/li&gt;
  &lt;li&gt;娇宠与忽视是孩子成长中最大的危害，他们也是产生未来社会犯罪与失败者的最主要的原因&lt;/li&gt;
  &lt;li&gt;夫妻间婚姻的幸福是孩子学会合作的第一课&lt;/li&gt;
  &lt;li&gt;处罚与批评对教育不会产生任何正面的作用，只有鼓励与成功才能激起孩子前进的动力&lt;/li&gt;
  &lt;li&gt;父亲需要做好榜样，必须证明自己对妻子、对儿子、对社会都是一个好伙伴，并让孩子认识到男人必须接受职业训练，必须能养活自己和家庭。这一点有些父权主义向，但我所受的个人还是认同的父权主义的这一部分的&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;此外书中还有一些观点是打破了我过去的认识，引起我更多思考的，比如：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;对孩子的性教育不应该避而不谈，也不应该知无不言，因为孩子往往还没有准备好接受他们还无法适当掌握的性知识，结果反而容易引起不恰当的兴趣与好奇。应该仅针对孩子好奇与希望知道的内容进行解答和指导&lt;/li&gt;
  &lt;li&gt;孩子对不同的学科的兴趣发展，并非是先天决定的，主要是由后天中受到的反馈（即鼓励还是打击）决定的&lt;/li&gt;
  &lt;li&gt;多子家庭中出现问题儿童的绝大多数是长子，其次是最小的孩子。长子的问题往往是由于第二个孩子诞生后家庭关系之间的平衡发生了变化，而家长未能及时帮助孩子调整其心态&lt;/li&gt;
  &lt;li&gt;我们无法保证每个家庭的家长都能合格的抚养出心理健康的孩子，而学校才是应该承担起这个社会责任，而教师则是应该通过严格的培训并具有极强的责任感&lt;/li&gt;
  &lt;li&gt;罪犯的出现均是由于“合作”的缺失，而且基本上都是由于童年的糟糕的成长环境导致的&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;不过作者也有一些观点在我看来可能是我无法认同的，会让我感觉到作者受其时代的制约，比如：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;作者强调梦是对人内心深处行为和需求的反应，但我还是更倾向于认为梦只是大脑在睡眠时进行重组记忆以及优化大脑中各种记忆间相互关联时产生的生理附带现象而已。&lt;/li&gt;
  &lt;li&gt;作者认为同性恋是成长过程中产生的不正确的生活目标所导致的，是属于“生活的失败者”，但我们现在社会观点中，尤其是科学领域更倾向于认为同性恋是先天形成的。&lt;/li&gt;
  &lt;li&gt;作者非常强调人类作为社会性动物的存在，甚至会认为人类尚存的自私和利己主义是因为作为社会性动物尚未进化完全的部分&lt;/li&gt;
  &lt;li&gt;作者表示养育子女是个人作为奉献与合作的一种表达，是我可以理解和认同的，但同时认为不婚不育与犯罪、同性恋一样都是“生活的失败者”，则是有些过于片面且理论化了，目前东亚社会中普遍存在的低生育率问题可绝不是能归结到个人在“合作发展上的失败”这么简单的一个议题。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;读完全书后，通过其他人的评论，我才发现我所读的这本（也是市面上最流行的译本）似乎并非是评价最好的译本，17年民主建设出版社出版马晓佳翻译的那本可能质量更高一些，只好等将来如果有机会想重读时再去读吧。&lt;/p&gt;

&lt;p&gt;话说习惯了电子书阅读之后，真的是很难再回到实体书阅读了，我现在就陷在这样一种矛盾中，首先我不喜欢收集实体书，实在是因为太占地方了，而且搬家时又是极大的负担，但我又很喜欢逛书店，喜欢书籍一摞摞错落有致的摆放在书架上的感觉，还有那种油墨印刷的书香味道。我喜欢实体书的印刷与设计，每一本都包含着作者和出版社为了让读者读着舒心的用心良苦，而且每本又不那么一样，带着各自的风格与个性，但是当我真的去阅读一本书时，却又已经被电子阅读器宠坏了，电子书可以设置自己心仪的字体、大小、间距、留白等，还能搜索和高效的摘抄。&lt;/p&gt;

&lt;h1 id=&quot;笔记&quot;&gt;笔记&lt;/h1&gt;

&lt;p&gt;《自卑与超越（完整全译本）》
阿尔弗雷德·阿德勒
182个笔记&lt;/p&gt;

&lt;h3 id=&quot;译者序&quot;&gt;译者序&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;阿德勒认为：由身体缺陷或其他原因所引起的自卑，有可能摧毁一个人，使人自甘堕落或发生精神病，但另一方面，也有可能使人发愤图强，力求振作，以补偿自己的弱点。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;自卑感并不是变态的象征，而是个人在追求优越地位时的一种正常的发展过程。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;一生活的意义&quot;&gt;一、生活的意义&lt;/h2&gt;

&lt;h3 id=&quot;1生活对于我们的意义&quot;&gt;1．生活对于我们的意义&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;人类通过自己的行为来诠释生活的意义，几乎每个人都只把这个问题和它的答案通过自己的行为表现出来。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;2人生的三大事实&quot;&gt;2．人生的三大事实&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;这三个事实之一是：我们人类居住在地球这个贫瘠星球的表面上，我们没有办法脱离地球的表面去讨生活。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;2023/10/23发表想法
人终究是一种社会动物，这是已经写入我们DNA中的&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;我们自己并不是人类种族的唯一成员，我们四周还有其他人，只要我们活着，就必然要和他们发生联系&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;人类同时还被另一种事实所束缚：人类有两种性别，个体和人类集体生命的存续都必须依赖于这一事实。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;生活中的每一个问题几乎都可以归纳于职业、社会和性这三个主要问题之下。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;假如有一个人，他的爱情生活很不完美，他对职业也不够尽心尽力，他的朋友很少，因为他发现和他的同伴接触是件痛苦的事。那么，从他在生活中所遭遇的这些拘束和限制，我们可以断言：他一定会感到“活下去”是件艰苦而危险的事，生活对他来讲机会太少而挫折太多。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;假如有一个人，他的爱情生活非常甜蜜而融洽，他在工作上取得了可观的成就，他的朋友很多，他的交际范围广泛而成果丰硕。我们可以据此而断言，这样的人必然会感到生活是一种富于创造性的过程，生活中充满了机会，却没有不可克服的困难。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;3社会情感&quot;&gt;3．社会情感&lt;/h3&gt;

&lt;p&gt;2023/10/23发表想法
这种想法似乎是在完全否定个人主义&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;属于私人的意义是完全没有意义的，意义只有在和他人交往时才有存在的可能。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;即使是天才，也只能用其至高无上的效用来定义，因为一个人的生命只有被别人认定为对他们很重要时，他们才会称他为天才。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;我们赋予生活的意义是否真的应该是：奉献、对别人发生兴趣和互助合作。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;2023/10/23发表想法
屈从社会，适应社会，融入社会&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;假如一个人在他赋予生活的意义里，希望对别人能有所贡献，而且他的情感也都指向了这个目标，他自然会把自己的人格塑造到理想形态——一种对他人、对社会都有贡献的状态。他会根据自己的目标调整自己，他会根据自己的社会感觉来训练自己，他也会从练习中获得种种能力和技巧。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;2023/10/23发表想法
科学就是现代最强大的“宗教”&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;由于科学使人类对其同类的兴趣大为增加，所以它或许比政治和宗教等其他运动更能接近这一目标，也更能让人类了解生活的意义。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;4童年对人生的影响&quot;&gt;4．童年对人生的影响&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;意义不是由环境决定的，而我们则以我们赋予环境的意义决定了我们自己。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;这种儿童的心灵负担非常重，他们很难体会到生活的意义在于奉献。除非有和他们很亲近的人能把他们的注意力由他们自身转移到他人身上，一般情况下，他们大都只会关心自己的感觉。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;他一直被训练为只取不予，而从未学会用别的方式来与他人相处。别人老是服侍着他，这使他丧失了独立性，他不知道自己也能做事情。当他面临困难时，他只有一种应付的方法——乞求别人的帮助。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;被宠坏的孩子长大之后，很可能成为我们社会中最危险的群体。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;2023/10/23发表想法
自私+任性&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;他们觉得：“生活的意义是——独占鳌头，被认为是最重要的人物，并获取心中想要的每件东西。”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;2023/10/23发表想法
缺乏爱的人往往如此&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;他不知道他能用对别人有利的行为来赢取感情和尊敬，因此，他不但怀疑别人，也不能信任自己。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;这三种情境——器官缺陷，被娇纵，被忽视——最容易使人将错误的意义赋予生活。从这些情境中出来的儿童几乎都需要帮助以修正他们对待问题的方法。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;5童年记忆的重要价值&quot;&gt;5．童年记忆的重要价值&lt;/h3&gt;

&lt;p&gt;2023/10/23发表想法
即使是一些不那么愉快的记忆，它也是塑造我们的一部分&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;每件记忆都是值得纪念之物。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;当新婴儿降生时，要得到年纪较长的孩子的合作，最好是让他们帮忙照顾他，使他们对他产生兴趣，并分担保护他的责任。如果得到了他们的合作，他们便不会把父母集中在娃娃身上的注意力当作是对他们重要性的一种威胁。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;6合作的重要性&quot;&gt;6．合作的重要性&lt;/h3&gt;

&lt;p&gt;2023/10/23发表想法
所以这本书实际上是《神经病自救指南》吗&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;合作也是我们拥有的防止神经病倾向发展的唯一保障&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;我们必须开拓我们的生活。这是我们的责任，我们也能够对付它。我们是自己行为的主宰。除旧布新的工作，舍我其谁！”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;二心灵与肉体&quot;&gt;二、心灵与肉体&lt;/h2&gt;

&lt;h3 id=&quot;1心灵与肉体的交互作用&quot;&gt;1．心灵与肉体的交互作用&lt;/h3&gt;

&lt;p&gt;2023/10/24发表想法
从进化学来分析，植物也没有进化出复杂思维的必要性&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;假如植物能预见未来，它们的官能也会使之一无所用。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;我们所有的努力都是为要达到一种能使我们获得安全感的地位，这种感觉是：生活中各种困难都已经被克服，而且我们在环绕着我们的整个情境中，也已经得到最后的安全和胜利。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;如果我们看到一种表现或病征，而无法认出它背后的意义时，要了解它的最好方法，就是先将它依外形分解成简单的动作。让我们以偷窃的表现为例。偷窃就是把别人的所有物据为己有&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;2情感影响发展&quot;&gt;2．情感影响发展&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;愤怒是控制一个人或一种情境的工具之一。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;所有神经病患者都会避开生活中不能使他们感到自己是征服者的部分。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;在第五年结束时，他的人格已经成形。他赋予生活的意义、他追求的目标、他趋近目标的方式、他的情绪倾向等等，也都已经固定。以后它们虽然也可能改变，但在改变它们之前，他必须先从儿童期固定成形时所犯的错误中解脱出来。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;器官的缺陷造成了许多阻碍，但是这些阻碍却绝不是无法摆脱的命运。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;但是，患有夜尿症的儿童所受到的待遇，大都不会使他想克服它，反倒会想继续保留它。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;母亲很可能错误地用尽各种方法想消除他的夜尿症。如果孩子注意到这一点是多么受人重视，他就可能不愿治愈自己的疾病。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;假如孩子想反抗父母给他的待遇，他必然会找出他自己的方法，来攻击他们最大的弱点。德国有一个著名的社会学家发现：在罪犯中，有相当惊人的比例是来自那些父母的职业是压制犯罪的家庭，如法官、警察、狱吏等。而教师的子女也常常特别顽劣难化。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;例如，当一个人发脾气时，他总希望尽快地克服这种情绪，而他找到的最好方法似乎就是：打击、辱骂或诋毁另一个人。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;3身形性格与心智&quot;&gt;3．身形、性格与心智&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;假如他们的环境以另一种方式加给他们许多负担，他们也会变得胆小而沮丧。通过有计划的打击，我们可能把任何一个小孩变成举止像神经质的人。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;在所有的失败者之间，最常见的共同点是其合作能力非常之低。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;迄今为止，我们所拥有的了解心理差异的最好方法，就是观察其合作能力的高低。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;三自卑感和优越感&quot;&gt;三、自卑感和优越感&lt;/h2&gt;

&lt;h3 id=&quot;1自卑情结&quot;&gt;1．自卑情结&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;告诉病人他正蒙受着自卑情结之害是没有什么用的，这样做只会加重他的自卑感，而不是让他知道如何克服它们。我们必须找出他在生活样式中表现出的特殊气馁，我们必须在他缺少勇气之处鼓励他。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;2023/10/27发表想法
当人无法处理所面对的压力时，而又无法逃避时则会开始转向自欺&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;他的自卑感会愈积愈多，因为造成自卑的情境仍然一成未变，问题也依旧存在。他所采取的每一步都会逐渐将他导入自欺之中，而他的各种问题也会以日渐增大的压力逼迫着他。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;当个人面对一个他无法应付的问题时，他表示他绝对无法解决这个问题，此时出现的情绪便是自卑情绪。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;愤怒、眼泪和道歉一样，都可能是自卑情绪的表现。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;在面临困难时，最彻底的退缩表现就是自杀。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;在每个自杀案件中，我们总会发现：死者一定会把他死亡的责任归之于某一个人。自杀者仿佛在说：“我是所有人类中最温柔、最仁慈的人，而你却这么残忍地对待我！”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;2023/10/27发表想法
就是我们常说的恋母情结&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;俄狄浦斯情结&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;他们在爱情里寻找的，不是平等的伴侣，而是仆人；最能使他们安心依赖的仆人则是他们的母亲。我们在任何孩子身上都可能造成俄狄浦斯情结。只要我们让他的母亲宠惯他，不准他把兴趣扩展到别人身上，并让他的父亲对他漠不关心。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;2023/10/27发表想法
这么说强迫症背后的原因也是来自自卑感&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;对白天的工作感到十分厌烦的失眠症患者&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;我们人类的全部文化都是以自卑感为基础的。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;如果我们想象出：一个人或人类整体，已经抵达了一个完全没有任何困难的境界，我们必能想象到：在这种环境中的生活一定是非常沉闷的。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;我们生活中的乐趣主要是来自我们缺乏肯定性。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;2追求优越感&quot;&gt;2．追求优越感&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;没有哪一个人对他的优越感目标清楚得能够将之完整无缺地描述出来。他也许知道他的职业目标，但这只不过是他努力追求的一小部分而已。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;我们能够看出：他训练自己去帮助他的同类到何种程度，以及他限制住他的帮忙到何种程度。他把他的这种目标作为补偿其特殊自卑感的方法，而我们也必须能够从他在职业中或在其他地方的表现，猜测出他所欲补偿的自卑感。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;对优越感的追求是极具弹性的，事实上，一个人愈健康、愈接近正常，当他的努力在某一特殊方向受到阻挠时，他愈能另外找寻新的门路。只有神经病患者才会认为他的目标的具体表现是：“我必须如此，否则我便无路可走了。”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;3设立有意义目标&quot;&gt;3．设立有意义目标&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;我们需要让他们改进的，是他们的具体目标。目标一改变，心灵的习惯和态度也会随之改变。他不必再用他旧有的习惯和态度，适合于他的新目标的态度会取代它们的地位。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;真正能够应付并主宰其生活问题的人，只有那些在奋斗过程中也能表现出利人倾向的人，他们超越前进的方式可以使别人也能受益。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;我们对行为、理想、目标、行动和性格特征的各种要求，都是它们应该有助于人类的合作。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;四早期的记忆&quot;&gt;四、早期的记忆&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;记忆绝不是偶然的，人们只会记忆那些他觉得对他的处境极具重要性的事件。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;1理解记忆&quot;&gt;1．理解记忆&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;个人企图达到优越地位的努力，是整个人格的关键，所以我们在个人心灵生活中的每一点都能看到它的影像。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;记忆绝不是偶然的，个人从他接受的、多得不可计数的印象中选出来记忆的，肯定是那些他觉得对他的处境极具重要性的事件。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;只要他的生活样式发生了改变，他的记忆也会随之改变。他会记住不同的事情，否则他便会对他记得的事件给予不同的解释。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;2关于早期记忆的六个案例&quot;&gt;2．关于早期记忆的六个案例&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;早期的回忆是特别重要的。首先，它们显示出个人的生活样式的根源，及其最简单的表现方式。我们从中可以判断：一个孩子是被宠惯的还是被忽视的，他能和别人合作到何种程度，他愿意和什么人合作，他曾经面临过什么问题，以及他如何对付它们。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;第一件记忆能表现出个人的基本人生观，这是他的态度的雏形。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;大部分人都会从他们的最初记忆中透露出他们生活的目的，他们和别人的关系，以及他们对环境的看法。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;一个人所受过的训练是使他趋向合作，还是反对合作；他是勇气十足，还是胆小沮丧；他是希望受人支持和被人照顾，还是充满自信而能够独立；他是准备施予，还是只想接受。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;祖父祖母几乎都是很疼爱孙儿们的。他们不像孩子的父母亲那样承担着教育孩子的责任，他们希望孩子们能依附他们，以证明他们仍然能够获得温情。我们的文化很不容易让老人家们感到自己有价值，有时，他们会用一些简单的方法来肯定自己的重要性——例如喜欢动怒等。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;年纪较小的孩子经常会有一个竞争的对手，而他们又一直想要击败他们的对手。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;当一个人讨厌某件事物，而要找出这种厌恶的理由时，他通常会从他的经验中挑选出某些东西来作为解释。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;3行为的根源早期记忆&quot;&gt;3．行为的根源——早期记忆&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;假如下雨了，你该怎么办？你只能打把雨伞或坐出租车，想要和雨反抗或压过它都是没有用的。现在你正像竭尽所能去反抗雨一样。你相信你有力量。你相信你已经压过他了，但是你的胜利伤害最深的却是你自己。”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;五梦&quot;&gt;五、梦&lt;/h2&gt;

&lt;h3 id=&quot;3个体心理学派与梦&quot;&gt;3．个体心理学派与梦&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;梦是常识的敌人。我们很可能发现有些不愿意被他们的感觉所欺骗的人，他们宁可依照科学的方法做事。这种人很少做梦或根本不会做梦。其他的人大都喜欢背离常识，他们不愿意用正常而有用的方法来解决他们的问题。常识是合作的一面，合作素养欠佳的人都不会喜欢常识。这种人会频频做梦。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;2023/10/29发表想法
太玄学了，作为理科生我觉得做梦就是大脑在睡眠时重组记忆和优化它们之间的联系时产生的副产品，不要过度解读&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;每一个梦都是自我陶醉和自我催眠，它的全部目的就是引起一种让我们准备应付某种问题的心境。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;4梦的构成&quot;&gt;4．梦的构成&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;当代的弗洛伊德也曾特别强调：梦主要是由隐喻和符号构造而成的&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;这是因为假如我们不用隐喻和符号，而坦率地说出自己的意愿，我们便无法避开常识。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;2023/10/30发表想法
在跳跃前数一二三的例子&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;在人类的心灵中，已经预存有执行生活样式，并使之固定和加强的各种方法，最重要的方法之一就是激发起心境的能力。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;5常见的梦&quot;&gt;5．常见的梦&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;关于梦，我们必须首先考虑的是它遗留下来的心境，以及它和整个生活样式之间的关系。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;经验使我们相信：一个人如果无法与人交往，很可能是因为她希望驾驭别人，事实上，她只对自己有兴趣，她的目标在于表现她个人的优越感。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;在我们的时代，美丽的女孩容易给人深刻的印象，也容易控制别人&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;一个人如果是合作的，他必定也是勇敢、乐观的。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;六家庭的影响&quot;&gt;六、家庭的影响&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;如果在家庭中没有权威的存在，那么其中必定会有真正的合作。父亲和母亲都不应在家中占有太突出的地位。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;1母亲的影响&quot;&gt;1．母亲的影响&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;假如我们希望培养出很有技巧的母亲，我们必须教女孩子以母道，让她们喜欢当母亲，把母亲的工作视为是一种创造性的工作，而且在以后的生活里，当面临自己所要扮演的角色时不会感到失望。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;很不幸，在我们的文化中，女性母道部分的价值却被视为是微不足道的。假如人们重男轻女，假如男性的角色占有较优越的地位，女孩子自然不会喜欢她们未来的工作。没有人会居于臣属的地位而感到满足。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;2023/10/30发表想法
不知道现在东亚社会普遍少子化是因为这个因素更大还是因为经济上的压力更大？&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;她们不愿意也不准备怀孩子，她们不期望孩子的到来，也不觉得养育孩子是件有趣的创造性活动。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;人类的整个社会都维系于女性对母道的态度。然而，几乎在每一个地方，女性在生活中的地位都被低估，而且被认为是次要的。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;即使在童年时期，男孩子们也常常把家务事看作是仆役的工作，似乎他们的尊严不容许他们插手做家务。人们很少把整理家务当作是女性的一大贡献，而视之为贬抑女性的一种苦役。如果女人真正能够把家事看作是一种艺术，从中能获得乐趣，并能丰富光大她家人的生活，她就能够使它成为比世界上任何其他职业都不逊色的工作。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;母道的驱动力已经被证实比性或饥饿的驱动力更强。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;通过她的儿子，她才和生活的整体紧密联系，她才觉得自己是生与死的主宰。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;对母道的追求就是人类对优越地位——成为神圣的目标——追求的一种表现&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;她自己必须给予孩子一个可信赖人物的最初经验，然后她必须准备将这种信任和友谊扩展开，直到它包括整个人类社会为止。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;这种欲望与性无关。它是一种支配母亲的欲望，它要完全控制她，使她成为奴仆。只有被母亲骄纵，并且对世界上的其他人没有同胞感的孩子，才会有这种欲望&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;一个被母亲缚在她自己身边的孩子，一旦进入一个不再和她联系在一起的情境，麻烦就开始发生了。例如，当他到学校去，或在公园里和其他孩子一起玩时，他的目标仍然是要和他的母亲联系在一起。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;2023/10/30发表想法
我小时候也怕黑，怕黑并不意味着都恋母，对黑暗的恐惧是百万年进化中刻在DNA中的&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;他对黑暗的害怕，意思只是他不喜欢和母亲分开。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;对被宠惯的孩子而言，疾病是求之不得的事。因为当他们害病时，他们会比平常更受到关注。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;养育这种孩子的最好方法，是帮他们找到能代替母亲或父亲角色的人，让他们过上平常的家庭生活。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;许多失败者的出身都是孤儿、私生子、被遗弃的孩子，以及由于父母的婚姻破裂而留下的孩子，从这件事实可以看出母亲的温暖和照顾是多么重要&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;假如我们都能体会到合作和爱情是绝对无法用武力获得的，那么在这个世界上，一定可以避免没有必要的紧张和没有用处的努力。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;2父亲的角色与责任&quot;&gt;2．父亲的角色与责任&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;他最先对其他人之间合作的感受，就是父亲和母亲之间糟糕的合作关系，这样的父母不可能希望能教会孩子如何合作。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;婚姻的意义是两个人共同结合以谋求他们相互的幸福，他们孩子的幸福，以及社会的幸福；&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;在家庭生活的全部行为之中，并不需要应用权威；假如其中有一个成员特别突出，或比别人更受重视，那一定非常不幸&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;作为父亲，他必须证明他自己对妻子、对儿子，以及对社会都是一个好伙伴。他必须以良好的方式应付生活的三个问题——职业、友谊和爱情。他必须以平等的立场和妻子合作，照顾并保护他的家庭。他不能忘记妇女在家庭生活中所占有的创造性地位是不容贬抑的，他的责任不是贬低妻子的母亲角色，而是和她一起工作。在金钱方面，我们应该特别强调，即使父亲是家庭主要的经济来源，它仍然是家庭共有的。父亲绝不应表现得好像他在施舍，其他人则在收受。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;每一位父亲都应该了解，我们的文化过分强调了男性的优越地位，结果他的妻子在和他结婚之后，便生怕自己会受到贬抑而被置于低下的地位。他不能只因为他的妻子是女性，不会像他一样赚钱养家，便以为妻子不如自己。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;处罚，尤其是体罚，对孩子总是有害的。不能以友善的方式进行的教育便是错误的教育。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;如果母亲告诉她的孩子：“等你爸爸回来教训你！”她等于是暗示他们：把父亲当作最后的权威以及生活中的实力人物。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;有时候，两个仍旧依赖在父母身上的人结了婚，他们会过分重视他们和原来家庭之间的联系，当他们提到“家”时，他们指的是他们父母的家。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;假如他们对儿子的婚事不满意，他们可以在结婚之前表示反对，但是既然结婚了，那就只有一条路可以走——他们应该尽其所能促成婚姻的美满。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;作为父亲，男人必须接受职业训练，必须能养活他自己和家庭。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;在我们现代的文化环境下，经济责任主要还是落在男人肩上。要解决这个问题，他必须工作，必须勇敢，必须了解他的职业并知道它的利弊，必须在他的行业中和别人合作，让别人对他有好感。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;因此，他必须成功地解决这个问题——找到能对全体人类有所贡献的职业。然而，他本人认为自己从事的职业是否有用倒无关紧要，重要的是工作本身必须有用。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;3为人父母&quot;&gt;3．为人父母&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;做丈夫有一个重要条件：他必须对他的配偶深感兴趣。要看出一个人是否对另一个人有兴趣是很容易的事。如果他对她有兴趣，他对她喜好之物也会感兴趣，同时会把她的幸福当作是自己必须兼顾的目标。情感不仅能够证明彼此之间有兴趣，有许多种情感还能作为夫妻之间事事和谐的明证。他必须成为他妻子的良伴；他必须努力奋斗，以使她的生活更舒适、更富裕；他必须乐观进取，以取悦她。只有夫妻双方都认为他们的共同幸福高于个人利益时，才可能有真正的合作。他们两人对另一方的兴趣都应该比对自己的兴趣更浓。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;假如夫妻彼此过分亲密，有时候孩子就会觉得自己的地位降低了。他们会产生忌妒之心，并希望能和父亲或母亲一争长短。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;我觉得在我们这个时代有一种倾向，人们想告诉孩子许多他们还无法适当掌握的性知识，结果引起了不恰当的兴趣和好奇，甚至把性不当一回事，而以稀松平常的态度等闲视之。这样子并不见得比以往隐瞒孩子或绝口不谈与性有关的事物的态度更高明。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;所以，最好是先了解孩子希望知道什么，并只回答他们正在思考的问题，而不要从我们自己的角度强迫他们接受我们认为每个人都应该知道的事情。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;父亲应该作为妻子和孩子们的顾问。他不能利用他较多的经验而过分夸大其词。他不是家庭教师，他应该像朋友互相劝告一样地劝导他们，并且要避免引起反感。假如他们同意了他的看法，也不必得意忘形。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;女人通常不外出挣钱，因此她们对金钱大多比丈夫敏感。如果批评她们浪费，她们会深感受到伤害。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;妻子或孩子们也不应该迫使父亲付出在其能力之外所能负担的金额。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;如果父亲非常成功或才能出众，孩子们会觉得自己的成就不可能和他等量齐观。他们泄气了，他们对生活的兴趣也会受到妨碍。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;假如父亲在他的行业中很有成就，他不应在家庭中过分强调他的成功，否则孩子们的发展便会受到阻碍。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;当然，假如他的父母曾让他对他们的关爱怀有信心，假如他知道他的地位稳如泰山，最重要的，假如他已经准备要迎接新娃娃的降临，并学会怎样帮忙照顾他，那么，这场危险便会不留恶果地消失于无形。通常，他都没有做好这种准备。新娃娃真的夺走了他原来享有的照顾、情感和赞赏。他开始想把母亲拉回自己身边，并考虑要怎么做才能重新获得别人的注意。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;有时候，这种丧失过权力以及自己一度统治过的小王国的孩子，会比其他孩子更理解，权力和威势的重要。当他们长大后，他会喜欢搬弄权势，并过分夸张规则和纪律的重要性&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;问题儿童的绝大部分都是长子，紧接其后的是最小的孩子。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;次子通常都比长子有才能，并较为成功。此处，我们无法承认遗传在这种发展中有任何影响。假如他很快地超越前进，那只是因为他对自己要求较高。即使在他长大之后，走出家庭圈子，也经常会找一个竞争对手；他常常会拿自己和这个他认为占有优越地位的人互相比较，并想尽各种办法要超越他&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;最小的孩子经常是整个家庭的栋梁，这件事并非偶然。人们都知道这一点，并编了许多有关最小的儿子的力量的故事。事实上，他是处在一个相当有利的情境中：父亲、母亲、兄妹，都会帮助他；还有许多事物可以激发他的野心和努力，同时又没有人从后面攻击他或分散他的注意力。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;独生子也有属于他自己的问题。他有一个敌手，但是他的敌手并不是哥哥或姐姐。他竞争的感觉是针对他的父亲。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;在女孩子中间长大的男孩，都是属于不太讨人喜欢的类型。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;七学校的影响&quot;&gt;七、学校的影响&lt;/h2&gt;

&lt;h3 id=&quot;1教育的变革&quot;&gt;1．教育的变革&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;学校是家庭的延伸。假如父母能够负起对孩子们教育的责任，让他们能够适当地解决生活中的各种问题，那么便没有学校教育的必要了。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;在欧洲教育的历史上，最先只有王子和贵族的子弟才能受教育，他们是社会中唯一有价值的群体，其他的人注定要安分守己，默默无闻过一辈子。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;2教师的角色&quot;&gt;2．教师的角色&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;我们必须找出一批教师，他们不只是为金钱而教育儿童，他们能遵照人类的利益来工作。他们必须体会到这种工作的重要性，并且接受了良好的训练。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;教授课程最好的方法就是和生活中的其他部分紧密连接，使孩子们能够看出这种教导的目的和他们所学知识的实用价值。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;3课堂里的合作与竞争&quot;&gt;3．课堂里的合作与竞争&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;他在学校的功课很差，当他父母听到这个消息后，便在家里“修理”他。这种情况是经常发生的：孩子在学校里拿了一张坏成绩单，挨了教师一顿骂；把它带回家后，又受到父母的惩罚。这种事经历一次便已经够叫人丧气了，连续两次遭惩罚简直是恐怖。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;2023/10/31发表想法
孩子会更凭借本能做事，缺少成年人的理智&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;否则，我们会发现，孩子们对他们的自治并不会十分严肃，他们只把它当作一种游戏。结果他们可能比老师更严厉、更苛刻；他们可能利用班会来争权夺利，攻击别人，排除异己，或争取优越的地位。因此，从一开始起，教师就应该给予学生们应有的注意和劝告。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;在教育中引起最大困扰的，并不是儿童本身的各种限制，而是他认为他具有的各种限制。假如一个儿童知道他的智商很低，他可能觉得全无希望，成功已与他绝缘。在教育过程中，我们应该全力设法增加儿童的勇气和信心，并帮他消除由于他对生活的解释而为自己的能力订下的各种限制。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;当老师给某个学生一张很坏的成绩单时，他相信他是在刺激他发奋向上。然而，假如学生的家庭对他要求很严，他可能就不敢把成绩单带回家。他可能涂改成绩单或不敢回家。在这种情况下，有时候孩子们甚至会自杀。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;他们最常犯的错误是相信他们再也无法进步了。他们看到别人遥遥领先，认为自己永远无法企及。假如一个孩子对这种看法非常固执，他会把它移转到以后的生活环境中。即使是在成年后的生活里，他也会计算他的地位和别人之间的距离，以为自己必须永远留在这一点之后。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;4天赋与习得&quot;&gt;4．天赋与习得&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;能够妨碍兴趣的，并不是遗传，而是灰心或对失败的畏惧。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;我在念书时，有好几年都是班上的数学低能儿，我也十分相信我完全缺乏数学才能。很幸运的是，有一天，我竟然出乎意料地发现自己会做一道难倒了老师的题目！这次成功改变了我对数学的整个态度。以往，我的兴趣完全没有放在这门功课上，现在，我开始以数学为乐，并利用每个机会来增强我的数学能力。结果，我在学校里成为数学学习上的佼佼者。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;5区分孩子的个性&quot;&gt;5．区分孩子的个性&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;直到16岁之前，女孩子发育得都比男孩子快。假如男孩子不了解这点，他们便很难保持他们的自尊。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;有些孩子只有在受到嘉奖或赞赏时才肯学习。有许多被宠惯的儿童，只有在老师对他们额外注意时，他们在学校功课的表现上才特别优越。假如他们失去了这种特别的关怀，麻烦就来了。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;懒惰的孩子，除非他的懒惰是对父母或老师的直接攻击，否则他们几乎都是野心勃勃而又怕遭到失败打击的儿童。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;懒惰的孩子从未尝过被击败的滋味，因为他从没有面临真正的考验。他对眼前的问题总是尽量逃避，也不肯轻易和人一较短长。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;儿童时期的错误和成年后的失败是一脉相通的。没有学会合作之道的儿童，以后会变成神经病、酗酒者、罪犯或自杀者。焦虑性神经病患者幼时多害怕黑暗、陌生人或新情境。忧郁症患者多是爱哭的娃娃。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;6顾问会议的工作&quot;&gt;6．顾问会议的工作&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;他并不责备孩子，只是和他进行一种友善的谈话，给他另一种观点。假如他想提及孩子的错误，他可以将他放进一种假设的情况中，以此来征求孩子的意见。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;八青春期&quot;&gt;八、青春期&lt;/h2&gt;

&lt;h3 id=&quot;2心理特征&quot;&gt;2．心理特征&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;对每个孩子而言，青春期中最重要的一件事情就是他必须证明他已经不再是个孩子了。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;4青春期的挣扎&quot;&gt;4．青春期的挣扎&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;青春期的所有危险，都是由于对生活的三个问题缺乏适当的训练和准备所造成的。如果孩子们对未来心怀畏惧，他们自然会以最不费力气的方法来应付它。然而，这种简单的方法却是没有用的方法。孩子们越是受到命令、告诫、批评，他们越觉得彷徨不知所从。我们愈推他向前，他会愈往后退缩。除非我们能够鼓励他，否则想帮助他的努力都会徒劳无功，甚至伤害到他。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;这些都是勇敢坚毅的孩子，对他们而言，独立的意义并不是困难和冒失败的危险，而是更广泛地获取成就和为别人奉献的机会。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;以前一直觉得受人轻视的儿童，现在可能因为和同伴的接触增加，而开始孕育出他们也能被人欣赏的希望。他们中有许多人非常醉心于争取别人的赞赏。男孩子假如只想寻求别人的夸奖，那是相当危险的；&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;她在青春期时，把设法脱离被轻视的感觉这件事的重要性看得太重了！&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;5青春期的性意识萌芽&quot;&gt;5．青春期的性意识萌芽&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;假如一个女孩子相信自己一直受母亲的压迫而意图反抗，她就很可能任意和她遇上的男人发生性关系，以此作为反抗的手段&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;我们宁可等待孩子开始好奇而想知道这方面的事时，才告诉他们。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;6正视青春期&quot;&gt;6．正视青春期&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;如果这个孩子已经学会把自己当作是和社会上任何人平等的一分子，并了解他应该做的奉献工作，尤其是如果他已经学会将异性看作是平等的友伴，青春期只是给他一个机会，让他开始对成年人的生活问题做出独立而有创造性的解答。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;九犯罪及其预防&quot;&gt;九、犯罪及其预防&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;罪犯的失败只是程度较深的共同失败而已。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;1犯罪心理&quot;&gt;1．犯罪心理&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;在罪犯的各种活动和态度中，都显现出他也是努力要成为优秀的人物，要解决问题，要克服困难。他和普通人的不同之处并不在于他没有做这种形式的追求，而是他所追求的方向。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;2023/11/01发表想法
这样去想，很多罪犯可能是一直未能在正确的方向上取得过足够的正向反馈&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;如果你追溯他们的历史，你将会发现他们在学生时代，甚至是在进学校之前，就已经发生困难了。他们从未学会合作之道。要解决职业问题，非要先学会与人合作不可，但是这些罪犯偏偏与此道无缘。因此，假如他们在职业问题之前失败了，我们也不能过分责怪他们&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;他们把异性当作是一宗财产，我们经常发现他们认为爱情是可以购买的。对这种人而言，性生活是征服，是占有，也是他们应该保有的东西，而不是生活中的伴侣关系。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;2023/11/01发表想法
惩罚的效果并不像人们想象的那么大&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;我们必须教给罪犯合作之道，只在感化院里鞭打他们是没有什么用的。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;妒忌绝不会产生有价值的目标。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;2罪犯的类型&quot;&gt;2．罪犯的类型&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;父母们可能也想把他们的孩子教育成良好的公民，可是他们却不知从何入手。如果他们整天板着脸孔，事事吹毛求疵，他们一定不会有成功的机会。如果他们骄纵他，让他成为舞台上的主角，他就会只因为他自己的存在，便觉得自己很重要，而不愿意作任何有创造性的努力，以博取其他人的赞扬。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;3合作的重要性&quot;&gt;3．合作的重要性&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;除非我们能获知他各种解释背后的意义，和他各种观点的成因，并发现他的态度最初开始时的方式，否则我们就无法劝服他。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;2023/11/03发表想法
有些时候会觉得法家的思路就是‘’不要再在走歪的人身上浪费社会资源了，直接淘汰掉……‘’&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;这就是严厉刑罚总是不生效的原因之一。罪犯会把它看作是社会充满敌意及不可能与之合作的证据。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;有什么人会对一个经常受到责备和惩罚的地方培养出兴趣呢？在这种情况下，孩子会信心全失，他对学校、老师、同学再也不会感兴趣。他开始逃学，四处游荡，寻求隐匿之所，以免被发现。在这些场所，他会找到一些和他有同样经验，又走上同样道路的孩子。他们了解他，他们不但不责怪他，反倒恭维他，并燃起他的野心，让他把希望寄托在生活中无用的一面上。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;2023/11/03发表想法
父母要深知榜样的作用和重要性&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;当父母在子女面前抱怨生活艰难、世道险恶时，他们也会妨碍孩子社会兴趣的发展。假如他们老是指责他们的亲戚或邻居，老是批评别人并显露出对别人的恶意和偏见，也会发生同样的事情。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;如果大家能认识到犯罪是懦弱的表现，而不是勇敢的行为，那么我相信，罪犯就无法对自己的行为自圆其说，而且也没有小孩子再愿意在未来走上犯罪道路&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;4如何矫治犯罪行为&quot;&gt;4．如何矫治犯罪行为&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;在各种不同的失败者之间，他们最主要的共同点就是缺乏合作精神，缺乏对别人及对人类幸福的兴趣。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;我们可以看出他的自卑情结。他逃避着劳动的情境以及必须和别人发生联系的生活和工作。他觉得靠自己的能力无法获得正常的成功。他不肯和人合作的习性会增加他的困难，因此大部分的罪犯都是非技术性的劳工。他发展出一种毫无价值的优越感来隐藏起他的自卑情结。他一直在想象自己是多么勇敢，多么出类拔萃。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;我们应该使他们摆脱他们对世界的个人解释，以及他们对自己能力的过分低估；我们应该教他们不要限制自己的发展，并消除他们对必须面临的情境和社会问题的恐惧。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;还有一点很重要的是，不管是在监狱中或是在出狱后，都不要羞辱犯人或向他挑战。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;十职业&quot;&gt;十、职业&lt;/h2&gt;

&lt;h3 id=&quot;1平衡生活的三条系带&quot;&gt;1．平衡生活的三条系带&lt;/h3&gt;

&lt;p&gt;2023/11/03发表想法
被宠坏得还子&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;有些人试图要逃避这种职业问题，他们不愿意工作，对人类共同的兴趣也漠不关心。然而，我们会发现，他们虽然不愿意面对职业问题，其实他们却总是在恳求别人的帮助。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;在我们的时代，对这个问题最完美的解决方法，也是最符合社会要求和分工制度的解决方法，就是一夫一妻制。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;3影响职业选择的其他因素&quot;&gt;3．影响职业选择的其他因素&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;还有些人不管选择了哪一种职业都不会感到满意。他们想要的不是一个职业，而是保证其优越地位的方法。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;只有对人类的共同福利有杰出贡献的个人，人们才称之为天才。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;4对待职业的态度&quot;&gt;4．对待职业的态度&lt;/h3&gt;

&lt;p&gt;2023/11/03发表想法
作者的观点认为正向的鼓励效果要远好于责罚&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;早期的努力是晚年成功的最佳基础。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;十一人及其同伴&quot;&gt;十一、人及其同伴&lt;/h2&gt;

&lt;h3 id=&quot;1人类需要团结&quot;&gt;1．人类需要团结&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;我们应该认识到，婚姻并不是私人的事情，而是全体人类在心灵上和精神上都必须参与的共同事务。结婚之后，双方都必须负起某些责任，这是整个社会对他们的期待。社会希望他们生育健全的子女，并以合作的精神将之抚育成人。因此，在每一桩婚姻中，每一个人都应当乐于合作。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;2023/11/03发表想法
几乎所有的文化都鼓励先付出&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;被宠坏的孩子问我们：“为什么我应该爱我的邻居？他们为什么不先来爱我？”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;争执、批评和贬抑对方都是不必要的。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;2利己主义&quot;&gt;2．利己主义&lt;/h3&gt;

&lt;p&gt;2023/11/03发表想法
人类的利己主义，即自私的本省是否可以理解为做为社会性动物尚未完全进化的一部分&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;我们无法认同的是只问收获、不事耕耘、只追求个人利益的人生观。这对于个人和团体的利益都是最大的阻碍。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;3过失犯罪&quot;&gt;3．过失犯罪&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;他并未受过要替别人着想的训练，他不知道要采取预防措施来保障别人的安全。这是因为他缺乏合作精神。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;4社会兴趣和社会平等&quot;&gt;4．社会兴趣和社会平等&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;如果他觉得别人都充满敌意，如果他觉得四周都是敌人，自己不得不采取防卫手段，那么我们就无法期待他会和别人结成朋友，而且他自己也不会成为别人的好朋友。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;我们对于一个“人”的所有要求，以及我们能够给他的最高荣誉，就是他必须身为良好的工作者，所有其他人的朋友，爱情与婚姻中的真正伴侣。一言以蔽之，他必须证明他是人类的一个良好的同伴。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;十二爱情与婚姻&quot;&gt;十二、爱情与婚姻&lt;/h2&gt;

&lt;h3 id=&quot;1爱情合作与社会兴趣的重要性&quot;&gt;1．爱情、合作与社会兴趣的重要性&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;合作是婚姻的首要条件了&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;爱情，以及其结果的婚姻，都是对异性伴侣最亲密的奉献，它表现在心心相印、身体的吸引，以及生儿育女的共同愿望中。我们很容易看出，爱情和婚姻都是合作的一面，这种合作不仅是为了两个人的幸福，而且也是为了人类的利益。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;2夫妻是平等的伙伴关系&quot;&gt;2．夫妻是平等的伙伴关系&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;要完全解决这种两个人的合作问题，每一个配偶都应该关心对方更甚于关心自己。这是爱情和婚姻成功的唯一基础。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;3不适合结婚的人&quot;&gt;3．不适合结婚的人&lt;/h3&gt;

&lt;p&gt;2023/11/04发表想法
作者真的很传统嘛&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;我相信，在结婚之前避免发生性关系，是爱情和婚姻中亲密奉献的最佳保证。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;2023/11/04发表想法
现在国内不婚不育的呼声越来越大，应该是内外因的综合结果，如果人人都有家有业，相信会更有意愿去抚养下一代的。作者的观点比较纯粹理想&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;所以在爱情和婚姻的问题中，我们发现，最能够自发自动地关心人类利益的人，都是最盼望要生育儿女的人，而在意识或潜意识中对其同类不感兴趣的人，都会拒绝接受子女的负担。如果他们总是索取和期待，而不愿给予，他们便不会喜欢孩子。他们只关心他们自己，而把孩子看作是一种麻烦，一种累赘，一种负担，一种会妨害他们自身利益之物。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;4婚姻观与人生观&quot;&gt;4．婚姻观与人生观&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;只有一夫一妻制才能使个人在爱情和婚姻中获得最高和最完美的发展。&lt;/p&gt;
&lt;/blockquote&gt;

        </description>
        <pubDate>Mon, 06 Nov 2023 01:52:26 +0000</pubDate>
        <link>/2023/book-what-life-should-mean-to-you.html</link>
        <guid isPermaLink="true">/2023/book-what-life-should-mean-to-you.html</guid>
      </item>
    
      <item>
        <title>[书评] 闪击英雄</title>
        <description>
          
          &lt;p&gt;二战德军有着闪电战之父之称的古德里安撰写的回忆录，国内译版标题为《闪击英雄》，凸显了古德里安的军事成就，但原版标题是《一个士兵的回忆》，相比之下就显得谦虚了很多，我更喜欢原版标题，有一些古德里安本人的军人的情节在里面——“即使是装甲兵司令，首先他也是一名士兵”。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2023/book-hero-of-blitz.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;整本书洋洋洒洒32万字，断断续续啃了18个小时（微信读书统计）才看完，虽然古也参加了一次世界大战，但在本书中只作为自己成长经历的一部分在第一章中一笔带过，书中主要内容是按照时间顺序依次介绍了：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;二战前德国装甲兵的发展与战术构想&lt;/li&gt;
  &lt;li&gt;作为前线指挥官参加的二战
    &lt;ul&gt;
      &lt;li&gt;波兰战局&lt;/li&gt;
      &lt;li&gt;法国战局&lt;/li&gt;
      &lt;li&gt;基辅战局&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;从被解职到就任装甲兵总监的时期到最终德国战败&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;一战战败后古德里安本希望能在总参谋部任职，但被意外的分配在汽车部队的经历反而使得“摩托化”的概念逐渐在其心中生根发芽，并最终使得装甲兵成为其一生笃信的战术核心理论。字里行间中，你能读出古德里安对于自己的装甲部队，对于坦克在战争中的决定性，有着不容动摇的信念（即使在二战后期制空权已经明显占据出更重要的地位）&lt;/p&gt;

&lt;p&gt;古德里安在军事上取得最辉煌的成就主要体现在二战前期的波兰和法国战局中，德国的装甲部队所向披靡，古德里安也带着他的装甲作战理念取得了载入史册的多场胜利；但是从苏德战场中，随着后勤的难以维系、糟糕的交通以及恶劣的天气，字里行间可以读出德军已经显现出强弩之末的迹象了，也就是在此时，古德里安因为违背了希特勒的军令，擅自退兵而遭到了解职。&lt;/p&gt;

&lt;p&gt;当古德里安重新被任命时，已经是在斯大林格勒会战惨败、战争的形势发生逆转以后了，出任的总参谋部装甲总监的职位也更像是一个参谋，并不能亲自领导前线的作战。从这时起，他自己也说他对于战争的走势其实已经没有太多的影响了，其努力进行的所有工作更多的是在尽职地完成一个军人的职责。&lt;/p&gt;

&lt;p&gt;古德里安与希特勒的个人关系，是个不能绕开的话题，古德里安并非出自传统军事贵族家庭（名字中不带“冯”），也使得他作为军队中的新鲜血液而在初期备受希特勒的看重，一路提拔至装甲集团的司令，但其始终不愿意参与政治的态度，又让希特勒总是难以完全以“自己人”来看待他，更何况在本书中能看得出古德里安是个对于自己的看法相当“固执”的人，这更让希特勒又爱又恨，需要他因为他有真知灼见，讨厌他因为其无法完全遵循自己的意志行事，这最终也让古德里安成为二战中德军唯一一位屡建军功但没能授勋元帅的集团军司令。&lt;/p&gt;

&lt;p&gt;受其父亲的影响，古德里安有着强烈的德意志传统军人的情节。比如他坚持认为指挥官应当身处前线与自己的士兵们同甘共苦，并掌握最真实的情报，你能看到他不厌其烦的描写其花费20个小时克服泥泞的道路与天气在多个部队的前线中辗转，不断的抱怨总参谋部的军官们从来不来前线视察，而仅仅凭借着臆想在做各种重大决策；再比如军人应当忠诚的服从命令而不过问政治，他对希特勒和他的纳粹党从来没有表现过任何兴趣，只有当这些政治关系可能会影响到军事决策的时候，他才会花些心思和精力去应对。&lt;/p&gt;

&lt;p&gt;书中对于战场中各个部队的动向与安排的描写事无巨细，对于普通读者来说稍显痛苦，但我想对于军事考证爱好者来说，可能就是如获至宝了，这本书和隆美尔的《战时文件》还有曼施坦因的《失去的胜利》被称为德国二战文献三大件。&lt;/p&gt;

&lt;p&gt;此外书中还有一些有趣的观点，比如我一直不能很理解的德国发动对苏战争的原因竟然是出于希特勒本人对于布尔什维克的仇恨以及他希望给已经被全面调动起来的德军“找点事情干”……（如此草率吗）&lt;/p&gt;

&lt;p&gt;书中最后一段对于希特勒的描写与人物分析非常非常精彩，包括古德里安眼中的希特勒，希特勒是如何一步步走上权力的巅峰，除了他自己的努力之外，又有着整个德国社会背景在推动着这一几乎是必然的走向，而在战争的后期，德国的最高决策层又是如何一步步走向了臣服于希特勒独断专行，并跟随这名赌徒一步步走向最终的毁灭。从古德里安的视角，我们不一定能获得全面客观的解读，但也是一份难得的第一手资料。&lt;/p&gt;

&lt;p&gt;读完整本书，给我最深的感受是，全面战争从来不是由个人英雄主义和将军高明战术的决定的，靠的还是国家的硬实力，在绝对的实力面前，任何技术都会显得渺小且无力。&lt;/p&gt;

&lt;p&gt;最后，从这本书中，能看得出古德里安对于战争的态度其实没有太多后悔的成分的，如果有，也主要是围绕在军事层面上的决策失误上的，书中没有任何对于战争给予他国人民带来的灾难的任何愧疚，而对于德国人民在战争末期所遭受苏军的蹂躏，他也认为是“为了德意志再次辉煌所必需承受的代价”，可以说他一切的心思与理想都是寄托在军队上的，发动战争的不是他，也不是德国军人的错误，军人的职责就是服从命令，并实现自己的光荣。&lt;/p&gt;

&lt;p&gt;豆瓣上对于这本书的短评中，有一条很有趣，甚至可以说一句话概括了整本书 —— 《如果当初听我的》（笑）&lt;/p&gt;

&lt;h1 id=&quot;笔记&quot;&gt;笔记&lt;/h1&gt;

&lt;p&gt;《闪击英雄：古德里安将军战争回忆录》
古德里安
23个笔记&lt;/p&gt;

&lt;h3 id=&quot;基辅会战&quot;&gt;基辅会战&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;而我们的军事领导既不亲自到前线来考察，又听不进我们的汇报。其结果必然是要付出沉重的代价，而我们所蒙受的巨大牺牲本来是可以避免的。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;奥廖尔和布良斯克会战&quot;&gt;奥廖尔和布良斯克会战&lt;/h3&gt;

&lt;p&gt;2023/10/05发表想法
语气上感觉古将军是个嘴硬的人哈&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;如果第34军级司令部的步兵能够早点到达也不致如此&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;当时我们只有在特别有利的条件下，才能有效地对付敌人的T34型坦克。我们的Ⅳ型坦克上的75毫米口径短射程火炮，只有从T-34坦克背后实施攻击时，才能穿透其防护板，击中发动机。可是要想在射程之内，找到一个合适的发射位置，确实需要高超的技巧。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;埃贝尔巴赫上校还是第一次露出精疲力竭的神情，他看上去与其说是体力上的困乏，还不如说是精神上的疲惫。看到我们这样最优秀的军官在近几日的紧张战斗中被拖累成这个样子，心中不免生出阵阵酸楚。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;大约八周以来，无论是部队的冬装，还是发动机的冷却水防冻剂的供应可以说是微乎其微。上述这种状况使士兵们在以后的数月里经受了巨大的困难和痛苦，而实际上这一切原本都是可以很容易避免的。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;集团军群是否仍有余力继续进攻，将战术性胜利扩大为战略性胜利，是国防军总司令部在此次战争中面临的最重大和最急迫的问题。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;1943年下半年的争论&quot;&gt;1943年下半年的争论&lt;/h3&gt;

&lt;p&gt;2023/10/06发表想法
老实说，自己说出来还是缺少些说服力的&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;使工人们心里感到暖烘烘的，彼此心灵达到了沟通。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;无疑，他看出了我脸上挂着几分嘲笑的神情，突然停住话头，默默地盯着我，然后说道：“还是您对了！您在九个月前就跟我说过这个事&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;2023/10/06发表想法
希特勒是个素食主义者，Are you fucking kidding me??&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;素食主义者&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;第十章-1944年7月20日事件及其后果&quot;&gt;第十章 1944年7月20日事件及其后果&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;我们敌人的最终目的，不仅仅是要消灭希特勒和纳粹主义，而是整个的德意志民族。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;被判死刑的人，命运固然悲惨，但没有死的人的处境也许更糟。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;第十一章-总参谋长&quot;&gt;第十一章 总参谋长&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;他命令克卢格立刻到元首大本营向他报告，但克卢格元帅却在半路上服毒自杀了。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;东线的防御准备&quot;&gt;东线的防御准备&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;敌人在东线的进攻一旦成功，我们的家乡势必沦陷，这里的居民必遭蹂躏。因为他们在戈乌达普和讷默斯多尔夫的作为已为我们展现了一幅恐怖的画面。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;俄军的突击&quot;&gt;俄军的突击&lt;/h3&gt;

&lt;p&gt;2023/10/07发表想法
想不到都要亡国了还这么搞，所以公司搞这一套也就没那么新鲜了&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;这种会议纯属聊天，唠叨些不关任何实际行动的空话。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;已经丧失作战能力的空军和海军代表的发言，真是对我精神和肉体的一种巨大折磨。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;2023/10/08发表想法
希特勒可能从始至终都没有找过自身的原因&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;我对这个固执己见的人语重心长地说道：“我一再向您提出撤出库尔兰，并不是因为我一定要和您争个高下。我觉得，现在我们除了从西线撤兵得到预备队之外，已经没有别的办法了，而没有预备队就不可能守住德国的首都。我提出这样的建议没有别的意思，只是表示我对德意志的忠诚！”希特勒听完这句话，气得整个左半身都在发抖，他暴跳如雷，大发脾气，对我吼道：“您怎么敢对我说这些话？您难道认为我不是为德意志而战吗？我一辈子都是在为德意志而奋斗！”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;眼前坐在我周围的这个小家庭，他们的幸福和毁灭与希特勒的命运紧紧联系在一起。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;2023/10/08发表想法
这就是赌徒的思路&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;没有必要考虑民族如何生存下去的问题。还不如我们自己把它毁掉。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;第十二章-最后的崩溃&quot;&gt;第十二章 最后的崩溃&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;傍晚时分，我才回到了措森。我的夫人正在迎候我，说道：“你今天回来晚得实在可怕！”我说：“这是最后一次了。我被解职了。”我们两个人拥抱在一起，如释重负。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;希特勒&quot;&gt;希特勒&lt;/h3&gt;

&lt;p&gt;2023/10/08发表想法
我的天，这话是怎么过审的！？&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;希特勒的原则是：“不是国家指挥党，而是党指挥国家！”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;2023/10/08发表想法
因为撤掉戈林就是否定自己，就是扇自己的大嘴巴&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;依然没有把他从对战争结局最具影响的空军职位上撤下来。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;如果问，是什么东西损害了民族社会主义和德国的伟大事业，那当属这种疯狂和愚蠢的民族政策。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;希特勒想统一欧洲，但是他对各民族间差异的蔑视，以及他采取的中央集权制的做法，注定了他失败的命运。&lt;/p&gt;
&lt;/blockquote&gt;

        </description>
        <pubDate>Sun, 22 Oct 2023 07:32:03 +0000</pubDate>
        <link>/2023/book-hero-of-blitz.html</link>
        <guid isPermaLink="true">/2023/book-hero-of-blitz.html</guid>
      </item>
    
      <item>
        <title>[书评] 重构：改善既有代码的设计</title>
        <description>
          
          &lt;p&gt;这本书最早在大约十年前曾经囫囵的读过一遍，但和当时差不多同一时期看的&amp;lt;模式识别&amp;gt;一样，都看的云里雾里的，前阵子又翻出来看了一遍，突然发现很多东西都能看明白了，甚至还能对书中的一些观点提出一些不同的理解了，看来真应了那句老话——纸上得来终觉浅，绝知此事要宫……要躬行啊，经验这个东西确认讲究一个厚重哈！&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2023/book-refactoring.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;这本书的核心思想可以总结为以下几点：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;重构是保证代码在开发过程中始终处于易于维护的状态的唯一手段&lt;/li&gt;
  &lt;li&gt;重构需要在开发过程中坚持不懈的进行&lt;/li&gt;
  &lt;li&gt;要记住代码首先是给人看的（请把自己也当个人看），其次才是给机器看的&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;不过这本书的思想中也有一个我认为略显偏激的部分，即作者认为所有代码都应该以可读性为优先，但在像游戏行业这种对性能要求很高的领域，我觉得重构的目标应该在某种程度上努力达到性能与可读性的一种平衡（极致的追求性能往往会牺牲可读性），我认为性能优化本身也应该包含为重构的一部分。&lt;/p&gt;

&lt;p&gt;总的来说这本书全面的阐述了重构的概念与思想，并总结汇列了日常开发中比较典型的需要进行重构的问题代码类型以及其对应的重构策略，几乎可以认为是一本软件工程开发人员必读的好书！&lt;/p&gt;

&lt;p&gt;PS1：重读完发现好像前两年出了更新的第二版，我这次真应该读第二版的……&lt;/p&gt;

&lt;p&gt;PS2：我把笔记部分也贴出来了，有些凌乱，不过有兴趣的朋友可以读读&lt;/p&gt;

&lt;h1 id=&quot;笔记&quot;&gt;笔记&lt;/h1&gt;

&lt;blockquote&gt;
  &lt;p&gt;最重要的一件事就是坚持以持续不断的重构行为来整理代码&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;我：&lt;strong&gt;作为开发者应该通过不断的调整，来让自己的代码始终保持在最佳状态中&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;重构就是再代码写好之后改进它的设计&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;第一章第一个重构案例&quot;&gt;第一章：第一个重构案例&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;每当我要进行重构的时候，第一个步骤永远相同：我&lt;strong&gt;得为即将修改的代码建立一组可靠的测试代码。而且这些测试还必须得自我检测能力。&lt;/strong&gt;（即测试可以帮你直接判断出结果的正确性，而不是输出测试内容，再人工复合正确性）&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;我：在心动小镇项目中重构ResManager的时候由于原本的逻辑就存在缺陷，因此只能在没有可靠测试环境的情况下进行重构，最终能顺利完成重构的结果现在看来无疑还是多少有些幸运的&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;重构技术就是以微小的步伐修改程序。如果你犯下错误，很容易便可发现它&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;更变变量名称是值得的行为吗？绝对值得！好的代码应该清楚表达出自己的功能，而变量名称是代码清晰的关键&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;我：实际工作中变量名应该也是常改常新（随着重构的进行而不断修改）&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;只有写出人类容易理解的代码，才是优秀的程序员。&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;我：作者在第一个重构实例中使用了”用接口来代替临时变量“的做法，在我看来这对于性能是有所损失的，为了极致追求可读性而损失性能这一点上可能还值得推敲&lt;/p&gt;

&lt;p&gt;我：构造函数中是不是没有必要也追求使用封装好的Set函数？？&lt;/p&gt;

&lt;h2 id=&quot;第二章重构原则&quot;&gt;第二章：重构原则&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;重构：对软件内部结构的一种调整，目的是在不改变软件可观察行为的前提下，提高其可理解性，降低其修改成本&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;我：&lt;strong&gt;如果书中提倡的重构是追求人的可阅读性，我则认为重构更重要的是维护好结构性（降低未来的修改成本）和性能，可读性相对来说则是稍稍可以妥协的&lt;/strong&gt;（相信继任者的一定代码阅读水平，保持正常水平即可）&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;重构的目的是使软件更容易被理解和修改&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;和重构一样，性能优化通常是不会改变组件的行为&lt;/strong&gt;（除了执行速度），只会改变其内部结构，&lt;strong&gt;但两者出发点不同，性能优化往往是代码较难理解。&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;两顶帽子：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;添加新功能时，你不应该修改既有代码，只管添加新功能&lt;/li&gt;
  &lt;li&gt;重构时你不能再添加功能，只管改进程序结构，此时你不应该添加任何测试&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;设计不良的程序往往需要更多代码，这常常是因为代码在不同的地方是用完全相同的语句做同样的事。因此改进设计的一个重要的方向就是消除重复代码。代码愈多，正确的修改就愈困难，因为有更多代码需要理解&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;很多人说重构是为了未来的程序员来接受相关的开发工作，但更多的时候那个未来的开发者就是我们自己，这样去想重构就显得尤其重要了。我是个懒惰的程序员，我的懒惰表现形式之一就是：总是记不住自己写过的代码&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;如果不对代码做些修改，也许我永远看不见它们，因为我的聪明才智不足以在脑子里把这一切都想象出来&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;要记住”磨刀不误砍柴工“！适当的重构绝对可以提高编程速度&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;重构本来就不是一件应该特别拨出时间做的事情，重构应该随时随地地进行，你不应该为了重构而重构&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;三次法则：当你三次做有件事并产生反感时，你就应该重构 —— &lt;strong&gt;事不过三，三则重构&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;”结对编程“的形式，把代码复审的积极性发挥到了极致&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;系统当下的行为，只是整个故事的一部分，如果没有认清这一点，你无法长期从事编程工作。如果你为求完成今天的任务而不择手段，导致不可能在明天完成明天的任务，那么最终还是会失败。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;我：&lt;strong&gt;但同时也不应该为了明日的任务，而在今天采用过度设计&lt;/strong&gt;！&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;很多经理嘴巴上说自己”质量驱动”，其实更多是”进度驱动”，对此争议的建议是：不要告诉经理！&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;间接层是一把双刃剑，会让程序难以阅读；而好处是允许逻辑共享并可以分离意图与实现。&lt;/strong&gt;有一种比较少见的重构游戏：找出不值得间接层，并将它拿掉&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;学习一种可以&lt;strong&gt;大幅提高生产力的新技术时，往往难以察觉其不适用的场合&lt;/strong&gt;。新技术的展示项目往往只是个别情景，这种情况你很难看出什么会造成这种新技术成效不彰或者形成危害（ECS刚刚流行的时候我就是这种感觉）&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;对于修改接口，重构时需要特别谨慎，尤其是已经发布的接口，这意味着你需要同时维护新旧两个接口，直到所有用户都有时间对这个变化做出反应&lt;/p&gt;

&lt;p&gt;何时不该重构：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;有时候既有代码实在太混乱了，重构还不如重新写一个来得简单。做出这种决定很困难。&lt;strong&gt;重写（而非重构）的一个清楚讯号就是：现有代码根本不能正常运行！&lt;/strong&gt;（与ResManager何其相似！）&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;未完成的重构工作就像是”债务”。很多公司都需要借债来使自己更有效地运转。但是借债就需要付利息，过于复杂的代码所造成的维护和扩展的额外成本就是利息&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;思考 -&amp;gt; 设计 -&amp;gt; 编码 -&amp;gt; 重构&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;不一定要在一开始就找到”最正确”的解决方案，此刻的你只需要得到一个足够合理的方案就够了，因为在实现初始方案的时候，你对问题的理解也会逐渐加深，这时就是重构发挥功效的时候&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;重构让日后的修改成本不在高昂&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;当下只管建造可运行的最简化系统，至于灵活而复杂的设计，唔，多数时候你都不会需要它（不要过度设计）&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;哪怕你完全了解系统，也请实际测试它的性能，不要臆测&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;我并不赞成为了提高设计的纯洁性而忽视性能，把希望寄托于更快的硬件身上也绝非正道&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;我：作者提到了书中重构的思想是”&lt;strong&gt;除了一些对性能有严格要求的实时系统&lt;/strong&gt;“（很不幸游戏开发即在此列中），所以游戏开发者，可能需要&lt;strong&gt;对重构的尺度稍微做一些调整&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&quot;第三章代码的坏味道&quot;&gt;第三章：代码的坏味道&lt;/h2&gt;

&lt;p&gt;一些典型的”坏”代码：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;重复代码&lt;/li&gt;
  &lt;li&gt;过长的函数
    &lt;ul&gt;
      &lt;li&gt;早期的编程语言中，子程序调用需要额外的开销，但&lt;strong&gt;现代OO语言几乎已经免除了进程内的函数调用开销&lt;/strong&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;过大的类&lt;/li&gt;
  &lt;li&gt;过长的参数列表&lt;/li&gt;
  &lt;li&gt;发散式变化
    &lt;ul&gt;
      &lt;li&gt;如果某个类经常因为不同的原因在不同的方向上发生变化，就是发散式变化&lt;/li&gt;
      &lt;li&gt;此时也许将对象拆分为两个会更好&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;霰弹式修改
    &lt;ul&gt;
      &lt;li&gt;如果你每次改动，都必须在许多不同的类内做许多小修改，就是霰弹式修改&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;依恋情结
    &lt;ul&gt;
      &lt;li&gt;函数对某个类的兴趣高于自己所处类的兴趣（通常是数据）&lt;/li&gt;
      &lt;li&gt;解决思路是移动函数至其更适合的位置&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;数据泥团
    &lt;ul&gt;
      &lt;li&gt;总在一起出现的数据应该拥有属于它们自己的对象&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;基本类型偏执
    &lt;ul&gt;
      &lt;li&gt;（作者鼓励使用对象来代替基础类型数据，这样对性能的损伤相比可读性的提升要更大吧？）&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Switch现身
    &lt;ul&gt;
      &lt;li&gt;（作者鼓励使用多态来代替Switch，又是一种牺牲来换取可读性的方案，但我并不觉得多态会比Switch更具有可读性）&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;平行继承体系
    &lt;ul&gt;
      &lt;li&gt;每当你为某个类添加一个子类，就必须为另一个类相应的增加一个子类的情况&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;冗赘类
    &lt;ul&gt;
      &lt;li&gt;在开发和重构的过程中逐渐失去其原本作用的类（应当被果断消灭）&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;夸夸其谈未来性
    &lt;ul&gt;
      &lt;li&gt;不提前为”未来”进行实现&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;令人迷惑的暂时字段
    &lt;ul&gt;
      &lt;li&gt;仅为特定情况而设置的临时对象&lt;/li&gt;
      &lt;li&gt;需要通过Extract Class来将相关代码提取&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;过度耦合的消息链 / 中间人
    &lt;ul&gt;
      &lt;li&gt;不要有”中间商”赚”差价”——尽量减少事件传递中不必要的路径&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;不合适的”亲密”
    &lt;ul&gt;
      &lt;li&gt;两个类直接的对象过分的互相使用&lt;/li&gt;
      &lt;li&gt;通过Extract Class / Move Method来”斩断”其中一方对另一方的依赖&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;异曲同工
    &lt;ul&gt;
      &lt;li&gt;相同的函数功能，不同的接口名称&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;未完成的类&lt;/li&gt;
  &lt;li&gt;纯粹的数据类
    &lt;ul&gt;
      &lt;li&gt;需要随时调整数据类对外暴露的访问接口&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;被拒绝的馈赠
    &lt;ul&gt;
      &lt;li&gt;父类中有子类并不需要的数据和接口（不想继承）&lt;/li&gt;
      &lt;li&gt;这通常意味着继承体系上的设计错误&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;过多的注释
    &lt;ul&gt;
      &lt;li&gt;注释过多通常是因为代码很糟糕（笑）&lt;/li&gt;
      &lt;li&gt;当你感觉需要撰写注释时，请先尝试重构，试着让所有的注释都变得多余&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;第四章构筑测试体系&quot;&gt;第四章：构筑测试体系&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;编写优良的测试程序，可以极大地提高编程速度&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;每个程序员都能讲出花一整天（甚至更多）时间只为找出一个小问题的故事&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;每个类都应该包含它们自己的测试代码&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;编写测试代码时，我往往一开始先让它们失败，是为了向自己证明：测试机制的确可以运行&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;功能测试的主要目的则是用来保证软件能够正常运作，功能测试尽可能把整个系统当作一个黑箱&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;进行重构时，单元测试是我们的好朋友&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;测试的要诀是：测试你最担心出错的部分。测试的一项重要技巧就是”寻找边界条件”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;当测试数量达到一定程度之后，继续增加测试带来的效益就会呈现递减态势&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;第五章重构列表&quot;&gt;第五章：重构列表&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;对于强类型的编程语言中，你往往可以直接删除旧部分，让编译器来帮你找出因此而被悬挂起来的引用点（Rider等现代IDE可以帮我们完成这个工作）&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;编译器无法找到通过反射机制而得到的引用点，这也是我们应该小心使用反射的原因之一&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;在单进程软件中，你永远不必操心多么频繁地调用某个函数，因为成本足够低；但在分布式软件中，函数的往返必须被减至最低限度&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;第六章重新组织函数&quot;&gt;第六章：重新组织函数&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Extract Method&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;将过长的函数中部分值得复用的部分提取为单独的函数&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;每个函数的粒度都很小，那么函数被复用的机会就更大；此外，这也使得高层函数读起来象是一系列注释；最后，函数的腹泻也会变得更容易&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;关键在于函数名称和函数本题之间的语义距离（如果判定函数长度是否合适）&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;2. Inline Method / Temp&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;将不必要的函数调用或临时变量声明直接展开放入函数中 / 如果临时变量妨碍到其他的重构，可以对其进行内联化（如果要方便调试的话，则不应该内联化）&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;间接层有其价值，但不是所有的间接层都有价值&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;3. Replace Temp with Query&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;使用接口来代替局部变量的赋值与使用，潜在以牺牲性能为代价，&lt;strong&gt;我不是很赞同&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;此外在我的经验中，如果大量编写get这种小函数，实际上会对代码的可读性逐渐产生负面的效果&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Split Temporary Variable&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;局部变量尽量不要一心二用。针对每次赋值，创造一个独立、对应的临时变量&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;同一个临时变量承担两件不同的事情，会令代码阅读者糊涂&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;5. Remove Assignments to Parameters&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;不要对函数的参数进行赋值（主要当作常量使用，按引用传递的话应当做return来处理）&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Replace Method with method Object&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;将函数中用到的局部变量也封装为对象，&lt;strong&gt;对于这类通过引入新的类型或增加成员变量来换取可读性的方法军不是很赞成&lt;/strong&gt;。&lt;/p&gt;

&lt;h2 id=&quot;第章在对象之间搬移特性&quot;&gt;第章：在对象之间搬移特性&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Move Method / Field&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;如果一个类中的方法/变量主要被另一个使用，那么应该移动至更”亲近”的类中&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Extract / Inline Class&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;如果部分成员变量具有共同的逻辑特性，那么就应该被提取至单独的类中；反之则应该融合至同一个类中&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Hide Delegate / Remove Middle Man&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;通过添加新的接口来隐藏委托调用，或去除中间接口/类来进行直接调用（去除委托）&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Introduce Foreign Method&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;如果你使用的对象中缺少部分函数功能，而你又无法修改（第三方库），则可以通过外加函数（全局或静态）来实现，但如果你需要大量的外加函数，则说明应该使用”Introduce Local Extension”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Introduce Local Extension&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;对第三方的库中的类进行封装，来实现功能的扩展或者希望的接口上的修改&lt;/p&gt;

&lt;h2 id=&quot;第七章重新组织数据&quot;&gt;第七章：重新组织数据&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Self Encapsulate Field&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;全部是用Get/Set函数来对成员变量进行访问（好处我能理解，即在未来出现问题时非常方便调试，但是感觉写起来就很繁琐）&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;此外的好处还有子类中可以仅通过覆写一个函数就做到改变获取数据的途径，也支持延迟初始化等（只有在需要用到某值时才对其进行初始化）&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;直接访问变量的好处是：代码比较容易阅读&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;我比较喜欢先使用直接访问方式，知道这种方式给我来麻烦为止，此时我就会转而使用间接访问方式&lt;/strong&gt;。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;2. Replace Data Value with Object&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;鼓励对每一个成员变量进行类封装吗？？好家伙，疯了吧……不认同，不认同&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Change Value to Reference, Vice versa&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;如果一个类衍生出许多彼此相等的实例，则希望通过引用来保证他们均指向同一个对象（&lt;strong&gt;尽可能保证数据的单一同源性&lt;/strong&gt;）&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;如果当引用对象开始变得难以使用时，则应该将其改为值对象&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;4. Replace Array with Object&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;对于数组中元素各自代表不同东西的情况，应该使用类来进行替换，用不同的字段来表示&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;5. Duplicate Observed Data&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;将GUI控件中的数据复制到领域对象中，建立一个Observer模式（大概就是MVC那套吧）&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;你不能仅仅只是移动数据，必须将它复制到新的对象中，并提供相应的同步机制&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;6. Change Unidirectional Association to Bidirectional, Vice versa&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;当两个类都需要使用对方特性，但期间只有一条单向链接。则应添加一个反向指针，并使修改函数能够同时更新两条连接（有点像AssetRequest和BundleRequest）&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;反之当一个类不再需要另一个类的特性时，则可以去掉不必要的关联&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;7. Replace Magic Number with Symbolic Constant&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;魔法数字应该使用常量来表示&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;8. Encapsulate Filed&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;其实和第1条说的是同一件事，将public字段改为private，并提供get函数&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;9. Encapsulate Collection&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;对于类中的集合对象，于其提供对象本身的引用，更应该提供接口的封装（收敛功能权限）&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;10. Replace Recode with Data Class&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;鼓励使用数据类来代替Struct，并提供get接口来访问&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;11. Replace Type Code with Class / Subclasses / State&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;和第2条非常类似，但是针对Type Code类似的数据；使用Subclass的方式实际上是利用多态来代替分支语句；使用State模式或Strategy模式来实现（通过Switch语句来创建不同的子类）
&lt;strong&gt;12. Replace Subclass with Fields&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;如果情况足够简单，则可以将多态改回分支&lt;/p&gt;

&lt;h2 id=&quot;第八章简化条件表达式&quot;&gt;第八章：简化条件表达式&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Decompose Conditional&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;将if语句中较复杂的判别式，提取为单独的函数&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Consolidate Conditional Expression&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;将多个结果相同的条件判别式，合并成一个（但我觉得大部分情况下还是不合并的好，因为总会需要频繁改动）&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Consolidate Duplicate Conditional Fragments&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;将条件分支中重复的代码搬移到条件表达式外&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Remove Control Flag&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;使用break或者return语句来代替控制标记&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Replace Nested Conditional with Guard Clausese&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;尽量避免使用重复嵌套较深的条件语句，使用平铺的方式来表达（翻译为卫语句？）&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Replace Conditioanl with Polymorphism&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;这不又是上一章中的的第11条吗？看到这里已经感觉到这本书中还是存在大量雷同的内容了……&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. Introduce Null Object&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;在继承体系中引入Null Object类，可以改善你代码中需要大量重复判断null的情况&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;8. Introduce Assertion&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;当某一段代码需要对程序状态做出某种假设时，可以使用断言来明确表现这种假设&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;使用断言时，只有条件为真时，代码才能正常运行。因此断言的失败应该导致一个非受控异常。断言绝不能被系统的其他部分使用。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;实际上，程序最后的成品往往将断言统统删除。因此，标记”某些东西是个断言”是很重要的&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;第九章简化函数调用&quot;&gt;第九章：简化函数调用&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;我有一个坚守的很有价值的习惯：明确地将”修改对象状态”的函数（修改函数）和”查询对象状态”的函数（查询函数）分开设计。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;1. Rename Method&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;名字起的不合适的情况&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;记住，你的代码首先是为人写的，其次才是为计算机写的。而人需要良好名称的函数。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;2. Add / Remove Parameter&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;过长的参数列是不好的味道&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;程序员可能经常添加参数，却往往不愿意去掉它们。他们打的如意算盘是：无论如何，多余的参数不会引起任何问题，而且以后还可能用得上它&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;3. Separate Query from Modifier&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;将查询函数和修改函数分离&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;如果你在一个多线程系统中工作，肯定知道这样一个重要的惯用手法：在同一个动作中完成检查和赋值&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;4. Parameterize Method&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;例如将fivePercentRaise()和tenPercentRaise()合并为raise(percentage)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Replace Parameter with Explicit Method&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;将setValue(width, height)拆分成setWidth()和setHeight()&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Preserve Whole Object&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;将需要从同一对象中访问的多个属性值，封装成统一的对象来返回（连作者都说这条具有两面性）&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. Replace Parameter with Methods&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;通过函数内部调用其他函数的方式来减少传递的参数的数量&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;8. Introduce Parameter Object&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;上一条思想的延续，通过将多个参数合并为新的类对象来减少传递参数的数量&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;9. Remove Setting Method&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;有些人甚至会在构造函数中使用设值函数！（那么构造函数中是否建议调用Init()函数来完成初始化）&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;10. Hide Method&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;对于外部不会调用的函数应当修改为private&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;11. Replace Constructor with Factory Method&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;通过工厂函数来创建对象，例如：（好处主要是可以集中管理Code Type的逻辑）&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Employee(int type) { _type = type; }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;改为：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;static Employee create(int type) { return new Employee(type); }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;12. Encapsulate Downcast&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;将类型转换（Casting）的动作移到函数中，你不应该要求用户来承担Casting的工作，应该由接口提供准确的数据类型&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;13. Replace Error Code with Exception&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;异常是语言级别的错误（崩溃）处理机制，它可以让错误分析变得更加容易，但并不能消除错误（崩溃）&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;异常，这种方式之所以更好，因为它清楚地将”普通程序”和”错误处理”分开了&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;使用错误码的缺点是不便于理解&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;14. Replace Exception with Test&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;异常应该只用于异常的、罕见的行为，也就是那些产生意料之外的错误的行为，而不应该成为条件检查的代替品&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;第十章处理概括关系&quot;&gt;第十章：处理概括关系&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Pull Up Field / Method&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;如果子类中的多个字段/函数使用方式相似，那么他就应当被归纳到超类中&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;2. Pull Up Constructor Body&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;字段的初始化应当尽量在超类中完成，子类通过调用超类的构造函数来完成对应字段的初始化&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Push Down Field / Method&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;当超类中的字段/方法只是为某一个子类实现的，那么它应当移至对应的子类中&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Extract Subclass&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;如果类中的某些特性只被某些（并非全部）实例用到，那么应当将这部分特性移至子类中&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Extract Superclass&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;和第1条思想相同（又是在凑字数……）&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Extract Interface&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;不同的类中相同的逻辑最好通过接口的方式来组织&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. Collapse Hierarchy&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;子类和超类区别不大时，可以合并在一起&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;8. Form TemPlate Method&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;将子类直接一些存在区别的操作分别放进独立的函数中，并保持相同的签名，在原函数变得相同后，上移至超类&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;将子类中不同的实现提取至专门的接口中，核心目标是尽可能减少重复代码&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;9. Replace Inheritance with Delegation, Vice versa&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;使用组合代替继承！（这个我强烈赞同）&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;如果实际上还是使用到了受托类的所有函数，那么就还是应该使用继承来代替委托方式（组合）（只要没有使用到所有函数，那么还是倾向于使用组合）&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;第十一章大型重构&quot;&gt;第十一章：大型重构&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;你不可能说服精力把系统停止运行两个月来让你进行重构。你只能一点一点地作你的工作，今天一点点，明天一点点&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;整个团队都必须意识到：有一个大型的重构正在进行，每个人都应该相应的安排自己的行动。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;只有持续而无处不在的重构才能有可能竟其功&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;四个大型重构：&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Tease Apart Inheritance：梳理并分解继承体系&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;某个继承体系同时承担了两项责任，则应该分别建立独立继承体系，并通过组合的方式来实现互相调用&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;AssetRequest和BundleRequest就是活生生的例子&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Convert Procedural Design to Objects&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;将过程化设计转化为对象设计&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;作者是明显倾向于对象化实现的，但实际上在游戏开发中，很多功能比较单一的模块中处于性能的考虑是会更倾向于过程化的实现风格的！&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Separate Domain from Presentation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;MVC那一套，把领域逻辑从GUI类中分离出来（这个不是再前面已经讲过了吗？？严重凑字数！）&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;MVC模式最核心的价值在于：它将用户界面代码（GUI）和领域逻辑（即模型）分离了&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;4. Extract Hierarchy&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;当你的类做了太多工作，其中一部分工作是以大量条件表达式完成的，则应该为其建立对应的继承体系&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;第十二章重构复用与现实&quot;&gt;第十二章：重构、复用与现实&lt;/h2&gt;

&lt;p&gt;综合的总结性讨论，这一章大概读读就好&lt;/p&gt;

&lt;h2 id=&quot;第十三章重构工具&quot;&gt;第十三章：重构工具&lt;/h2&gt;

&lt;p&gt;安利作者开发的Smalltalk语言的重构工具，不太适用于绝大多数开发者……&lt;/p&gt;

        </description>
        <pubDate>Fri, 06 Oct 2023 05:05:10 +0000</pubDate>
        <link>/2023/book-refactoring.html</link>
        <guid isPermaLink="true">/2023/book-refactoring.html</guid>
      </item>
    
      <item>
        <title>23年秋国庆上海一日游</title>
        <description>
          
          &lt;p&gt;因为9月份刚刚去过杭州玩，也实在不想去和别人挤什么景点，因此今年国庆又是一个没有安排任何出行计划的长假，最后只是很敷衍的安排了一天的市内游，而且前一天睡得很晚，早上起来困意十足，去市中心的话开车又不划算，只能坐地铁，内心实在是一千个不愿意，可看看窗外天气倒是真的不错，又找不出什么理由耍赖，只好强打起精神，出门！&lt;/p&gt;

&lt;p&gt;上午先直奔新天地一大会址，给笑笑完成老师布置的“一大会址合影”的国庆家庭作业……&lt;/p&gt;

&lt;p&gt;一看已经差不多午饭时间了（出来的实在太磨蹭了哈哈），既然来了新天地，那就还是去吃心心念念的哈比特汉堡吧！自从南陈路店关店之后（没能熬过疫情），想吃到这口儿就不那么容易了。另外现在笑笑又大了一些，从这顿开始以后我们仨人得买三个汉堡了。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2023/20231002_114454_哈比特汉堡.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;你别说一口咬下去，还是那么的满足。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2023/20231002_121702_笑笑和妈妈.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;吃完饭才就地安排一下下午的行程，一搜似乎附近值得逛逛的地方还不少，先去了附近的恒基·旭辉天地逛了逛，这个商场的装修风格很像是电影千与千寻的调调，这边还有一家二酉书店，装修的很有腔调，与其说是书店更像是个书吧。如果一个人有时间又在附近的话，过来点一杯喝的看看书，应该是个愉快的体验，这书店还有一间小书房，让人印象深刻，不过不像是对外的，可能是老板自己用的。于是关于老板开这个书店究竟挣不挣钱我们又展开了一番讨论。我猜可能不是为了挣钱，更像是老板财富自由以后，开个自己真心喜欢的店玩玩吧。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2023/20231003_134550_旭辉天地.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;天公作美，不冷不热，还有让人倍感幸福的阳光和微风，心情好了起来，按我老婆的话说：“现在不是早上嘟着大脸的样子了哈”。&lt;/p&gt;

&lt;p&gt;之后又走了很多路，逛了思南公馆和思南书局，旅游季的关系这边到处都是人，体验不算很好，之后在复兴公园略作休整，其实到现在也才出门三个小时左右，现在的体力还真的是不给力啊！公园里老人居多，但不管老幼，能看得出在这样一个可爱宜人的日子里大家都是幸福开心的心情。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2023/20231002_134424_复兴公园.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;本来还想参观下孙中山故居的，但是队伍已经排满了买票需要等一个多小时，只好作罢，又去逛了思南书局·诗歌店和香港三联书店，这个思南书局似乎和上海中心那个云朵书店是同一家的，都看着不像是正经卖书的，装修的倒是很漂亮，只是书实在是没摆多少本……&lt;/p&gt;

&lt;p&gt;西西弗书店看起来是目前我比较喜欢的书店了，在装逼与务实上似乎是一个平衡点。&lt;/p&gt;

&lt;p&gt;要说这思南公馆这附近有很多名人故居，很多都是民国时期的政府要员，比如孔祥熙的故居现在被改成了一家饭店，离孙中山故居大概100米，走两个路口就到，想想当年会不会这么个画风？——国父吃完饭门口溜溜弯，一出门就碰上孔祥熙，“老孙，吃了没？没吃来家吃嗨，今儿家里做炸酱面~！”&lt;/p&gt;

&lt;p&gt;坐公交车又来到了附近的武康大厦，People Mountain People Sea，以至于比起拍摄武康大厦，我似乎更想拍那些拍摄武康大厦的人们（可惜摄影水平有限，尝试了几个角度也没能拍出我想要的效果），楼下还有一家“大隐隐于市”书店，本来也想顺便逛逛的，但是大门都要挤才能进得去，看来这书店隐于世隐得很失败呢（笑）&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2023/20231003_134734_武康大楼.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;武康大楼对面是宋庆龄故居，一日同游这两口子的故居，我大脑中第一反应是“这两口子感情不咋地啊，分居了不说，家还离得这么远，哈哈”。&lt;/p&gt;

&lt;p&gt;一路向西，渐渐脱离了游客队列，走回到了法华镇路上，又让我的思绪不由得回到了Red Accent的时光。&lt;/p&gt;

&lt;p&gt;晚上本来准备带娘儿俩去尝尝沪西老弄堂，或者就在路边的露天西餐馆小资一下，结果最后阴差阳错一路降级变成了兰州拉面（沪西老弄堂现在是网红店了，人可太多了，排队估计得1+小时）&lt;/p&gt;

&lt;p&gt;今天老婆问了我一句：“是不是我们应该趁着前几年年轻的时候多出来转转”。我其实脑子里想的是，像今天就这么逛逛也很好啊，多少年以后，看看老照片，回想起今天，应该也会羡慕现在的情绪和青春的。&lt;/p&gt;

        </description>
        <pubDate>Mon, 02 Oct 2023 11:58:13 +0000</pubDate>
        <link>/2023/shanghai-one-day-trip.html</link>
        <guid isPermaLink="true">/2023/shanghai-one-day-trip.html</guid>
      </item>
    
      <item>
        <title>告别WordPress，你好Jekyll</title>
        <description>
          
          &lt;p&gt;如同当年将博客系统从&lt;a href=&quot;https://www.ownself.org/2012/gao-bie-bo-blog.html&quot;&gt;Bo-Blog&lt;/a&gt;迁移至WordPress一样，最近终于下定决心再次将博客从WordPress更换到目前更“先进”更顺应潮流的静态博客系统上，目前选择的是Github Pages官方比较推荐的Jekyll。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2023/github-pages-jekyll.png&quot; alt=&quot;Jekyll-GithubPages&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;起因&quot;&gt;起因&lt;/h1&gt;

&lt;p&gt;最早在几年前看到&lt;a href=&quot;https://onevcat.com/&quot;&gt;OneV’s Den&lt;/a&gt;的博客从WordPress迁移到Jekyll时就已经产生了这个想法，当时就对这个Jekyll的访问速度和简洁的风格印象深刻，更觉得可以把博客直接免费托管在Github上感到惊奇（Github真大方），但因为那几年孩子的出生以及工作上的繁忙，就一直被拖着。直到上个月读一篇技术博客时，看到作者也在使用了11年WordPress后，下定决心切换为Hugo后（&lt;a href=&quot;https://therealmjp.github.io/posts/hello-hugo/&quot;&gt;Hello, Hugo&lt;/a&gt;），才又燃起了我折腾一番的动力。于是我汇列了一下更换的优缺点：&lt;/p&gt;

&lt;p&gt;优点&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;可以将博客托管至Github Pages，暂时每年不再需要缴服务器空间费了&lt;/li&gt;
  &lt;li&gt;目前托管的服务器太烂了，速度和空间容量不说，PHP版本都是不给升级一下（便宜没好货）&lt;/li&gt;
  &lt;li&gt;我真的太喜欢Markdown了（这才是决定性的理由！）&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;缺点&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;迁移博客需要时间和学习成本（事后来看正好一周的时间，过程其实还是充满乐趣的）&lt;/li&gt;
  &lt;li&gt;托管至Github Pages以后可能会有国内访问上的限制与风险（目前还OK）&lt;/li&gt;
  &lt;li&gt;Jekyll很多配套的功能比较有限，插件社区也没办法与WordPress相比，可能需要更多的在自己并不熟悉的HTML+JS的代码上投入精力&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;此外，我还对比了目前流行的静态博客框架，虽然Hugo有着构建速度更快的性能优势，但是似乎也有着明显更高的学习曲线。因此最后还是保守的选择了Github Pages官方推荐的Jekyll。&lt;/p&gt;

&lt;h1 id=&quot;过程&quot;&gt;过程&lt;/h1&gt;

&lt;p&gt;有了想法后当天就在本地先试了试安装环境与部署测试，参考Jekyll的官方文档就好，本地环境的安装就需要占用你接近1GB的空间（这上来第一点上就显得有点劝退了，改动和调试可能以后需要在固定的设备上进行了），之后又参照着Github Pages的文档，将测试的站点推到了https://ownself.github.io上，第一步比想象中的要顺利。&lt;/p&gt;

&lt;p&gt;既然开了头，从第二天开始上班时候，就开始心里长草了，加上最近工作上没那么紧张，于是利用早晨早到公司的那一个多小时里就开始继续折腾了起来，连着用了几天，一步步完成了：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;使用官方推荐的WordPress插件将老博客的文章导出为Jekyll的格式&lt;/li&gt;
  &lt;li&gt;测试并选定评论的功能插件：&lt;a href=&quot;https://utteranc.es/&quot;&gt;utterances&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;修复文章的Tags&lt;/li&gt;
  &lt;li&gt;选定第一版准备使用的主题&lt;a href=&quot;https://github.com/daattali/beautiful-jekyll&quot;&gt;beautiful-jekyll&lt;/a&gt;的安装与测试&lt;/li&gt;
  &lt;li&gt;利用插件Jekyll-Paginate实现主页的分页功能（官方程序竟然没有提供，这个坑了我差不多半天的时间）&lt;/li&gt;
  &lt;li&gt;修复老文章中的格式问题&lt;/li&gt;
  &lt;li&gt;编写Python脚本来导出老博客中的评论到utterances中&lt;/li&gt;
  &lt;li&gt;修复所有文章链接问题&lt;/li&gt;
  &lt;li&gt;域名指向（到这里就算是正式迁移了）&lt;/li&gt;
  &lt;li&gt;启用Google Analytics（代替之前的Jetpack）&lt;/li&gt;
  &lt;li&gt;编写Python脚本修复所有的贴图链接&lt;/li&gt;
  &lt;li&gt;删除冗余的WordPress自动生成的缩略图（发现有时候WordPress自动生成的缩略图比我的原图还大……）&lt;/li&gt;
  &lt;li&gt;实现RSS全文输出，并通过跳转修复老的RSS地址&lt;/li&gt;
  &lt;li&gt;实现博客的全文搜索功能&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Github Pages似乎不支持subpath，但是老博客是带着”/blog/”的subpath的，最后决定不再使用”/blog/”了，为了修复已经存在的老文章的链接地址失效的问题，又编写了Python脚本自动生成了所有老链接地址的自动跳转页面。&lt;/p&gt;

&lt;p&gt;Beautiful-Jekyll主题实现了一个快速搜索标题的功能，但阅读了代码发现它是通过在每一个页面上内嵌所有文章的meta信息来实现的，这实在是个非常不环保非常浪费性能的实现，于是我魔改了主题的代码，摘去了这部分内嵌逻辑并把全文搜索（要求的Json格式中不能包含&amp;amp;字符这一点也坑了我将近半天的时间）实现在了专门的搜索页面上。&lt;/p&gt;

&lt;h1 id=&quot;总结&quot;&gt;总结&lt;/h1&gt;

&lt;p&gt;总的算起来前后花了差不多一周的业余时间，完成了博客的迁移，也顺便提醒我今后还是应该尽力多分一些精力，多写一点东西，对我来说，其实写东西的核心并不为给别人看，更多是写给自己的，一份思考与一份总结，无论是生活上的还是工作中的。&lt;/p&gt;

&lt;p&gt;PS：意外发现&lt;a href=&quot;https://bo-blog.com/&quot;&gt;Bo-Blog&lt;/a&gt;的站点还在维持，并且还可以下载到当年使用的程序，还附了一首充满感情的小诗，要知道Bo-Blog v2.1可是15年前的产物了，我想作者对它的情怀由此可见。&lt;/p&gt;


        </description>
        <pubDate>Sun, 01 Oct 2023 08:24:35 +0000</pubDate>
        <link>/2023/jekyll-immigrated.html</link>
        <guid isPermaLink="true">/2023/jekyll-immigrated.html</guid>
      </item>
    
      <item>
        <title>Unity项目Android平台内存分析</title>
        <description>
          
          &lt;h1 id=&quot;概述&quot;&gt;概述&lt;/h1&gt;

&lt;p&gt;现代操作系统的内存分配机制越来越复杂，分页、交换等机制的引入使得我们想要精确的了解我们编写的程序所使用的真实内存用量这件事情变得越来越不可能，而游戏开发中内存用量又是非常重要的性能标准。在本文中，我尝试将过往工作中一些在Unity项目中在安卓平台上分析内存的方法总结在这里。&lt;/p&gt;

&lt;h1 id=&quot;adb&quot;&gt;ADB&lt;/h1&gt;

&lt;p&gt;ADB是Linux提供系统级的工具，功能丰富且强大，其中对于内存分析我们常用的有如下几个。&lt;/p&gt;

&lt;h3 id=&quot;adb-shell-dumpsys-meminfo-application-id&quot;&gt;adb shell dumpsys meminfo [application id]&lt;/h3&gt;

&lt;p&gt;adb中最常用也是最主要的内存分析工具，其会输出应用程序关于内存总体及在各个类别的统计数据，并输出类似如下格式的信息：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;App Summary
                       Pss(KB)                        Rss(KB)
                        ------                         ------
           Java Heap:    11264                          26080
         Native Heap:   246716                         248732
                Code:    81256                         188528
               Stack:     2652                           2664
            Graphics:   214416                         214416
       Private Other:   588276
              System:    12874
             Unknown:                                  591972

           TOTAL PSS:  1157454            TOTAL RSS:  1272392       TOTAL SWAP PSS:       27
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;其中我们可以通过下面的App Summary的信息段来了解应用程序的内存不同部分的用量：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Java Heap&lt;/strong&gt;：Java相关代码的内存分配，在Unity项目中，这部分用量通常不大。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Native Heap&lt;/strong&gt;：C/C++代码中直接通过malloc分配的内存，在Unity项目中由于Unity底层的内存分配主要使用VirtualAlloc的方式，所以绝大部分会归类到Unknown类别中，因此这部分内存通常也不应过大，主要包含Mono或者il2cpp的虚拟机，部分图形API的驱动内存分配，以及项目中一些第三方Native Plugin也会造成一些这部分的潜在内存分配。&lt;strong&gt;这部分的内存用量可以通过Google提供Perfetto工具来进行抓取和分析&lt;/strong&gt; （&lt;a href=&quot;https://perfetto.dev/&quot;&gt;Perfetto&lt;/a&gt;） ，但要注意的是Perfetto工具目前支持的机型还相对比较有限。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Code&lt;/strong&gt;：映射的so/jar/apk/dex/oat/art等代码文件所占用的内存，在Unity项目中这部分代码&lt;strong&gt;最主要的用量来自libunity.so和libil2cpp.so两个文件&lt;/strong&gt;。需要注意的Android系统的工作机制是逐渐读取代码文件，只有在需要使用发现缺页时才会去实际分配并载入文件中相关部分，而且随着系统内存的整体情况的变化，这部分内存也最有可能会Swap-out出去。此外要注意PSS与RSS内存统计在这个类别中也是区别最大的，其中&lt;strong&gt;RSS内存会将程序所使用到的系统级的代码文件计算在内&lt;/strong&gt;，而这部分文件又通常由许多应用程序所共享的，&lt;strong&gt;PSS数据则会将共享的部分按照所涉及的应用程序数据所平分&lt;/strong&gt;，对于我们的内存分析来说，这部分&lt;strong&gt;更准确的数据应该参考Private Dirty + Clean&lt;/strong&gt;。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Graphics&lt;/strong&gt;：GPU部分的内存用量，在Unity的项目中，Mesh数据和Texture的数据应属于这部分类别。在我们的观测中，发现&lt;strong&gt;部分个别设备会出现关于这个类别的统计偏差&lt;/strong&gt;，其会将本属于该类别的内存归类到Unknown中。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Unknown&lt;/strong&gt;：adb将内存中所有匿名申请及无法溯源的内存归类于此，这也是Unity引擎中内存分配的主要来源，&lt;strong&gt;包括了Unity引擎中绝大多数C++的内存分配和C#的Managed Heap的内存分配&lt;/strong&gt;，以及一些来自第三方Native Plugin的内存分配，例如Wwise。&lt;strong&gt;这部分的内存我们可以主要通过Unity Memory Profiler来进行分析&lt;/strong&gt;。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;adb-shell-cat-procpidstatm&quot;&gt;adb shell cat /proc/[pid]/statm&lt;/h3&gt;

&lt;p&gt;该命令会打印出与应用程序相关的内存页的用量，其会输出7个数字，分别代表：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Size : 程序虚拟空间的完整大小&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Resident：程序实际正在使用的物理内存的大小&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;Shared：Resident中共享内存页数（例如存在文件备份的内存页）&lt;/li&gt;
  &lt;li&gt;Text：程序所拥有的可执行内存页数&lt;/li&gt;
  &lt;li&gt;Lib：Library（Linux 2.6内核以后均为0）&lt;/li&gt;
  &lt;li&gt;Data：程序数据段和栈内存页数&lt;/li&gt;
  &lt;li&gt;Dirty：脏内存页数（Linux 2.6内核以后均为0）&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;要注意以上数据均为内存的页数（Pages），在计算实际内存时我们只需要将该数字乘以单个内存页的容量即可（Android系统为4KB）。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;这个命令中对我们最重要的数据是Resident，因为这个数据是Unity引擎中底层返回的”System Used Memory”数据的实际来源，也是Unity Memory Profiler中内存总用量的来源&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;在我们的测试过程中，发现这个数据与adb meminfo中的PSS和RSS均存在一定的偏差，通常来说该值大于PSS而小于RSS。&lt;/p&gt;

&lt;p&gt;关于该命令更多信息可查阅Linux系统文档：&lt;a href=&quot;https://man7.org/linux/man-pages/man5/proc.5.html&quot;&gt;proc(5) – Linux manual page&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;其他常用的相关命令还包括：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;adb shell run-as [application id] showmap [pid]&lt;/li&gt;
  &lt;li&gt;adb shell run-as [application id] cat /proc/[pid]/smaps&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;adb-shell-run-as-application-id-pmap-pid--x--txt&quot;&gt;adb shell run-as [application id] pmap [pid] -x &amp;gt; **.txt&lt;/h3&gt;

&lt;p&gt;该命令用于详细打印出应用程序的详细内存映像信息，并输出类似如下格式的信息：（由于该命令输出内容较多，所以通常我们通过”&amp;gt; **.txt”将其结果输出至指定文本文件中）&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Address            Kbytes     PSS   Dirty    Swap  Mode  Mapping
0000000012c00000  524288   11884   11884       0 rw---  [anon:dalvik-main space (region space)]
000000006f04a000    2620    1278    1256       4 rw---  boot.art]
000000006f2d9000     364     234     232       0 rw---  boot-core-libart.art]
000000006f334000     816     347     336      20 rw---  boot-core-icu4j.art]
000000006f400000     220     125     124       0 rw---  boot-okhttp.art]
000000006f437000     272      94      92       4 rw---  boot-bouncycastle.art]
000000006f47b000      60       0       0       4 rw---  boot-apache-xml.art]
000000006f48a000     512       2       0       0 r----  boot.oat
000000006f50a000    2508      13       0       0 r-x--  boot.oat
......
......
......
00000073a338f000      16      16      16       0 rw---  [anon:.bss]
00000073a3393000       4       0       0       0 r----  [anon:.bss]
00000073a3394000      24      12      12       0 rw---  [anon:.bss]
0000007fed645000       4       0       0       0 -----    [anon]
0000007fed646000    8188      64      64       0 rw---  [stack]
----------------  ------  ------  ------  ------
total           20713476  656271  532504    1556
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这个命令向我们非常详细的展示了应用在内存中所处的每一个段落的信息（相信adb meminfo也是通过这些信息来汇总分析），其mapping信息可以帮助我们验证adb meminfo中相关类别的数据信息。&lt;/p&gt;

&lt;p&gt;其中.so .art .oat .dex对应Code部分的内存；dalvik对应Java部分内存；anon则对应Unknown部分的内存。&lt;/p&gt;

&lt;p&gt;在我们的测试中，我们主要用来验证前文中adb meminfo数据中.so mmap部分数据存在的波动性问题。&lt;/p&gt;

&lt;p&gt;关于该命令更多信息可查阅Linux系统文档：&lt;a href=&quot;https://man7.org/linux/man-pages/man1/pmap.1.html&quot;&gt;pmap(1) – Linux manual page&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;so-mmap的波动问题&quot;&gt;.so mmap的波动问题&lt;/h3&gt;

&lt;p&gt;在我们测试过程中，会观测到同一个APK测试时.so mmap的用量有时可以在启动后及游戏的运行过程中稳定在100MB以内，而另一些时候则会在启动后开始逐渐增长至300MB，该现象在不同的手机上均会复现并无明显规律可循。&lt;/p&gt;

&lt;p&gt;经过我们的进一步的测试与分析，可以发现当.so mmap用量出现大幅增长时，Unknown部分的内存是会出现相应减少的，而内存的总量则始终保持稳定。&lt;/p&gt;

&lt;p&gt;之后通过利用pmap工具的进一步分析，我们确认无论.so mmap会不会增长，在pmap的数据中，.so的用量始终保持稳定，因此根据我们已有的线索来推断，只能理解为adb meminfo会出现这种将部分unknown内存用量错误的归类于.so mmap的问题。&lt;/p&gt;

&lt;p&gt;如果&lt;strong&gt;你的测试中也观测到类似的现象，我们建议你通过pmap数据来确认真实的.so文件相关内存用量，并采用正确的.so mmap数据时的adb内存数据&lt;/strong&gt;（抛弃.so mmap出现不正常增长时的内存数据）&lt;/p&gt;

&lt;h1 id=&quot;unity-memory-profiler&quot;&gt;Unity Memory Profiler&lt;/h1&gt;

&lt;p&gt;Memory Profiler是Unity提供的用于内存分析的工具，以目前尚在Preview的Package的形式提供给开发者使用，其本质是通过获取引擎中Allocator所记录的内存分配信息（需要Development Build）并进行归类来帮助开发者对游戏的内存情况进行分析，截至本文的编写，我们使用的是0.7.1-preview-1版本。&lt;/p&gt;

&lt;p&gt;该工具目前还处在开发与持续改进中，而在我们的使用过程中，通过阅读Memory Profiler与引擎的源代码，也确实发现了Memory Profiler在内存分析中一些很容易造成误导的问题，但总体来说Memory Profiler依然是目前Unity项目中用来分析Managed Heap与Unity引擎中Native Heap的最好的工具。&lt;/p&gt;

&lt;h3 id=&quot;managed-heap&quot;&gt;Managed Heap&lt;/h3&gt;

&lt;p&gt;这部分内存即为Unity C#代码逻辑使用的堆内存（Mono/il2cpp），更详细的信息可以通过”Objects and Allocations”标签中的”All Managed Objects”表格并结合实际代码来进行分析和改进。&lt;/p&gt;

&lt;p&gt;此外我们需要了解的In Use/Reserved两个数据所代表的含义，&lt;strong&gt;”In Use”表示当前C#代码中实际进行new分配并尚在生命周期的内存数据，Reserved则表示Unity Managed Heap的扩容逻辑向系统所预先申请的内存空间&lt;/strong&gt;（当Managed Heap扩容时实际上在操作系统层面上并不会立刻造成实际的物理内存分配，后文中有更详细的讨论）&lt;/p&gt;

&lt;h3 id=&quot;native-heap&quot;&gt;Native Heap&lt;/h3&gt;

&lt;p&gt;即Summary页面上的Other Native Memory部分，这也是除了Unity项目中除了Graphics中Texture、Mesh、Shader之外我们最应该关注的部分，也是用量通常最大的部分，对于这部分内存的详细情况，我们可以参考”Objects and Allocations”中的”Native Allocations”的数据。&lt;/p&gt;

&lt;p&gt;其主要的组成内容包括：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Objects&lt;/strong&gt;：即所有常见的Unity引擎对象的C++层面的内存分配，包括GameObject、Transform、Animator、Collider等等，如果你的项目场景中对象很多，这部分内存往往是Native Heap中最大头的部分，这往往会使得通常只关注Managed Heap中相关对象用量（Objects的C#端的内存）的开发者们低估在项目中使用海量Unity对象所造成的内存负担，此外Unity引擎中也会存在一些匿名的底层内存申请也会归类于这部分内存（例如Addressable），如果你的项目这部分用量过于庞大，而且你有Unity引擎源代码，可以通过打开RECORD_ALLOCATION_SITES宏，并魔改一下Memory Profiler来获得这部分内存更精细的类别统计（统计其Allocator的类别）&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;No Root Area&lt;/strong&gt;：这部分内存主要是引擎底层内部使用的部分内存，比如各种内部用到的Buffer，数组等以及一些来自GfxDevice模块的内存分配。此外在我们的测试中，可以发现使用大量的MeshCollider也会造成该部分内存的增长。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;SerializedFile&lt;/strong&gt;：这部分内存与AB包的加载数量呈直接且线性的关系。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;PersistentManager.Remapper&lt;/strong&gt;：也与AB包的使用相关，如果AB包中存在大量嵌套层级较深的Prefab的时候，这部分内存用量往往会出现较明显的增长。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;all-native-objects&quot;&gt;All Native Objects&lt;/h3&gt;

&lt;p&gt;在”Objects and Allocations”中还有一个标签页”All Native Objects”看上去应该是用来详细展示Native Allocations中的Objects类别的数据，但仔细看的话会发现其总量是通常会高于Native Allocations中的Objects用量的，关于这部分统计数据，我们了解了如下一些信息：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;其统计的是引擎Native分配中所有由GC系统所追踪并带有InstanceID的Objects，通过实际数量也可以确认，其应为Native Allocations中Objects的一部分对象&lt;/li&gt;
  &lt;li&gt;而其统计的内存中是包含了贴图与Mesh等部分GPU段内存的用量的，也因此导致内存用量无法与其他类别的内存统计量所对应&lt;/li&gt;
  &lt;li&gt;对于Objects本身的对象在”All Native Objects”中是不统计其数据结构头部信息的（Overhead），而通过阅读引擎源代码可以发现在Overhead部分是会被统计在Other Native的Reserved部分的，而其是会造成实际的内存分配的&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Other Native的In Use/Reserved空间的情况会比Managed Heap略微复杂一些，通过阅读引擎源代码可以发现与Other Native有关系的众多Allocator的逻辑其实并不相同，有些例如BucketAllocator确实会预先向操作系统申请虚拟内存空间，即我们通常所理解的Reserved操作，但例如DefaultAllocator则不会进行类似的操作，反而仅将OverHead与Padding计算入Reserved空间。对于这部分的详细内容，我们可能需要更多的测试与调研，但Other Native的实际内存用量是应该会高于引擎目前统计的In Use的部分的。&lt;/p&gt;

&lt;h3 id=&quot;treemap&quot;&gt;Treemap&lt;/h3&gt;

&lt;p&gt;Treemap是Memory Profiler从早期版本开始就已经提供的内存分析工具，可以以图形的方式来帮助开发者了解项目运行时的内存情况，但需要注意的是其所展示的内存包括了我们上文说的Graphics+Managed Heap+Native Heap，但&lt;strong&gt;均为部分包含，并未展现Unity引擎所使用内存的很多方面&lt;/strong&gt;。例如我们之前对比测试中发现当AB包数量较大时使用Addressable和AssetBundle.LoadFromFile()存在相当大的内存差距，而这部分差距在Treemap中无法得到体现。&lt;/p&gt;

&lt;p&gt;本质上&lt;strong&gt;Treemap是Unity为我们提供的用来发现一些项目中常见的内存问题的便捷工具，当项目进行较深度优化时，该工具无法发现所有问题&lt;/strong&gt;。&lt;/p&gt;

&lt;h3 id=&quot;untracked-memory&quot;&gt;Untracked Memory&lt;/h3&gt;

&lt;p&gt;按照Unity的官方文档，这部分是包含了目前Unity无法追踪的内存的总量，其包含Native Plugin、Executable &amp;amp; Dll、il2cpp runtime等。&lt;/p&gt;

&lt;p&gt;通过实际阅读源码，可以发现Unity对于这部分的计算方式是使用来自系统的/proc/[pid]/statm中Resident的内存用量减去Unity目前统计的各部分的内存用量得来的。&lt;strong&gt;但问题在于其减去的是各部分Reserved的内存数据，而Reserved的空间实际上有许多可能是并未发生实际内存分配的&lt;/strong&gt;，这使得Untracked的数据可能会产生相当大的误差。&lt;/p&gt;

&lt;p&gt;在我们的测试中经常会观测到Untracked Memory显示为Unknown，通过源代码我们发现显示Unknown的原因是系统返回的内存用量小于了Unity所统计的内存总和……而这正是由于Reserved空间的误差所造成的。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;由此我们判断Memory Profiler中的Untracked Memory完全没有任何指导意义，且极具迷惑性&lt;/strong&gt;。由此我们在以后的内存分析中需要重新定义Untracked的统计方式而不应采用Memory Profiler中的数值。&lt;/p&gt;

&lt;h1 id=&quot;系统内存分配与unity内存分配的规则&quot;&gt;系统内存分配与Unity内存分配的规则&lt;/h1&gt;

&lt;p&gt;在分析内存时，我们同样应该对操作系统以及引擎的内存分配行为及逻辑有所了解，以更好地理解我们所观测到的一些现象。&lt;/p&gt;

&lt;p&gt;安卓系统的内存管理体系主要继承于Linux的系统，这里推荐一个来自Google I/O的演讲&lt;a href=&quot;https://www.youtube.com/watch?v=w7K0jio8afM&quot;&gt;Understanding Android memory usage (Google I/O ’18)&lt;/a&gt; 介绍了一些系统层面的内存工作机制，简而言之，从系统角度来看，内存最小分配的单元是页，每个页4KB，并且会在系统内存紧张时尝试回收部分可回收的内存页面（Clean Pages），或必要时杀掉优先度较低的应用进程。&lt;/p&gt;

&lt;p&gt;而引擎底层的重载了new操作并主要通过VirtualAlloc接口来进行内存申请，其在内存声明/申请时并不会真正发生底层的物理内存分配，而只有在实际进行相关的内存访问（读/写）时才会触发系统底层内存分配操作。&lt;/p&gt;

&lt;p&gt;此外引擎所记录的内存信息主要是基于虚拟内存地址，其无法反应对象在真实物理内存上所属内存页情况，因此我们所看到的例如Managed Heap中In Use的用量是一种理想的非常紧凑的内存用量情况，其实际分配与物理内存页的情况可能会造成更高的内存用量，而这部分的偏差也是我们目前已有的工具中无法准确统计到的。&lt;/p&gt;

&lt;p&gt;ADB数据中反应的是反映了系统实际所使用的物理内存页的情况，而Unity所记录的是更加理想化的紧凑化之后的内存数据，即我们在Unity Memory Profiler所能看到的内存用量应会适量占据更多的内存。&lt;/p&gt;

&lt;h1 id=&quot;内存分析流程&quot;&gt;内存分析流程&lt;/h1&gt;

&lt;p&gt;在了解上述所有内容后，我们在日常项目的内存分析工作中，通常使用了如下的分析流程：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;使用adb shell dumpsys meminfo来分析程序内存的整体情况，并确保.so mmap数据的正常&lt;/li&gt;
  &lt;li&gt;使用Perfetto获取并分析Native Heap的内存使用情况&lt;/li&gt;
  &lt;li&gt;使用pmap来对比并确认.so mmap的内存使用情况&lt;/li&gt;
  &lt;li&gt;利用Memory Profiler中的All Native Objects数据来分析Graphics相关内存（ADB的Graphics与Memory Profiler中Graphics的用量差别应为引擎底层的渲染相关内存分配）&lt;/li&gt;
  &lt;li&gt;通过Memory Profiler的数据来分析Unknown中的主要内存使用情况&lt;/li&gt;
  &lt;li&gt;通过开关Native Plugin的方式来获得相关插件的大致内存用量&lt;/li&gt;
  &lt;li&gt;由于Unknown ≈ Memory Profiler中统计数值(Managed Heap + Other Native + Audio + Profiler) + Native Plugin，我们在使用ADB的Unknown用量减去所有可统计的已知内存部分，可以获得更为精确的Untracked memory内存用量&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;利用这样的方法我们将ADB所统计的内存用量，更清晰的划分为类似下图的内存分配图（Graphics可更进一步统计出Mesh与Texture2D的用量占比），以帮助我们了解项目的内存使用情况，并针对性的展开相关部分的优化与改进工作。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2023/03/1c5e7198-9777-46fe-9630-fb116b4653a8.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;通过分析流程所获取的内存用量分布饼图&lt;/p&gt;

        </description>
        <pubDate>Sun, 19 Mar 2023 07:37:18 +0000</pubDate>
        <link>/2023/unity-memory-profile-on-android.html</link>
        <guid isPermaLink="true">/2023/unity-memory-profile-on-android.html</guid>
      </item>
    
      <item>
        <title>为Unity Sprite实现GPU Instancing</title>
        <description>
          
          &lt;h1 id=&quot;概述&quot;&gt;概述&lt;/h1&gt;

&lt;p&gt;公司里有一个使用Unity开发的2D像素风格的战棋类的游戏项目，其实现上采用了3D场景+精灵动画人物的方案，配合了Unity URP渲染管线，静态场景是可以利用SRP Batcher来提升Graphics API方面的性能表现，但是很遗憾到项目正在使用的Unity 2020.3为止，Unity的Sprite Renderer还没有实现对SRP Batcher的支持。于是我的目标就是根据他们游戏的特点尽可能的提供性能改进的方案。&lt;/p&gt;

&lt;h1 id=&quot;资产特性&quot;&gt;资产特性&lt;/h1&gt;

&lt;p&gt;这次优化的目标主要围绕游戏中使用的Sprite Renderer组件，也就是游戏中人物角色的绘制，项目中与人物相关的资产具有以下一些特征：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;游戏中所有角色绘制使用的Shader是相同的&lt;/li&gt;
  &lt;li&gt;角色的精灵动画使用帧动画实现&lt;/li&gt;
  &lt;li&gt;每个角色的精灵帧动画在同一张Atlas中，并通过Sprite Mode “Multiple”和Sprite Editor来编辑并导入工程&lt;/li&gt;
  &lt;li&gt;每个角色的Atlas贴图格式相同且大小均为512X512&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;优化思路&quot;&gt;优化思路&lt;/h1&gt;

&lt;p&gt;既然Shader都是相同的，那么合批是有前提保障的；而贴图方面角色贴图规格相同也使得使用TextureArray成为可能，那么剩下的问题就是Mesh了，而Sprite的Mesh刚好又是可以通过简单的Quad即可实现的，于是我们的目标就是利用自定义的MeshRenderer来代替Unity原生的Sprite Renderer了。&lt;/p&gt;

&lt;p&gt;经过一些调试和阅读SpriteRenderer的源代码实现，我们发现即使将Sprite的MeshType设置为“Full Rect”，SpriteRender实际上也会为每一个不同的Sprite生成不同的Mesh信息，原因是不同的Sprite会有不同的尺寸（PixelPerUnit）和偏移等信息，但其计算逻辑比较简单，我们是可以通过相同的Mesh（比如Unity内建的Quad）配合不同的材质属性来在顶点着色器中实现具体的缩放和偏移的。&lt;/p&gt;

&lt;p&gt;Unity中合批性能最好的GPU Instancing的要求之一是使用相同的模型，既然理论上可以通过相同的Quad模型，那么我们可以尝试来实现人物精灵的GPU Instancing了。&lt;/p&gt;

&lt;h1 id=&quot;缩放与平移&quot;&gt;缩放与平移&lt;/h1&gt;

&lt;p&gt;为了保证使用了统一Quad模型的MeshRenderer在渲染Sprite的时候可以将Sprite正确的大小和偏移表现正确，我们需要计算好尺寸与偏移，并将其保存在MaterialPropertyBlock中，以供顶点着色器可以在世界坐标变换前，先在模型空间根据这些信息进行变换以复现SpriteRenderer中原本的坐标位置。&lt;/p&gt;

&lt;p&gt;这里需要特别注意的是SpriteRenderer中生成的Mesh和Unity内建的Quad的Mesh虽然都是两个三角形，但是顶点和索引的顺序确实完全不同的，这个暗坑耽误了我不少的时间。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2022/03/UnitySpriteGPUInstancing.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;计算尺寸和偏差的逻辑代码：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// 根据Sprite的尺寸和偏移计算Quad的缩放与平移关系
Pivot.x = sprite.rect.width / sprite.pixelsPerUnit;
Pivot.y = sprite.rect.height / sprite.pixelsPerUnit;
Pivot.z = ((sprite.rect.width / 2) - sprite.pivot.x) / sprite.pixelsPerUnit;
Pivot.w = ((sprite.rect.height / 2) - sprite.pivot.y) / sprite.pixelsPerUnit;
// 根据顶点顺序的不同重新映射正确的UV范围
newUV.x = sprite.uv[1].x - sprite.uv[0].x;
newUV.y = sprite.uv[0].y - sprite.uv[2].y;
newUV.z = sprite.uv[2].x;
newUV.w = sprite.uv[2].y;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后我们在VS中通过手工生成变换矩阵的方式在世界变换之前应用正确的缩放与平移变换：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;half4 pivot = UNITY_ACCESS_INSTANCED_PROP(Props, _Pivot);
// 生成缩放平移矩阵
half4x4 m;
m._11 = pivot.x; m._12 = 0; m._13 = 0; m._14 = pivot.z;
m._21 = 0; m._22 = pivot.y; m._23 = 0; m._24 = pivot.w;
m._31 = 0; m._32 = 0; m._33 = 1; m._34 = 0;
m._41 = 0; m._42 = 0; m._43 = 0; m._44 = 1;
float4 vertex = UnityFlipSprite(input.positionOS.xyz, _Flip);
// 生成UV的变换矩阵
half3x3 uvm;
half4 newUV = UNITY_ACCESS_INSTANCED_PROP(Props, _NewUV);
uvm._11 = newUV.x; uvm._12 = 0; uvm._13 = newUV.z;
uvm._21 = 0; uvm._22 = newUV.y; uvm._23 = newUV.w;
uvm._31 = 0; uvm._32 = 0; uvm._33 = 1;
half3 uv = half3(input.texcoord.x, input.texcoord.y, 1);
// 执行UV变换矩阵
uv = mul(uvm, uv);
VertexPositionInputs vertexInput;// = GetVertexPositionInputs(vertex.xyz);
// 执行顶点缩放平移变换
vertexInput.positionWS = mul(m, input.positionOS); // convert as Sprite
vertexInput.positionWS = TransformObjectToWorld(vertexInput.positionWS).xyz;
// ......
// 将变换后的UV赋值给片元的数据结构
output.uv.xy = uv.xy;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;贴图数组&quot;&gt;贴图数组&lt;/h1&gt;

&lt;p&gt;Texture Array的准备相对要简单很多，我们可以在Loading时候创建Texture Array并将关卡中必要的贴图拷贝进来，需要一点逻辑来维护贴图在数组中的位置以及可能动态出现的新贴图。在OpenGL 3.0中Texture Array的数量已经支持到256，Metal API更是支持到2048，相信应该是够用的，万一真不够也是可以通过逻辑管理多个贴图数组来实现最大可能的合批的。&lt;/p&gt;

&lt;p&gt;此外需要注意最好是利用Graphics.CopyTexture()接口来初始化Texture Array，因为是在GPU上进行的，速度较快且无需拷贝回系统内存。&lt;/p&gt;

&lt;h1 id=&quot;着色器语法&quot;&gt;着色器语法&lt;/h1&gt;

&lt;p&gt;这里列举Shader中一些必要的语法：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;启用贴图数组的必要宏：#pragma require 2darray&lt;/li&gt;
  &lt;li&gt;启用GPU Instancing的必要宏：#pragma multi_compile_instancing&lt;/li&gt;
  &lt;li&gt;声明贴图数组：Texture2DArray _TextureArray;&lt;/li&gt;
  &lt;li&gt;贴图采样：_Textures.Sample(my_point_clamp_sampler, float3(uv, _TextureIndex)&lt;/li&gt;
  &lt;li&gt;以及GPU Instancing必要的MaterialPropertyBlock中对应Buffer的声明&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;light-probe的支持&quot;&gt;Light Probe的支持&lt;/h1&gt;

&lt;p&gt;另外Unity从2018开始已经为GPU Instancing实现了对Light Probe的支持，但支持是依赖引擎中的一些固定操作的，因此我们需要保证我们的Shader中一些变量声明符合引擎中的规范，才能保证Light Probe可以正确的配合GPU Instancing工作。我们需要将Light Probe有关的变量以明确的命名并确保他们声明在”UnityPerDraw”的CBUFFER字段中。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;CBUFFER_START(UnityPerDraw)
// SH block feature
real4 unity_SHAr;
real4 unity_SHAg;
real4 unity_SHAb;
real4 unity_SHBr;
real4 unity_SHBg;
real4 unity_SHBb;
real4 unity_SHC;
CBUFFER_END
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在计算颜色的过程就可以使用引擎内置的计算方式来进行球谐的计算（运算逻辑来自URP内置球谐计算函数SampleSH9()）&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// Linear + constant polynomial terms
float3 res = SHEvalLinearL0L1(output.normal.xyz, unity_SHAr, unity_SHAg, unity_SHAb);

// Quadratic polynomials
res += SHEvalLinearL2(output.normal.xyz, unity_SHBr, unity_SHBg, unity_SHBb, unity_SHC);

#ifdef UNITY_COLORSPACE_GAMMA
    res = LinearToSRGB(res);
#endif

output.vertexSH.xyz = max(half3(0, 0, 0), res);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;而在C#中，我们需要通过引擎提供的接口手动计算出球谐系数并将他们拷贝到MaterialPropertyBlock中，引擎同样提供了接口帮助我们完成；最后我们还要需要将Render的Light Probe Usage设定为”CustomProvided”，这样引擎可以正确的知道我们准备利用CBUFFER来进行球谐系数的保存。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// Set Light Probe info
Vector3[] position = new Vector3[1] { transform.position };
SphericalHarmonicsL2[] lightProbes = new SphericalHarmonicsL2[1];
Vector4[] occlusionProbes = new Vector4[1];
 
// Manually get proper SH values
LightProbes.CalculateInterpolatedLightAndOcclusionProbes(position, lightProbes, occlusionProbes);
materialPropertyBlock.CopySHCoefficientArraysFrom(lightProbes);
materialPropertyBlock.CopyProbeOcclusionArrayFrom(occlusionProbes);
 
// We have to set light probe mode to &quot;CustomProvided&quot;, so Unity will copy and use them into CBUFFER
meshRenderer.lightProbeUsage = LightProbeUsage.CustomProvided;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;动态atlas&quot;&gt;动态Atlas&lt;/h1&gt;

&lt;p&gt;在我们实际将这个技术集成进项目工程时，因为开发过程中已经存在了大量不同尺寸的Sprite贴图，我们最后进一步实现了对于不同尺寸的Sprite贴图的动态合并图集的支持，这样的好处是无论工程中之前用到的贴图资源的尺寸大小，无论游戏运行时贴图的用途是角色还是场景装饰，都可以一个Instance全部画完，所有Sprite Render均通过一个Draw Call绘制完成，岂不快哉！&lt;/p&gt;

&lt;p&gt;听上去比较唬人，但实际上的原理并不复杂：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Sprite Instancing会在运行时使用可能用到的最大贴图尺寸来创建初始的Texture2DArray（例1024×1024）&lt;/li&gt;
  &lt;li&gt;当不同尺寸的Sprite贴图加载进来的时候，我们通过Graphics.CopyTexture拷贝至Texture2dArray中，但拷贝的位置会根据算法自动分配其位于Texture2DArray中合适位置&lt;/li&gt;
  &lt;li&gt;需要实现算法来维护Texture2DArray中目前可以利用的贴图区域和已经被占用的区域，原理类似于Hashmap的方式，通过一个元素为LinkedList的数组实现，数组下标则是贴图高度以2为底的对数（例：下标为5的数组内的LinkedList中保存的是可用的Nx32的贴图区域）&lt;/li&gt;
  &lt;li&gt;当我们需要申请新的贴图的时候，根据申请的贴图的高度来在对应下标的数组的LinkedList中寻找最合适的可用区域，如果没有找到，则会下标+1，尝试在更大的区域中寻找，一旦找到后，将区域裁减开，一块返回给当前申请贴图使用，另一块根据大小再重新加回到数组对应下标的可用区域列表中，如此完成整个贴图数组的管理。&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;结论&quot;&gt;结论&lt;/h1&gt;

&lt;p&gt;这篇文章中的优化方案其实还是需要一些先决条件的，如果你们的工程也符合这些先决条件，又刚好需要类似的优化内容，那么希望这个方案可以帮到你，如果不能，也希望能为你提供一些思路。&lt;/p&gt;

&lt;p&gt;项目中的资源不好公开出来，所以我将核心思路实现在了一个简单的&lt;a href=&quot;https://github.com/ownself/UnitySpriteGPUInstancing&quot;&gt;示例工程&lt;/a&gt;中，有需要的话，请自行参考，如果有发现问题或者更好的改进方案，也请不吝赐教。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2022/03/SpriteInstancingResult.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

        </description>
        <pubDate>Sun, 06 Mar 2022 12:31:20 +0000</pubDate>
        <link>/2022/unity-sprite-gpu-instancing.html</link>
        <guid isPermaLink="true">/2022/unity-sprite-gpu-instancing.html</guid>
      </item>
    
      <item>
        <title>2021年书单</title>
        <description>
          
          &lt;p&gt;我的父亲是个爱书的人，不仅爱看，也爱收藏书，小时候家里四个大书架放的满满的也不够用。但是我们家的条件又不允许有独立的书房，所以这些存书占据我的屋子中很多的空间，也因此在我的潜意识里，对纸质书并没有太多的好感，以至于自己成家以后，家里就坚决不设置书架这种家具，纸质书能不买就不买，看过了尽可能处理掉。&lt;/p&gt;

&lt;p&gt;工作以后我基本上都是看PDF格式的电子书了，因为绝大部分都是工作相关的技术类书籍。直到去年我才开始了使用Kindle并重新阅读起了课外类的书籍，回看这一年还是有很多收获的，而且也完美的解决了我对实体书的怨念问题，以后我会以年为单位来对自己的课外阅读中值得一读的作品做总结，希望能将这一习惯保持下去。&lt;/p&gt;

&lt;h3 id=&quot;10人以下小团队管理手册&quot;&gt;10人以下小团队管理手册&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://book.douban.com/subject/27019726/&quot;&gt;10人以下小团队管理手册&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2022/02/s29425665.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;日本人写的团队管理书籍，内容写的比较实在，语言也很精炼，理念也比较正面，不过大部分也都是大家都知道的大道理。但阅读时需要注意书中所提到的经验均来自日本企业的环境，会有一些日本企业文化的情景在里面，在阅读过程中需要将内容结合背景进行理解和思考。&lt;/p&gt;

&lt;h3 id=&quot;我这一辈子&quot;&gt;我这一辈子&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://book.douban.com/subject/26984264/&quot;&gt;我这一辈子&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2022/02/s29370045.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;老舍的短篇小说，以“我”为视角来描写中国旧社会作为底层人民生活的那种无奈感，有张国立主演的同名电视剧，虽然还没看过，但在阅读的过程中会不自觉地在脑海里把张国立的形象套在小说的主角身上，也许我会更推荐电视剧版本一些。&lt;/p&gt;

&lt;h3 id=&quot;古代人的日常生活&quot;&gt;古代人的日常生活&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://book.douban.com/subject/34912073/&quot;&gt;古代人的日常生活&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2022/02/s33550455.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;一本通俗易懂，语言风趣幽默的口水书，讲了一些中国古人衣食住行的历史，很多冷知识，随便读一读是很不错的消遣。&lt;/p&gt;

&lt;h3 id=&quot;蒋介石与现代中国&quot;&gt;蒋介石与现代中国&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://book.douban.com/subject/10797092/&quot;&gt;蒋介石与现代中国&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2022/02/s11134336.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;一个外国学者在阅读了大量材料和采访了很多人后写出的传记，相对来说还是比较客观的。在清末民初的历史中，政党和军阀就像是创业公司一般，有些很“务实”，有些还会保有“理想”的一面，早期的蒋介石有着理想的一面，后来在国内外环境的交困下，沦为美苏两边的投机分子。但总的来说正如书中最后总结的蒋介石其实和毛泽东一样，他也是一心想要恢复中国的主权与世界地位，如果蒋在九泉之下看到现今的世界，也一定会为了中国所取得巨大进步而感到高兴。&lt;/p&gt;

&lt;h3 id=&quot;日本人为何选择了战争&quot;&gt;日本人为何选择了战争&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://book.douban.com/subject/34204669/&quot;&gt;日本人为何选择了战争&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2022/02/s33456165.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;从日本人的角度去分析从甲午战争开始的日本军国主义战争之路，以现代人的角度看，日本走的路线犹如一场豪赌，寄希望于通过战争和掠夺走上一条快速成为列强的道路。而甲午战争、日俄战争的胜利极大的刺激了他们继续下去的动力。如果最终日本没有押注上所有的一切与美国开战，现在东亚的局面也许会截然不同。&lt;/p&gt;

&lt;h3 id=&quot;程序员的数学&quot;&gt;程序员的数学&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://book.douban.com/subject/19949020/&quot;&gt;程序员的数学&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2022/02/s20811702.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;书名乍一看以为是一本很枯燥的书，不过实际看起来却是相当的通俗易懂且有趣。实际上，比起是程序员，这本书更像是给拥有初中数学水平的人阅读的兴趣读物。通过一道道智力题风格的数学问题，罗列了一个程序员应该有的数学方面的若干种思路，如果孩子对编程有兴趣，可以作为一本相关数学知识的启蒙书。&lt;/p&gt;

&lt;h3 id=&quot;程序员的数学2--概率统计&quot;&gt;程序员的数学2 : 概率统计&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://book.douban.com/subject/26593822/&quot;&gt;程序员的数学2 : 概率统计&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2022/02/s28340170.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;如果说第一本是给小学生看的，那么第二本就要难上许多了，因为概率学涉及到连续值问题时会用到很多微积分和线性代数的知识。这本书讨论的范畴对于程序员来说更多的是人工智能和数据分析领域中会涉及到的一些数学知识。不过开篇的部分作者尝试使用很多比喻希望让读者更容易的理解一些概率学概念，我觉得适得其反，反而显得云里雾里的；而后面又预设读者通晓微积分计算而直接搬出大段数学推导，让节奏显得有些跳跃，总的来讲，对于数学基础不够扎实的人来说可能还是值得一读的。&lt;/p&gt;

&lt;h3 id=&quot;程序员的数学3--线性代数&quot;&gt;程序员的数学3 : 线性代数&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://book.douban.com/subject/26740548/&quot;&gt;程序员的数学3 : 线性代数&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2022/02/s28487645.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;程序员的数学系列来到第三本，其实第一本和第二三本的原作者就已经不是一个人，而三本书的中文译者也都是不同的人，所以阅读起来这三本书很难给人一种非常流畅阅读体验。 第三本在阅读的难度上和第二本类似，而且作者在讲解线性代数中基础概念尤其是几何意义的时候希望通过更“直观”的方式来便于读者理解，但不幸的是同第二本相同，这种“通俗”的表达再次略显适得其反，在“直观性”上，更推荐Youtube上&lt;a href=&quot;https://www.youtube.com/c/3blue1brown&quot;&gt;3blue1brown&lt;/a&gt;制作的《&lt;a href=&quot;https://www.youtube.com/playlist?list=PLZHQObOWTQDPD3MizzM2xVFitgF8hE_ab&quot;&gt;线性代数的本质&lt;/a&gt;》系列视频。 后半段书中介绍了线性代数在AI领域计算中涉及到的一些高维矩阵计算的优化算法，对于游戏开发者来说还算是一种不错的知识拓展。 其实就线性代数的应用方面，在游戏的3D图形学中的各种空间变换可以说是一种相当不错的教学用例，但本书中并没有涉及也不无是一种遗憾。&lt;/p&gt;

&lt;h3 id=&quot;煤气灯效应&quot;&gt;煤气灯效应&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://book.douban.com/subject/34978658/&quot;&gt;煤气灯效应&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2022/02/s33660425.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;一本心理学范畴的书，书中提出了煤气灯操纵者的概念，实际上是围绕着人与人关系中广泛存在的PUA行为的一种讨论，初衷和想法都非常出色，前半段对于一系列关系中的利害与行为产生的原因都做了总结和讨论，发人思考。但后半段开始采样大量的情景和对话来试图向读者展现作者所描绘的理论，让内容显得松散很多。而且更多的以两性关系中女性视角作为受害者来进行阐述也使得作者的立意让人不免感觉逐渐“女权”了起来。&lt;/p&gt;

&lt;h3 id=&quot;追风筝的人&quot;&gt;追风筝的人&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://book.douban.com/subject/1770782/&quot;&gt;追风筝的人&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2022/02/s1727290.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;去年里唯一读的一本小说。这个精彩的故事背后是一个个鲜活的人物形象。 最开始读的时候只是抱着随便看看的心情，但没想到这本书是如此的震撼人心，阅读过程中数次忍不住泪流满面，虽然对伊斯兰文化了解很少，甚至还有些偏见，但在这个故事中一个个鲜活的人物，看到的人性的善与恶，与我们所熟知的一样真实。&lt;/p&gt;

&lt;h3 id=&quot;干法&quot;&gt;干法&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://book.douban.com/subject/26648884/&quot;&gt;干法&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2022/02/s28324536.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;京瓷老板稻盛和夫的工作哲学，其想法和理念本身我是认同的，人生在世应当努力拼搏，且不过分苛求回报。但如果视角是作为老板要求员工或者同事，则有些洗脑或者PUA的味道，书中最后一段讲述改为作者在过去的经历中对于自己的要求和思考，看起来就让人容易接受的多。总的来说是一本鸡汤类的书籍，并且有些过分神话意念的力量，干货并不算多。&lt;/p&gt;

&lt;h3 id=&quot;深度工作&quot;&gt;深度工作&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://book.douban.com/subject/27056409/&quot;&gt;深度工作&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2022/02/s29470672.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;所谓深度工作通俗的讲就是在不受打扰高度集中的状态下更高效的进行工作的方法，本书从理论到实践围绕着为什么需要深度工作和如何进行深度工作两个方面阐述其的理论，而之所以深度工作如此重要是因为有一些工作的成果，是“浮浅工作”所无法最终产出的。作为程序员，日常的很多工作内容其实很契合书中的一些观点的，如何能在纷扰的生活和工作环境中，尽可能的集中自己的注意力是提升自己的很重要的方法。&lt;/p&gt;

&lt;h3 id=&quot;乌合之众--大众心理研究&quot;&gt;乌合之众 : 大众心理研究&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://book.douban.com/subject/1012611/&quot;&gt;乌合之众 : 大众心理研究&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2022/02/s1988393.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;一本很有名的关于社会心理学的书籍，本质上这是一本反集体主义思想的书籍，读到一半的时候我甚至开始怀疑这本书是如何在我国出版的，但当我读到后面作者喷民主制度和议会机制的时候，我才明白原来作者表达的是“在座的都是垃圾”。*笑哭* 作者主要通过法国大革命、由社会主义兴起并伴随的工人运动、英国民主议会制度以及陪审团等例子来分析当不同的人们组成群体后心理上发生的变化，而作者认为这种变化几乎全部是负面的。书中许多观念和作者的表达是需要结合作者所处在的历史时机去理解的，对我来说这本书可以带给我一些思考，有很多想法很有启发性，但我并不会全部认同作者想表达的东西。&lt;/p&gt;

&lt;h3 id=&quot;咖啡咖啡处处开&quot;&gt;咖啡咖啡处处开&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://book.douban.com/subject/26914080/&quot;&gt;咖啡咖啡处处开&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2022/02/s29149226.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;对咖啡小白来说一本不错的知识普及读物，关于咖啡的分类、历史、产地、制作流程甚至目前的国际市场的商业模式都有介绍；后半部分则介绍了咖啡的不同种喝法、冲泡技巧以及品鉴特点。看完后最让人比较稀嘘的一点是，咖啡最早在西方是作为喝不起茶的人们的廉价代替品出现的，但现在在作为茶的故乡的我们的国家里，年轻人却都以喝咖啡作为时尚的象征。&lt;/p&gt;

&lt;h3 id=&quot;少有人走的路--心智成熟的旅程&quot;&gt;少有人走的路 : 心智成熟的旅程&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://book.douban.com/subject/1775691/&quot;&gt;少有人走的路 : 心智成熟的旅程&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2022/02/s2144391.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;一本评价非常高的心理学书籍，成书较早，作者也是一位心理医生，主要讨论我们应该如何让心智不断成长，前半部分围绕如何自律和什么是爱这两个主题展开讨论，作者的思维很有东方哲学的味道，更多讲求我们应该从自身出发，以主动的方式去积极的面对人生和难题，很多论述确实能直击我的内心，书的前半部分可以给到4星半的水平。 后半部分则开始讨论起哲学与信仰的关系，以及我们应该如何树立内心中的“神”；而后对于潜意识和第六感的讨论则开始逐渐“神话”了起来，作者似乎是认为人的潜意识中有一定的超自然成分存在，这些内容则让作为理科生的我读起来异常出戏，我更希望能看到的，是从心理医生的角度系统性理论性的总结人们广泛遇到的心智成熟的问题，以及应当如何去解决它们。不得不说，全书读完之后，难免会有种高开低走，略带遗憾的感觉。&lt;/p&gt;

&lt;h3 id=&quot;人类群星闪耀时--十四篇历史特写&quot;&gt;人类群星闪耀时 : 十四篇历史特写&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://book.douban.com/subject/34434342/&quot;&gt;人类群星闪耀时 : 十四篇历史特写&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2022/02/s33300419.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;作者是一战二战期间的奥地利人，书中描绘了十四个颇有戏剧性历史时刻，夸张感十足的文笔很有戏剧的味道，也因此让本书在文学和历史之间显得有点摇摆。此外结合作者书中表达的思想与其所处在的历史时期，会让人觉得作者有着虔诚的基督教信仰以及些许白人至上主义，所以《人类群星闪耀时》不如译作《白人群星闪耀时》，比如书中描写第一个见到太平洋的巴尔沃亚，可难道领着他的土著向导不其实才是更早就见过太平洋的人吗？土著就不是人了吗？亦或者君士坦丁堡的陷落被作者描述为“人类精神世界的巨大损失”，但实际上对于伊斯兰世界来说，攻克伊斯坦布尔却是件伟大的成就。 书中最精彩的篇章无异于征战南极，发生阿蒙森和斯科特之间真实的历史比电影中的情节都更加戏剧性和悲壮，很遗憾到目前为止都没有一部以客观的视角描述这段历史的电影。&lt;/p&gt;

&lt;h3 id=&quot;人间失格&quot;&gt;人间失格&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://book.douban.com/subject/24744505/&quot;&gt;人间失格&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2022/02/s28470753.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;太宰治的杂文集，一本评价很高的书，但最后还是没能坚持看完，读了作者最富盛名的人间失格、Goodbye和维庸之妻三个篇章，虽然这么说会让喜欢这本书的人反感，但在我看来书中文字满是些负面的气息，要不就是些莫名其妙的无病呻吟，我完全不能领会其意。也许面向的读者群体是那些尚未建立成熟世界观又想表达特立独行的中学生，又或者是那些能强烈引起共情的有抑郁倾向的悲观主义者们，总之我的感觉是这不是一本适合有着健康积极处事态度的人有必要去读的书。 另外看了关于作者生平的简介，酗酒、滥情、嫖娼、嗑药且逃避现实，连自杀都要找个同伙才有胆量去实施的胆小鬼，写作在很长时间里只是其赖以谋生的手段，并非拥有强烈的热情。想必作者也是在童年因为缺失爱而导致自律失调的精神病人吧。 这类文学姑且可以叫废物文学吧，可惜了我因为读这本书而浪费掉的许多时间。&lt;/p&gt;

&lt;h3 id=&quot;子弹笔记&quot;&gt;子弹笔记&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://book.douban.com/subject/30395230/&quot;&gt;子弹笔记&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2022/02/s29939981.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;春节假期第一天在家闲来无事随便看了看的一本书，没想到却让我花了一天一口气看完了，看似是一本教你如何做笔记的方法书，但书中花了将近一半的时间在讨论关于反思的哲学，虽然关于这部分的哲学讨论不成体系，显得有些凌乱，也会让很多“效率专家”觉得可能有些幼稚，但确实说到了我很长久以来做笔记只注重思考和精炼，但很少考虑反思的问题。可以说子弹笔记的所有方法论都是围绕反思这一核心主题展开的，同我们自古以来的“吾当一日三省吾身”不谋而合，只是作者将这一哲学付诸到了实实在在的方法上。至少对来我说这本书引起了我的思考，也让我很有兴趣去用不一定严格意义的形式上，而在思路上尝试下“子弹笔记”。&lt;/p&gt;

        </description>
        <pubDate>Wed, 02 Feb 2022 13:14:19 +0000</pubDate>
        <link>/2022/book-of-year-2021.html</link>
        <guid isPermaLink="true">/2022/book-of-year-2021.html</guid>
      </item>
    
      <item>
        <title>Unity的缩放骨骼动画问题</title>
        <description>
          
          &lt;h2 id=&quot;概述&quot;&gt;概述&lt;/h2&gt;

&lt;p&gt;最近在工作中遇到了一个在Unity引擎中无法正确使用带缩放的骨骼动画（FBX格式）的问题，其表现为如果动画资源在DCC工具（Maya）制作中使用非统一缩放（Non-uniform scaling）的骨骼节点，则该动画在导入Unity工程中以后动画效果会呈现出与DCC工具中不同的带有严重变形的动画效果（抱歉项目内的模型资源不便在博客展示）。&lt;/p&gt;

&lt;h2 id=&quot;环境&quot;&gt;环境&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;软件名称&lt;/th&gt;
      &lt;th&gt;版本&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Unity&lt;/td&gt;
      &lt;td&gt;2019.4&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Maya&lt;/td&gt;
      &lt;td&gt;2020&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Unreal&lt;/td&gt;
      &lt;td&gt;4.25&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;FBX SDK&lt;/td&gt;
      &lt;td&gt;2018.1.1&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Win10 3D查看器&lt;/td&gt;
      &lt;td&gt;7.2010.15012.0&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;问题复现&quot;&gt;问题复现&lt;/h2&gt;

&lt;p&gt;我们首先尝试在不同的软件/引擎中查看问题动画资源的显示效果，结果发现问题资源在导入到Unreal引擎中是可以得到同DCC工具中相同的效果的。&lt;/p&gt;

&lt;p&gt;我们知道游戏引擎中为了实现动画资源更好的数据压缩，通常不会直接保存变换矩阵，而是通过SQT通道以及量化(Quantization)来进行一定程度的有损压缩。因为矩阵需要使用16个浮点数来表示一个完整的变换（缩放、旋转、平移），而如果使用四元数（四个浮点数）、平移向量（三个浮点数）、缩放向量（三个向量）则可以将每一个变换的数据信息缩减到10个浮点数来表示。在实际应用中，很多游戏引擎会限制非统一缩放，即仅允许模型进行整体缩放而不允许在不同的轴上进行不同程度的缩放，这样又可以省下两个浮点数，总共仅需要8个，这样算下来动画的数据量已经减小了一半！再来因为四元数是[-1~1]的值域，使用32位的浮点数来保存其实是一种浪费，所以通常还会更进一步将其压缩为整型来保存，而在运行时再动态的转换为浮点数来进行计算，这种技术被称为量化。&lt;/p&gt;

&lt;p&gt;几乎所有的引擎在动画数据导入以后都会对数据进行一次转存，从而将信息保存为进行过类似上述优化后的数据，而不同的引擎对于原始动画数据会有不同的解读。于是我们可以先盲猜一手，问题很有可能是出现在引擎端对于动画数据的转换和解读过程中。&lt;/p&gt;

&lt;p&gt;另一个值得注意的细节是，用Win10自带的“3D查看器”来查看问题动画的效果，虽然没有出现Unity中出现的很夸张的走形，但依然存在同DCC中效果的一些偏差，说明不同的软件之间对数据的解释都会一些差别。&lt;/p&gt;

&lt;h2 id=&quot;fbx文件格式&quot;&gt;FBX文件格式&lt;/h2&gt;

&lt;p&gt;我们找到一篇来自Unity官方教程，里面提到了一些动画相关问题的官方建议：&lt;a href=&quot;https://learn.unity.com/tutorial/rigging-edge-cases-1?language=en#5d02fb65edbc2a001f46ee63&quot;&gt;《Rigging Edge Cases》&lt;/a&gt;。其中第4、5章节提到的一个关于Non-uniform缩放的问题看上去与项目组遇到的问题非常相似，而关于这个问题官方的建议是将带有缩放的节点提出并孤立出来，而这个方法也与目前项目组的解决方案不谋而合。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2021/01/extra_scale_nodes.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;将缩放的变化置于额外的骨骼并保证其不会有子节点&lt;/p&gt;

&lt;p&gt;之后再查阅Unity的官方文档，可以了解到Unity之所以存在Non-uniform缩放显示不正确的问题是因为Unity计算缩放的方式同Maya等大多数DCC工具不一样，特别是不支持”Segment scale compensation”（以下简称SSC）：&lt;a href=&quot;https://docs.unity3d.com/Manual/HOWTO-ImportObjectsFrom3DApps.html#Maya&quot;&gt;《Importing objects from Autodesk® Maya》&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Unity does not support Autodesk® Maya®’s Rotate Axis (pre-rotation). &lt;br /&gt;
Joint limitations include: &lt;br /&gt;
 • Joint Orient (joint only post-rotation) &lt;br /&gt;
 • &lt;strong&gt;Segment Scale Compensate (joint only option)&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;这个SSC是Maya独有的一个动画功能，在使用Maya制作动画资源时默认会在每一个骨骼节点开启，其效果是自动针对骨骼父节点的缩放信息来对子结点进行缩放补偿，使得子节点不会受到父节点的缩放变化影响。&lt;/p&gt;

&lt;p&gt;为了更准确的定位问题发生的源头，我们使用Maya针对缩放补偿功能制作了一段简化的测试模型，该模型仅有4个骨骼节点，其中”joint2″带有缩放变化，Test1.fbx开启了缩放补偿，而Test2.fbx则关闭了缩放补偿。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2021/01/Test1.gif&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2021/01/Test2.gif&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;通过对文件内容进行对比（将FBX使用ASCII格式保存）我们可以发现两段动画唯一不同的字段为节点的”InheritType”（启用SSC为2，未启用SSC为1）&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2021/01/InheritType.png&quot; alt=&quot;InheritType&quot; /&gt;&lt;/p&gt;

&lt;p&gt;查看FBX SDK的官方文档：&lt;a href=&quot;https://help.autodesk.com/view/FBX/2017/ENU/?guid=__cpp_ref_class_fbx_node_html&quot;&gt;Class FbxNode&lt;/a&gt; 该字段是用来描述子节点是否受父节点的变换影响的。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;These settings determine how transformations must be applied when evaluating a node’s transformation matrix. The possible values are: &lt;br /&gt;
 • eInheritRrSs : Scaling of parent is applied in the child world after the local child rotation. &lt;br /&gt;
 • eInheritRSrs : Scaling of parent is applied in the parent world. &lt;br /&gt;
 • &lt;strong&gt;eInheritRrs : Scaling of parent does not affect the scaling of children&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;由此我们可以确认对于SSC功能FBX文件格式本身是支持的，这个信息不会因为将动画资源以FBX格式导出而丢失。&lt;/p&gt;

&lt;p&gt;在另一篇来自AutoDesk的文档中也明确提到了在&lt;strong&gt;使用Maya为Unity项目制作动画资源时，应当明确关闭SSC功能&lt;/strong&gt;：&lt;a href=&quot;https://knowledge.autodesk.com/support/maya/troubleshooting/caas/simplecontent/content/turning-segment-scale-compensate-maya-how-to-make-maya-rigs-play-nice-unity.html&quot;&gt;Turning Off Segment Scale Compensate in Maya: How to make Maya rigs play nice with Unity&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;when you scale a parent joint in Maya using scale compensation, it creates an offset for child joint rather than scaling it. Unity hates this and weird things can happen as a result.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;之后我们将两段动画在DCC工具中、Unreal引擎中以及Win10 3D查看器中均可以看到如上图所示的动画效果，而在导入到Unity工程中后，两段动画均显示为Test2的动画效果。至此&lt;strong&gt;我们基本可以确认问题是由于Unity引擎在导入动画资源进行的数据转换操作时引起的&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;PS：另一篇文档关于Scale compensation的官方文档，其中提到了SSC是Maya独有的功能，而MAX并不支持：&lt;a href=&quot;https://download.autodesk.com/us/fbx/FBX_Maya_online/files/WS73099cc142f48755-3d114b751181c40f14b1283.htm?_ga=2.113840783.96561652.1611223408-907670307.1610969916&quot;&gt;Scale compensation&lt;/a&gt;&lt;/p&gt;

&lt;h1 id=&quot;unreal的实现&quot;&gt;Unreal的实现&lt;/h1&gt;

&lt;p&gt;根据Unreal官方文档，Unreal是支持Non-uniform缩放动画的：&lt;a href=&quot;https://docs.unrealengine.com/en-US/AnimatingObjects/SkeletalMeshAnimation/NonUniformScale/index.html&quot;&gt;Non-Uniform Scale Animation&lt;/a&gt; 在前面的测试中我们也证实了该功能，此外我们也通过调查Unreal的源代码来了解了Unreal是如何实现对Non-uniform缩放动画的支持的。在“&lt;strong&gt;/Engine/Source/Editor/UnrealEd/Private/SkeletalMeshEdit.cpp&lt;/strong&gt;”的函数&lt;strong&gt;UnFbx::FFbxImporter::ImportAnimation()&lt;/strong&gt;中：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2021/01/UnrealImportAnim.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;可以看到在Unreal导入动画进行Resample的过程中，使用了FBXSDK的EvaluateGlobalTransform接口来获取骨骼节点的变换矩阵，通过调试我们可以发现该接口可以自动根据不同的InheritType得到该节点带有正确缩放信息的变换矩阵，而在最后转换为Unreal内部的变换数据结构（FTransform）时，还会对父节点的变换信息进行一个相对变换的计算，其中即会根据父节点的缩放信息来反算子节点的补偿缩放值。&lt;/p&gt;

&lt;h1 id=&quot;unity的实现&quot;&gt;Unity的实现&lt;/h1&gt;

&lt;p&gt;最后我们再来看看Unity引擎的源代码，来确认这个问题的最后一块拼图。在“&lt;strong&gt;/Modules/AssetPipelineEditor/Public/ModelImporting/FBXImporter/Animation.cpp&lt;/strong&gt;”的函数&lt;strong&gt;static void ImportAnimationTake()&lt;/strong&gt;中：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2021/01/UnityImportAnim.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;在Unity引擎中导入动画进行Resample过程时，直接使用了各个骨骼节点（FbxNode）的&lt;a href=&quot;https://help.autodesk.com/view/FBX/2017/ENU/?guid=__files_GUID_C35D98CB_5148_4B46_82D1_51077D8970EE_htm&quot;&gt;Transform Data&lt;/a&gt;的GetCurve()接口来获取的变换曲线，之后再将曲线转换为Unity内部的变换数据结构的，这种方式下当访问到受父节点缩放影响而需要进行缩放补偿的子节点时，由于GetCurve不会参考InheritType的影响，而返回的曲线为空（如果子节点本身没有其他变化信息），所以子节点的缩放补偿信息会在导入的过程中被完全丢失掉。&lt;/p&gt;

&lt;h1 id=&quot;结论&quot;&gt;结论&lt;/h1&gt;

&lt;p&gt;对于带有Non-uniform动画资源的功能支持的问题上，本质上是因为不同的引擎对于动画资源处理上的逻辑不同而导致的，Unity总体上对动画的缩放支持比较有限（Humanoid则完全不支持缩放），官方给出的建议可以绕过这个限制，但会因为额外增加的骨骼节点，对CPU和内存都有些额外的消耗，不过我也特别针对这部分进行了性能测试，而测试的结果也没有发现特别大的性能负担，综合所有已知信息，也确实是目前解决这个问题性价比最好的解决方案了。&lt;/p&gt;

        </description>
        <pubDate>Sun, 24 Jan 2021 13:48:09 +0000</pubDate>
        <link>/2021/scaling-animation-in-unity.html</link>
        <guid isPermaLink="true">/2021/scaling-animation-in-unity.html</guid>
      </item>
    
      <item>
        <title>在Unreal中使用Swift库</title>
        <description>
          
          &lt;p&gt;最近工作中遇到个很棘手的问题，就是项目中用到的一个SDK在iOS平台上的版本中使用了Swift库来实现其中的部分功能，SDK在Android平台上集成没有遇到任何问题，但是在iOS上却遇到了各种各样的问题。现在让我们来回顾一下我掉进这个坑一周以来的发现。&lt;/p&gt;

&lt;p&gt;首先映入眼帘的是链接的问题：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Undefined symbols for architecture arm64:
&quot;__swift_FORCE_LOAD_$_swiftCompatibilityDynamicReplacements&quot;, referenced from:
l18787 in XXXXXSDK
l18872 in XXXXXSDK
l19410 in XXXXXSDK
&quot;__swift_FORCE_LOAD_$_swiftCompatibility51&quot;, referenced from:
l18786 in XXXXXSDK
l18871 in XXXXXSDK
l19409 in XXXXXSDK
&quot;__swift_FORCE_LOAD_$_swiftCompatibility50&quot;, referenced from:
l18785 in XXXXXSDK
l18870 in XXXXXSDK
l19408 in XXXXXSDK
ld: symbol(s) not found for architecture arm64
Error: clang: error: linker command failed with exit code 1 (use -v to see invocation)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;很蹊跷的是同样是iOS平台的framework库，如果是使用Objective-C编写的库，那么使用Unreal的标准库导入流程不会有任何问题，但是一旦引入了Swift库，就会遇到上述的链接问题。&lt;/p&gt;

&lt;p&gt;尝试过程中，我们通过将系统级的swiftCompatibility*.a文件手动拷入UE工程中，竟然编译通过了，但是很遗憾的是程序运行起来立刻便会发生Crash。于是我们决定先抛开UE，尝试在原生的Xcode工程中研究明白引入Swift库究竟会带来什么样的变化。&lt;/p&gt;

&lt;h1 id=&quot;damn-you-swift&quot;&gt;Damn you! Swift&lt;/h1&gt;

&lt;p&gt;新建了空的Xcode原生工程，引入了之前依赖了Swift库的framework，果然重现了一模一样的链接错误，问题到这里看来和UE的关系并不大了，应该还是Xcode和苹果开发自己这边有些什么阴人的套路，老实说这个时候我的心情真的是相当绝望的，这些年来一直想躲开Swift的我终于还是躲不开了吗？这真的是逼着我去学最不想学的东西啊……没办法，只能抱着当年60分及格万岁的想法，硬着头皮研究吧……&lt;/p&gt;

&lt;p&gt;看到StackOverFlow有人提到类似的问题可以通过简单的在Xcode工程里拖入一个空的Swift文件的方式来解决？试了一下，嘿！还真灵，Swift什么内容都不用有，一个空文件，Xcode就能“智能”的在后台帮你把工程链接环境搞搞好（工程文件还看不出变化），能编！还能运行！这招灵是灵，StackOverFlow上用了的人都竖大拇指，但UE又没有接口让你搞个Swift文件进去。苹果我求求你，真不用你搞什么“智能”，你还是直接告诉我们需要设置哪里就好了。搜不到，真就搜不到，一点有用的东西都搜不到，苹果的开发支持也告你就拖个空Swift文件进去就好了……&lt;/p&gt;

&lt;p&gt;苹果我谢谢你全家。&lt;/p&gt;

&lt;p&gt;长话短说，经过若干天一系列惨烈的实验之后，我们终于成功在不拖入空Swift文件的前提下，让原生的Xcode工程在引入使用Swift库的framework后，成功的编译及运行，你需要在Xcode的工程中进行以下三项设置：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;在”Library Search Paths”中添加”$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)”和”$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)”&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;设置”Always Embed Swift Standard Libraries”为YES&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;在”Runpath Search Paths”中添加”/usr/lib/swift”和”@executable_path/Frameworks”并且务必保证为以上的顺序&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;其中第一条即可以让程序正确编译通过，但是这个地方是有几个暗坑的，$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)目录下就是系统用来存放swiftCompatibility*.a的目录，但是如果你的framework库是使用Xcode11编译的，而工程是使用Xcode12编译的话，那么不知道处于什么原因，即使你正确地设置了这个路径，链接器也无法正确的进行链接。这个暗坑在我们完全理解这些现象之前折磨了我们整整好几天。如果你不能保证使用你的framework库的开发者也都是用相同的Xcode编译的话，&lt;strong&gt;我的建议还是将你编译framework库用到的系统.a文件显式的拷贝至工程进行链接，这样即使别人使用不同的Xcode进行开发也不会遇到链接的问题&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;第2、3条解释起来也是需要费一点口舌的。首先我们需要知道的在iOS平台上Swift库只有动态库的形式存在的，但是在老一些iOS系统上并没有这个库（iOS12.2以前那时候Swift都还没有呢），那怎么办？iOS12.2以前就准备放弃了吗？苹果给你的解决方案就是勾选这个”Always Embed Swift Standard Libraries”选项，勾选了以后Xcode打包的时候会将兼容版本的Swift库拷贝至应用程序的”Frameworks”目录下，然后”Runpath Search Paths”则是决定程序运行时去哪里找这些动态库，添加上对应的”@executable_path/Frameworks”目录后，这样老设备上动态库也有的找，也有的用。&lt;/p&gt;

&lt;p&gt;你以为这样就行了吗？不行，在iOS高于12.2的新设备上跑起来照样Crash，告诉你”This copy of libswiftCore.dylib requires an OS version prior to 12.2.0.”，你考进去的动态库是专门给老设备用的，新设备上还必须得用人家系统里最新的！所以还得在”Runpath Search Paths”里添加”/usr/lib/swift”并且将其置于应用程序目录之前，以便在新设备上可以优先搜索到系统版本的Swift库。&lt;/p&gt;

&lt;h1 id=&quot;在unreal4中的实现&quot;&gt;在Unreal4中的实现&lt;/h1&gt;

&lt;p&gt;到此为止，我们已经将如何在原生Xcode工程中正确的集成使用了Swift库的framework的问题解决了，下一步该是如何在UE里将上述的这些改动应用上。&lt;/p&gt;

&lt;p&gt;“Library Search Paths”还是比较容易的，UBT开放了接口，可以在*.build.cs中通过添加如下代码来实现（或者明确的将.a拷贝至UE工程内再通过PublicAdditionalLibrary添加）：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;PublicSystemLibraryPaths.Add(&quot;/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphoneos&quot;);
PublicSystemLibraryPaths.Add(&quot;/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.0/iphoneos&quot;);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;但剩下两项我们并没有在UBT中找到开放的接口供我们修改，在有限的尝试失败后，我阅读了一些UBT的代码，最终我们决定通过修改UBT来实现上述改动：&lt;/p&gt;

&lt;p&gt;1. 修改/Engine/Source/Programs/UnrealBuildTool/ProjectFiles/Xcode/XcodeProject.cs中AppendPlatformConfiguration函数：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2020/11/xcodeproject.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;2. 修改/Engine/Source/Programs/UnrealBuildTool/Platform/IOS/IOSToolChain.cs中GetLinkArguments_Global函数：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2020/11/iostoolchain.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;总结&quot;&gt;总结&lt;/h1&gt;

&lt;p&gt;回过头再看这个问题，原因其实是两部分，一个是苹果在Xcode对于Swift库的包含引用的一些特殊性的机制；另一个是Unreal在iOS上对于Swift库的支持目前看来还是没有考虑到的。更深层次的原因就更多了，UBT中大量平台相关的设置都是直接写死在代码中的，如果项目中有些平台相关的特殊改动，大概率是躲不开修改UBT源码的；再有就是苹果对于Swift这门语言从设计到开发到使用推广，处处展现着欠考虑的一面，各种补丁还要想办法做兼容，搞得人各种狼狈，最后苦的还是开发者自己。&lt;/p&gt;

&lt;p&gt;说实话，这种知识真的是没什么用的知识，完全没有任何积累，因为大概率过上一两年，苹果再大改上一版Xcode，这些选项全给你换一套新名字，再给你藏到犄角旮旯，完事再推一套新的APIs，你重新研究去吧……现在费这么多口舌把他写出来，是因为我在研究这个问题的过程中国内外基本搜不到有用的信息，虽然可能踩到这个坑里的人很少，但希望万一真有掉进来的，希望这篇唠叨能帮他早一点跳出去吧。&lt;/p&gt;

        </description>
        <pubDate>Thu, 26 Nov 2020 15:14:52 +0000</pubDate>
        <link>/2020/zai-unreal-zhong-shi-yong-swift-ku.html</link>
        <guid isPermaLink="true">/2020/zai-unreal-zhong-shi-yong-swift-ku.html</guid>
      </item>
    
      <item>
        <title>Wwise资源容量与内存优化</title>
        <description>
          
          &lt;p&gt;最近在工作中帮助项目进行音频相关的包体容量和内存用量上的优化，我在过往的工作中其实较少接触音频相关的工作，所以这段时间也算是学到了很多之前不够了解的新知识，在这里把这段时间的工作和心得写下来权做笔记。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2020/05/wwise.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;目前项目中的音频模块功能使用了著名的第三方音频SDK组件Wwise。比起常见引擎比如Unity、Unreal内建的音频功能，Wwise的功能还是相当强大的，提供了包括混响、渐变过渡、动态变频等功能，音频设计师甚至还可以在不需要程序员的帮助下直接在Wwise中完成很多诸如条件、随机的逻辑操作。而且Wwise提供了功能强大的Profile工具来放便开发人员监控音频模块的使用情况。不仅仅给予了音频设计师极大的发挥空间，也让程序员更容易了解音频模块的资源使用情况。如果项目的规模、预算较大，确实可以考虑集成Wwise来提高开发效率。&lt;/p&gt;

&lt;h1 id=&quot;容量计算公式&quot;&gt;容量计算公式&lt;/h1&gt;

&lt;p&gt;音频资源在容量上的性质比起美术资源，比如贴图会显得更加线性且易于计算。其计算方法不仅仅适用于游戏音频的开发与制作，而是适用于整个数字音乐领域，数字音乐资源体积大小取决于四个要素：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;采样率&lt;/strong&gt;：也就Sample rate，以赫兹Hz为单位，指的是每秒钟记录声音变化的次数，越高则声音的听上去越自然流畅，通常CD音乐的标准是44100Hz，而高于48000Hz的声音因人耳朵的生理极限通常被认为是不必要的。要注意的是虽然同样是以Hz作为单位，采样率与我们常说人耳能听到的低高音范围（频谱响应）并不是一回事儿。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;位深&lt;/strong&gt;：位深指的是每一次采样时用来记录声音变化所使用的位宽，通常有16位和24位。16位意味着你听到的声音可以有2的16次方也就是65536种变化。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;声道&lt;/strong&gt;：立体声或者是单声道，决定音频是否使用两条音轨来对应左右耳的不同表现。值得注意的是，目前似乎无论使用什么样的压缩方式，使用立体声都意味着容量相对单声道的翻倍。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;时间&lt;/strong&gt;：一秒就是一秒，至少目前，无论什么压缩方式，资源容量在时间维度上是完全线性的变化&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;根据上面这些信息，我们可以很容易的计算出一张74分钟42秒（极限容量）的CD格式的音乐所需要的容量：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;44100(Hz) * 16(bits) * 2(stereo) * (74 * 60 + 42) = 771.8MB
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;CD音质在数字音乐中也算是品质相当好的了，体积也是相当大的，实际项目开发中是很难接受这种无压缩的格式给容量上带来的负担的。在互联网领域，有着像MP3这样的压缩格式，以有限的音质损失换取文件体积上极大的缩减。在游戏领域对体积不像互联网领域那么敏感，但却对性能方面会有些要求。&lt;/p&gt;

&lt;h1 id=&quot;压缩格式&quot;&gt;压缩格式&lt;/h1&gt;

&lt;p&gt;以Wwise为例，Wwise提供了ADPCM、Vorbis、Opus几种压缩格式可供实际开发中选择：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;ADPCM&lt;/strong&gt;：提供约1：4的固定压缩比率，较低的CPU负担&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Vorbis&lt;/strong&gt;：默认质量提供1：9~12的高压缩率，CPU的计算成本会比ADPCM高一些&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Opus&lt;/strong&gt;：Vorbis的改进版本，理论上会比Vorbis有更好的压缩率和更低的CPU成本，在我们的测试中表现和Vorbis相差其实不大&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;根据官方文档的建议，ADPCM格式比较适合游戏内的长度较短，复发率非常高的音效，比如像射击游戏中的枪声、RPG的技能音效等；Vorbis/Opus比较适合长度较长，游戏内发生数不高的一类音效，比如背景音乐、环境声以及剧情人物对话等等。&lt;/p&gt;

&lt;h1 id=&quot;tips&quot;&gt;Tips&lt;/h1&gt;

&lt;p&gt;在实际测试中，发现了另外两点值得注意的细节：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;一个是人声类的音频可以设置更高的压缩率（较低的质量），因为人声的发声频率范围较小，非常禁得住压缩而不会丢失太多的细节，在实际测试中使用Vorbis quality 2单声道的压缩方式（作为木耳朵的我很难听出区别）可以将每分钟的成本降至约500KB，这意味着游戏中一个小时的剧情语音仅需要使用40MB不到容量。我一直觉得剧情对话全语音是个很奢侈的事情，现在这么看至少在容量上还是可以承受的，相反可能声优录制的成本才是开发商特别需要关注的。&lt;/li&gt;
  &lt;li&gt;另一个是在保证表现的同时应该尽量使用单声道，除了有些内容比如背景音乐、环境音、UI菜单音效（音效部的同学特别提到）等需要保证声音的表现力外，像游戏场景内的点声源，人物对话等使用单声道是完全没有太大问题的，因为相比起各种高端的压缩算法，都比不过使用单声道降低资源容量来的直接有效。&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;成本推算&quot;&gt;成本推算&lt;/h1&gt;

&lt;p&gt;优化过后根据上述分类我们可以大致推算出不同的音效资源的使用成本：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;背景音乐&lt;/strong&gt;：使用Vorbis/Opus格式，双声道，默认压缩率，&lt;strong&gt;每分钟约800KB&lt;/strong&gt;的成本，一张CD长度的音乐压缩后约64MB&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;短音效&lt;/strong&gt;：使用ADPCM格式，根据需要设置单/双声道，Auto medium压缩率，&lt;strong&gt;双声道每分钟约2.3MB的成本&lt;/strong&gt;，单声道折半&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;剧情对话类&lt;/strong&gt;：使用Vorbis/Opus格式，单声道，较低质量，&lt;strong&gt;每分钟约500KB&lt;/strong&gt;的成本，1个小时的长度可以压缩至40MB以内&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;内存&quot;&gt;内存&lt;/h1&gt;

&lt;p&gt;游戏项目中关于音频的内存优化部分可讲的并不多，因为不存在像美术贴图资源那样需要打包或者存在解压缩的步骤。一个简单可靠的加/卸载机制和合理使用他们的时机足以出色的完成音频资源内存管理的工作。结合Wwise的SoundBank机制，可以总结下面几条Tips：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;常驻内存的音效&lt;/strong&gt;：你终归是需要有部分音效常驻内存的，一些很短、很高复发率并且随时会发声的音效，比如暂停菜单的音效。这一类的音效要避免反复加/卸载，增加内存碎片风险的同时浪费了I/O的性能，我们需要做的其实仅仅是合理的划分这部分音效资源并控制它的规模。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;流&lt;/strong&gt;：对于游戏内固定数量的长音效，比如背景音乐、剧情对话、环境声，使用流来播放非常有必要，相当于用游戏进行时一定的I/O性能来换取极大的内存节省。要注意控制使用流播放的音频可能的最大并发数&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;按照游戏逻辑来划分SoundBank&lt;/strong&gt;：这样我们可以通过仅加载必要的SoundBank来避免内存使用上的浪费，比如按照不同地图特有的环境音效，按照怪物种类、角色、武器来划分，这样在进入关卡战斗时我们可以根据预知的关卡和我方角色来仅加载必要的音频资源&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;结论&quot;&gt;结论&lt;/h1&gt;

&lt;p&gt;对于游戏项目开发来说，除非是对音频的表现有特殊的要求，对一般的项目来看音频部分的实现与使用在技术层面上的优化还都是相对比较好理解的，更需要强调是项目能够对于音频功能合理的设计和正确的使用，避免浪费不要的软硬件资源，把好钢用在刀刃上。&lt;/p&gt;

        </description>
        <pubDate>Sun, 03 May 2020 12:36:28 +0000</pubDate>
        <link>/2020/wwise-zi-yuan-rong-liang-yu-nei-cun-you-hua.html</link>
        <guid isPermaLink="true">/2020/wwise-zi-yuan-rong-liang-yu-nei-cun-you-hua.html</guid>
      </item>
    
      <item>
        <title>使用Autohotkey为你的键盘添加Fn层</title>
        <description>
          
          &lt;h1 id=&quot;60键盘&quot;&gt;60%键盘&lt;/h1&gt;

&lt;p&gt;一直以来，我都是60%键盘的爱好者，所谓60%键盘就是指键盘去除了小键盘、功能键区(F1~F12)、方向键和编辑键区，仅保留打字键区的键盘。60%键盘的优点有两个是我个人特别离不开的：一个是占用更小的桌面面积；另一个也是最重要的一点就是当你双手操作键盘的时候完全不用移动用于支撑的手掌底部，从而让你的敲击效率起飞。当然也不是没有代价的，那就是比起全键盘，所有省去的那些键必须要通过组合键的方式来进行。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2020/03/my60keyboard.jpg&quot; alt=&quot;这是我目前最满意的一把了&quot; /&gt;&lt;/p&gt;

&lt;p&gt;当然我想先说明的是这个议题本身就是带着强烈的个人偏好的，并没有所谓怎样更好的说法。比如有些人可能本身就是更喜欢104全键盘摆在桌上的那份踏实感，而且大部分人会更习惯更高的鼠标速度而不需要过分大的鼠标移动区域，再或者别忘了还有人在用轨迹球鼠标或者触摸板呢！我写这些也只是希望能给朋友们提供一点可能的“灵感”而已。&lt;/p&gt;

&lt;p&gt;60%键盘会占用更小的桌面面积，那么就给右侧的鼠标留下更大的滑动空间，就个人而言因为我个人是比较重度的FPS玩家，鼠标速度也因此一直习惯设置的非常低，43×38厘米的大号鼠标垫对我来说才刚刚勉强可以用，在习惯了60%键盘后，省出来的桌面面积可以容许我继续暂时保持着低鼠标速度的习惯，现在别说104全键盘了，即使84键的键盘摆上我的桌面也会让我多少觉得有些空间局促。&lt;/p&gt;

&lt;p&gt;如果说节省桌面面积更多的是对我玩游戏有帮助，那操作键盘时不需要移动手掌这点则是完全集中在提升我工作中的使用效率了。作为程序员，每天和代码打交道，也算是半个文字工作者了，我相信在经过一天高强度的编码工作后，会有很多人认同的一点便是，你可能经常需要迫不得已要把手离开键盘去抓一下鼠标完成一些操作然后再回到键盘才能继续之前的编码工作，不要小看这个微小的“中断”，当你每天需要反复进行几百次这样的“中断”时，累计下来浪费的时间可能是惊人的，更不能忽视的是它对你思路的打断和心情的影响。&lt;/p&gt;

&lt;p&gt;全面掌握快捷键是解决上述问题的一个好办法，现代开发工具都提供了详尽的快捷键方案和强大的自定义功能，而更进一步的话Vim/Emacs等工具更是这方面的绝佳助手，因为他们最初的使用情景就是没有鼠标的终端环境，我个人选择了Vim，而且我认为这些工具的学习其实是你程序员职业生涯中一笔非常划算的投资，虽然它们可能有着更难的学习曲线，但真的是越早学习越划算。&lt;/p&gt;

&lt;p&gt;好，我们假设你已经可以熟练的操作键盘完成编程中乃至桌面系统中绝大多数工作内容了，这时你会发现原来不用去触碰鼠标是如此的快乐，以至于你会开始致力于进一步学习如何能尽量的减少操作鼠标的频率了，然后同时你会开始慢慢发现即使是集中在键盘上工作时，当你需要操作方向键、PageUp/PageDown等编辑键、F1~F12、Esc等键时，因为距离的原因，还是需要抬起手掌，按下你想按的键，再回来用食指重新找回F或者J的时候，会让你重现起“中断”并拿起鼠标的不快感。当你到达这一步的时候，那么恭喜你，你可以发现60%键盘最美妙的地方了，你现在可以认真的考虑一下要不要尝试一下使用60%键盘了，因为它可以让你通过Fn层实现完全无需抬起手掌即可完成104键全键盘的键位操作。&lt;/p&gt;

&lt;h1 id=&quot;autohotkey&quot;&gt;Autohotkey&lt;/h1&gt;

&lt;p&gt;目前60%键盘的社区里流派众多，并且看过了上面那些矫情的描述之后，相信你也可以理解最终走到选择60%键盘这一步的用户会有着执拗的客制化的需求，所以目前60%键盘并没有能形成一个大多数人认可的布局或解决方案，除了HHKB、Filco Minilar air、Leopold FC660c这类大厂的60%键盘有自己坚持的布局与方案外，大部分小厂或淘宝店都是基于一个叫&lt;a href=&quot;https://wiki.geekhack.org/index.php?title=GH60&quot;&gt;GH60&lt;/a&gt;的开源可编程键盘的项目来开发自己的60%键盘的。这一类键盘的优势是可以自己指定键盘的布局，不过也因此在购买选择上你会看到一个类似“百家争鸣”的市场：有的是通过软件来设置，有的通过一系列复杂的键位操作来设置，还有的需要通过驱动刷固件的古老方式，而且大部分的做工和质量很难和传统的大厂相媲美。在我用过的几把60%键盘里，每一把都或多或少的有些让人不满意的地方，以至于最终让我走到了自己动手完全从头组装键盘的地步……&lt;/p&gt;

&lt;p&gt;看到这里你也不必感到沮丧，因为今天其实我的本意是想介绍一种零成本的60%键盘实现（测试）方案，它可以帮助你在不做任何实质投入的情况下测试60%键盘究竟适不适合你，是不是你需要的。而且方法也很简单：Windows+Autohotkey！&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.autohotkey.com/&quot;&gt;Autohotkey&lt;/a&gt;是Widnows平台上一款老牌的热键编辑软件，支持键位调换、热键修改以及按键宏等功能，非常强大，我最早使用的几年里一直仅仅是用它来做些绑定音量调节和屏蔽某些按键这类的简单的事，直到我开始自己组装键盘了，我才想起来是不是可以利用Autohotkey在软件层面上让普通键盘也拥有可编程的Fn层，简单的阅读官方文档+摸索测试后，证明是完全行得通的，在这里我贴一个我自己使用习惯的实现脚本，有兴趣尝试的朋友可以根据自己的情况做些调整来亲自尝试一下，脚本非常简单，看懂花不了5分钟，即使脚本中没有你想实现的功能，阅读&lt;a href=&quot;https://wyagd001.github.io/zh-cn/docs/AutoHotkey.htm&quot;&gt;官方的文档&lt;/a&gt;(中文)相信也不会花费太多的精力。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;; Disalbe Layer key and all the combinations
LCtrl::return
!LCtrl::return
+LCtrl::return
^LCtrl::return
!+LCtrl::return
^!LCtrl::return
^+LCtrl::return
^!+LCtrl::return

; All layers
CapsLock::LControl
`::Esc
Esc::`

; Layer 2
#If, GetKeyState(&quot;LCtrl&quot;, &quot;P&quot;) and !GetKeyState(&quot;ScrollLock&quot;, &quot;T&quot;)
j::Down
k::Up
h::Left
l::Right
o::PgDn
u::PgUp
i::Home
n::End
Backspace::Del
\::CapsLock
1::F1
2::F2
3::F3
4::F4
5::F5
6::F6
7::F7
8::F8
9::F9
0::F10
-::F11
=::F12
q::Media_Prev
w::Media_Play_Pause
e::Media_Next
a::Volume_Down
s::Volume_Up
d::Volume_mute
c::Launch_App2

; Use scrolllock as new number pad&apos;s toggle
#If, GetKeyState(&quot;ScrollLock&quot;, &quot;T&quot;)
j::1
k::2
l::3
u::4
i::5
o::6
;::NumpadMult
p::/
n::Enter
,::+
m::-
h::Backspace

#If, !GetKeyState(&quot;LCtrl&quot;, &quot;P&quot;)
\::Backspace
Backspace::\
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2020/03/keyboard.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;上图是我脚本的实现示意，绿色框内的为涉及到键位，具体的可以看相应按键的右下角所表明的Fn层按键，简单的讲分为这样几点：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Capslock键位让给Ctrl键：这个算是使用HHKB的后遗症，也有些人喜欢把这个键让给Fn键，都不错，总之我坚持认为这么顺手的位置放一个使用率如此低（至少对我而言）的按键是一种巨大的浪费&lt;/li&gt;
  &lt;li&gt;Esc和“`~”键对调：标准键盘下Esc键对我这种手小的人来说够起来还是需要抬起手掌的，而Esc的使用频率比~可要高的多了&lt;/li&gt;
  &lt;li&gt;Backspace和“|”键对调：这个也算是HHKB后遗症了，Backspace作为使用频率相当高的按键理应使用更易达到的位置，当然我试过不同的键盘里，这一条只适用于OEM键帽高度的键盘，比如通常是Low profile的薄膜键盘，我也会觉得还是原位置更顺手&lt;/li&gt;
  &lt;li&gt;左Ctrl作为Fn键：这个可能是比较会有争议一个方案，我之所以觉得这样非常方便是因为我按下Fn的方式是用手掌肚了压下按键而不是使用小拇指，这样的好处几乎不需要移动左手，但我试过在不是OEM高度的键盘上是很难完成这个操作的，所以如果你真的是矮键帽党，也许用Capslock作为Fn键会是更好的选择&lt;/li&gt;
  &lt;li&gt;H/J/K/L：这个是Vim的使用习惯了，真的方便，用惯了以后你会明白我的感受的：）&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;其实说到键盘的话，真的有着说不完的话，不过已经今天嘟囔了这么多了，更多的我们可以留着下次再讨论吧。&lt;/p&gt;

        </description>
        <pubDate>Sun, 29 Mar 2020 14:16:32 +0000</pubDate>
        <link>/2020/shi-yong-autohotkey-wei-ni-de-jian-pan-tian-jia-fn-ceng.html</link>
        <guid isPermaLink="true">/2020/shi-yong-autohotkey-wei-ni-de-jian-pan-tian-jia-fn-ceng.html</guid>
      </item>
    
      <item>
        <title>经典多人网络游戏同步模型</title>
        <description>
          
          &lt;p&gt;网络游戏的同步模型是一个巨大的话题，为了适应不同的游戏模式和机制，游戏行业中在过去的几十年中开发出了很多种经典的模型，我们今天来讨论从雷神之锤3开始被奉为经典并影响了无数FPS游戏的网络同步机制，这种机制一直也是作为标准同步模型而集成在Unreal引擎中的。为了区别星际争霸、帝国时代等RTS游戏所使用的帧同步(Lockstep)，在国内很多从业者口中称这种同步模型为状态同步(client-server)。&lt;/p&gt;

&lt;p&gt;我在过去第一次参与Unreal项目的开发时接触到了这种同步模型，并对其原理进行了学习和了解，但内部的机制Unreal其实全部都帮你已经实现好了，俗话说的好——纸上得来终觉浅，绝知此事要宫刑！哦，不，是要躬行……所以最好的学习办法还是动手写一下。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/wp-content/uploads/2020/02/NetworkingReplication.gif&quot; alt=&quot;Demo screenshot&quot; /&gt;&lt;/p&gt;

&lt;p&gt;关于状态同步的模型有一个英文的系列文章很好的阐述了其原理及克服一些问题的方法，再动手写示例之前最好再复习一下其原理：&lt;a href=&quot;https://www.gabrielgambetta.com/client-server-game-architecture.html&quot;&gt;client server game architecture&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;示例工程下载：&lt;a href=&quot;https://github.com/ownself/NetworkingReplicationDemo&quot;&gt;Networking replication demo&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;权威服务器&quot;&gt;权威服务器&lt;/h2&gt;

&lt;p&gt;在状态同步模型中有一条最重要和基本的宗旨，就是要维护服务器计算结果的权威性，而不能相信任何来自客户端的关键性计算结果。这一切的根源在于令人深恶痛绝的作弊问题，作弊问题是一个长久以来困扰着游戏行业的问题，从反恐精英到绝地求生，使用状态同步模型的游戏一直就是作弊问题的重灾区，保证服务器的权威并不能100%的杜绝作弊问题，但确实可以极大的增加作弊的门槛。&lt;/p&gt;

&lt;p&gt;在状态同步模型中，客户端负责处理并将玩家的输入信息发送给服务器，由服务器来进行世界的计算和更新，再将更新后的世界信息发送回客户端来显示及反馈操作结果。&lt;/p&gt;

&lt;h2 id=&quot;客户端预测&quot;&gt;客户端预测&lt;/h2&gt;

&lt;p&gt;由服务器计算和更新再发送回客户端没有问题，但网络消息在发送过程中带来的延迟会极大的影响本地玩家的操作体验，而网络延迟又是物理上无法克服的。为了解决这个问题我们需要使用客户端预测的技术。&lt;/p&gt;

&lt;p&gt;客户端预测的技术可以克服网络延迟带来的不好体验，客户端在发送消息时需要带上消息序列编号并在本地缓存，等服务器传回经过权威计算的结果后再根据消息的序列编号对已经缓存在本地的结果进行核对，如果发生偏差，再进行矫正。要特别注意的是矫正的过程并非矫正出错编号的位置和状态，而是在出错的位置计算矫正偏差，再以此偏差应用到后续所有用于校验的等待缓存队列中，最后再在当前客户端的玩家身上应用这个矫正偏差。&lt;/p&gt;

&lt;h2 id=&quot;实体插值&quot;&gt;实体插值&lt;/h2&gt;

&lt;p&gt;现实的情况中，服务器计算和更新世界的频率会成为很重要的性能瓶颈，所以不应该也不可能保证以非常高的频率来进行计算和更新，这样就会直接导致客户端上玩家看到其他玩家的位移是跳跃且间断的，以一种离散的方式移动的，这是一个很糟糕的体验，为了保证客户端上玩家看到的更新是流畅的，我们可以使用一个很简单的技巧，即客户端并不是直接将从服务器收到的信息作用在本地，而是通过插值的方式将物体“流畅”的逐步更新到正确的位置。&lt;/p&gt;

&lt;p&gt;使用插值关键是需要客户端至少晚一个Tick来进行更新，实际上是以客户端增加少许延迟的代价来换取流畅的表现。&lt;/p&gt;

&lt;h2 id=&quot;滞后补偿&quot;&gt;滞后补偿&lt;/h2&gt;

&lt;p&gt;因为实施了客户端预测和实体插值的机制，所以在客户端上，本地玩家在更新上总是领先与其他同步玩家的，这使得一些和位置与更新内容息息相关的计算与判断变得有些棘手。比如在FPS游戏中，命中的判断至关重要，所以为了保证游戏体验，游戏开发者们会使用一个看上去不太正确的技巧，就是使用错序的消息内容来进行相关的判断（本地玩家超前，远程玩家滞后），并将相关的序列信息一同发送至服务器来进行权威性判断。因为服务器保存着世界中所有过往的历史信息，所以实际上服务器可以做到根据某个客户端的错序信息来进行权威性计算的，这样做是以牺牲一定的公平性来提升客户端本地玩家的体验的。&lt;/p&gt;

&lt;p&gt;在这次的示例工程中并没有实现滞后补偿机制。&lt;/p&gt;

&lt;h2 id=&quot;网络消息的错序处理&quot;&gt;网络消息的错序处理&lt;/h2&gt;

&lt;p&gt;由于网络传输过程中的延迟和不可控因素，难免会造成消息最终以错序的方式到达服务器，解决的办法是提高客户端发送的频率，先缓存一小段客户端消息再进行更新计算。这种方法可以增强消息错序的处理能力但会增加延迟，而提高客户端消息发送频率则可以反过来降低延迟的影响。《守望先锋》甚至设计了一个可变的更新频率机制，在服务器发现客户端消息丢包的情况下会通知客户端增加发送频率直到服务器端该客户端的消息队列重新回到正常水平。有兴趣的朋友可以去看看暴雪在GDC上做的相关演讲。&lt;/p&gt;

&lt;h2 id=&quot;网络消息的丢包处理&quot;&gt;网络消息的丢包处理&lt;/h2&gt;

&lt;p&gt;同样，网络传输中消息包的丢失也是不可避免的。当发生某些消息丢包或者遭遇超长的消息延迟时，目前业界通常的做法是在服务器上以该客户端上一次已知的输入消息来填充空缺的消息，因为在实际的情况中，大部分的输入消息是连续且相同的，玩家不可能以极高的频率疯狂的改变方向的。&lt;/p&gt;

&lt;h2 id=&quot;示例工程&quot;&gt;示例工程&lt;/h2&gt;

&lt;p&gt;在写这个示例工程的时候，确实让我对于状态同步网络模型中一些问题的处理细节有了更深的理解，因为写这个示例主要的目的还是加深理解，时间也很仓促，难免有些bug或者不合理的地方，如果有兴趣阅读，还望不吝指出其中可以改进或者存在的错误。非常感谢。&lt;/p&gt;

        </description>
        <pubDate>Thu, 06 Feb 2020 09:21:07 +0000</pubDate>
        <link>/2020/jing-dian-duo-ren-wang-luo-you-xi-tong-bu-mo-xing.html</link>
        <guid isPermaLink="true">/2020/jing-dian-duo-ren-wang-luo-you-xi-tong-bu-mo-xing.html</guid>
      </item>
    
  </channel>
</rss>
