Скоро уже будет лет 10 как я увяз в Unity и C#… Начинал наверно как и многие с MonoDevelop 🥴 Потом появился Sublime Text, которым я пользовался пару лет, классный и быстрый редактор, у меня даже была такая же заметка про его настройку. Но он был поменян на VS Code, который тогда начал активно развиваться и поддерживаться. Собственно, до сих пор им и продолжаю пользоваться.
Далее, почему я считаю VS Code хорошим выбором для разработки на Unity и C#, также список плагинов и настроек которые использую и рекомендую.
Почему VS Code, плюсы
- лёгкий и быстрый
- бесплатный и кроссплатформенный
- гибкая кастомизация
- отлично подходит для многопроектной работы
- хорошо дружит с Git
Он действительно быстрый. Если сразу начали с него и не с чем сравнить особо, то можно попробовать отрыть средний проект в Studio или Rider и убедиться, что это действительно так. Ну и огромное количество расширений на каждый чих. И полезных и не очень.
Минусы
- более слабая интеграция с Unity
- слабый рефакторинг по сравнению с Rider
- слабее отладка
- нет встроенной навигации по Unity API
Тут минусы только в контексте работы с Unity. Некоторые из них выходят как ни странно из «плюсов», например, слабая интеграция с Unity и хуже рефакторинг — это «плата» за быстроту, бесплатность и возможность в одном редакторе работать и с C#, и c TypeScript, Node.js и с прочими языками и фреймворками. Редактор не заточен под один язык или платформу, как Xcode например.
Расширения
- C# Dev Kit — ну это база, как говорится, официальное расширение от Microsoft, лучше OmniSharp: нормальный intellisense, поддержка C# 8–12, встроенный Roslyn анализатор, быстрая индексация
- Unity Tools — подсветка методов монобехов, ссылки на Unity доки, лучше навигация по Unity API
- Error Lens — отображение ошибок и варнингов прямо в строках (спёрто у Rider 😬)
- GitLens — навигация по истории, blame, ревью и прочие git радости
- EditorConfig for VS Code — настройка форматирования через стандартизированный формат
- Todo Tree — быстрый поиск и отображение TODO-шек
- Unity — официальное расширение Unity для VS Code: API, debugger, подсказки, навигация
- Monokai Pro — тема оформления
- eppz! — ещё тема оформления
Ниже мой файл конфигурации .editorconfig который вместе с расширением EditorConfig for VS Code показывает ошибки, варнинги в именовании полей, переменных и методов, а также форматирует код в соответствии с указанными правилами.
Конечно мой конфиг не эталон, он формировался со временем и все эти правила подбирались под нашу команду, так чтобы всех устраивало. В нём есть почти все директивы с которыми можно поиграться и настроить под себя.
# Dotnet code style settings:
[*.cs]
indent_style = space
indent_size = 4
insert_final_newline = true
charset = utf-8
# Sort using and Import directives with System.* appearing first
csharp_using_directive_placement = outside_namespace:silent
dotnet_sort_system_directives_first = true
dotnet_separate_import_directive_groups = false
# Avoid "this." and "Me." if not necessary
dotnet_style_qualification_for_field = false:refactoring
dotnet_style_qualification_for_property = false:refactoring
dotnet_style_qualification_for_method = false:refactoring
dotnet_style_qualification_for_event = false:refactoring
# Use language keywords instead of framework type names for type references
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
dotnet_style_predefined_type_for_member_access = true:suggestion
# Suggest more modern language features when available
dotnet_style_object_initializer = true:suggestion
dotnet_style_collection_initializer = true:suggestion
dotnet_style_coalesce_expression = true:suggestion
dotnet_style_null_propagation = true:suggestion
dotnet_style_explicit_tuple_names = true:suggestion
# Whitespace options
dotnet_style_allow_multiple_blank_lines_experimental = false
# IDE0055: Fix formatting
dotnet_diagnostic.IDE0055.severity = warning
# Newline settings
csharp_new_line_before_open_brace = false
csharp_new_line_before_else = false
csharp_new_line_before_catch = false
csharp_new_line_before_finally = false
csharp_new_line_before_members_in_object_initializers = false
csharp_new_line_before_members_in_anonymous_types = false
csharp_new_line_between_query_expression_clauses = false
csharp_new_line_between_members = true
# Indentation preferences
csharp_indent_block_contents = true
csharp_indent_braces = false
csharp_indent_case_contents = true
csharp_indent_case_contents_when_block = true
csharp_indent_switch_labels = true
csharp_indent_labels = flush_left
# Whitespace options
csharp_style_allow_embedded_statements_on_same_line_experimental = false
csharp_style_allow_blank_lines_between_consecutive_braces_experimental = false
csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = false
csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = false
csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = false
# # Prefer "var" everywhere
csharp_style_var_for_built_in_types = true:suggestion
csharp_style_var_when_type_is_apparent = true:suggestion
csharp_style_var_elsewhere = true:suggestion
# Prefer method-like constructs to have a block body
csharp_style_expression_bodied_methods = false:none
csharp_style_expression_bodied_constructors = false:none
csharp_style_expression_bodied_operators = false:none
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion
# Prefer property-like constructs to have an expression-body
csharp_style_expression_bodied_properties = true:none
csharp_style_expression_bodied_indexers = true:none
csharp_style_expression_bodied_accessors = true:none
# Suggest more modern language features when available
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
csharp_style_inlined_variable_declaration = true:suggestion
csharp_style_throw_expression = true:suggestion
csharp_style_conditional_delegate_call = true:suggestion
csharp_style_prefer_extended_property_pattern = true:suggestion
# Space preferences
csharp_space_after_cast = false
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_after_comma = true
csharp_space_after_dot = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_after_semicolon_in_for_statement = true
csharp_space_around_binary_operators = before_and_after
csharp_space_around_declaration_statements = do_not_ignore
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_before_comma = false
csharp_space_before_dot = false
csharp_space_before_open_square_brackets = false
csharp_space_before_semicolon_in_for_statement = false
csharp_space_between_empty_square_brackets = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_declaration_name_and_open_parenthesis = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false
csharp_space_between_square_brackets = false
# Blank lines
csharp_blank_lines_around_region = 0
csharp_blank_lines_inside_region = 0
csharp_keep_blank_lines_in_declarations = 1
csharp_remove_blank_lines_near_braces_in_declarations = true
csharp_blank_lines_between_using_groups = 1
csharp_blank_lines_after_using_list = 1
csharp_blank_lines_around_namespace = 1
csharp_blank_lines_inside_namespace = 0
csharp_blank_lines_after_file_scoped_namespace_directive = 1
csharp_blank_lines_around_type = 1
csharp_blank_lines_around_single_line_type = 1
csharp_blank_lines_inside_type = 0
csharp_blank_lines_around_field = 1
csharp_blank_lines_around_single_line_field = 1
csharp_blank_lines_around_property = 1
csharp_blank_lines_around_single_line_property = 1
csharp_blank_lines_around_auto_property = 1
csharp_blank_lines_around_single_line_auto_property = 1
csharp_blank_lines_around_accessor = 1
csharp_blank_lines_around_single_line_accessor = 1
csharp_blank_lines_around_invocable = 1
csharp_blank_lines_around_single_line_invocable = 1
csharp_keep_blank_lines_in_code = 0
csharp_remove_blank_lines_near_braces_in_code = false
csharp_blank_lines_around_local_method = 1
csharp_blank_lines_around_single_line_local_method = 0
csharp_blank_lines_before_control_transfer_statements = 0
csharp_blank_lines_after_control_transfer_statements = 0
csharp_blank_lines_before_block_statements = 0
csharp_blank_lines_after_block_statements = 0
csharp_blank_lines_around_block_case_section = 0
csharp_blank_lines_around_multiline_case_section = 0
csharp_blank_lines_before_case = 0
csharp_blank_lines_after_case = 0
# Access modifiers
dotnet_style_require_accessibility_modifiers = omit_if_default:warning
# Blocks are allowed
csharp_prefer_braces = true
csharp_preserve_single_line_blocks = true
csharp_preserve_single_line_statements = true
dotnet_diagnostic.IDE0001.severity = silent
dotnet_diagnostic.IDE0002.severity = warning
# Using directive is unnecessary.
dotnet_diagnostic.IDE0005.severity = warning
# invalid switch.
dotnet_diagnostic.IDE0010.severity = silent
# add braces.
dotnet_diagnostic.IDE0011.severity = warning
# IDE0040: Add accessibility modifiers
dotnet_diagnostic.IDE0040.severity = suggestion
# IDE0060: Remove unused parameter
dotnet_diagnostic.IDE0060.severity = warning
# IDE0052: Remove unread private member
dotnet_diagnostic.IDE0052.severity = warning
# IDE0059: Unnecessary assignment to a value
dotnet_diagnostic.IDE0059.severity = warning
# CA1012: Abstract types should not have public constructors
dotnet_diagnostic.CA1012.severity = warning
# CA1822: Make member static
dotnet_diagnostic.CA1822.severity = warning
dotnet_diagnostic.IDE0051.severity = warning
dotnet_diagnostic.IDE0160.severity = warning
dotnet_diagnostic.IDE0161.severity = warning
# Prefer "var" everywhere
dotnet_diagnostic.IDE0007.severity = warning
csharp_style_var_for_built_in_types = true:warning
csharp_style_var_when_type_is_apparent = true:warning
csharp_style_var_elsewhere = true:warning
# csharp_style_allow_embedded_statements_on_same_line_experimental
dotnet_diagnostic.IDE2001.severity = silent
# csharp_style_allow_blank_lines_between_consecutive_braces_experimental
dotnet_diagnostic.IDE2002.severity = warning
# csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental
dotnet_diagnostic.IDE2004.severity = warning
# csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental
dotnet_diagnostic.IDE2005.severity = warning
# csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental
dotnet_diagnostic.IDE2006.severity = warning
# CS4014 Because this call is not awaited, execution of the current method continues before the call is completed
dotnet_diagnostic.CS4014.severity = silent
# csharp_style_implicit_object_creation_when_type_is_apparent
dotnet_diagnostic.IDE0090.severity = silent
# IDE0035: Remove unreachable code
dotnet_diagnostic.IDE0035.severity = warning
# IDE0130: Namespace does not match folder structure
dotnet_diagnostic.IDE0130.severity = silent
# IDE0071: Simplify interpolation
dotnet_diagnostic.IDE0071.severity = suggestion
dotnet_style_prefer_simplified_interpolation = true
# IDE0041: Use is null check
# Unity objects don't support null checking so best to use ReferenceEquals(value, null)
dotnet_diagnostic.IDE0041.severity = error
dotnet_style_prefer_is_null_check_over_reference_equality_method = false
# .NET Unnecessary code rules
[*.{cs,csx,cake,vb,vbx}]
dotnet_code_quality_unused_parameters = all:warning
dotnet_remove_unnecessary_suppression_exclusions = none:warning
# Constants are UPPERCASE
dotnet_naming_rule.constants_should_be_upper_case.severity = error
dotnet_naming_rule.constants_should_be_upper_case.symbols = constants
dotnet_naming_rule.constants_should_be_upper_case.style = constant_style
dotnet_naming_symbols.constants.applicable_kinds = field, local
dotnet_naming_symbols.constants.required_modifiers = const
dotnet_naming_style.constant_style.capitalization = all_upper
# Private should starts underscore
dotnet_naming_rule.private_members_with_underscore.symbols = private_fields
dotnet_naming_rule.private_members_with_underscore.style = prefix_underscore
dotnet_naming_rule.private_members_with_underscore.severity = error
dotnet_naming_symbols.private_fields.applicable_kinds = field
dotnet_naming_symbols.private_fields.applicable_accessibilities = private
dotnet_naming_style.prefix_underscore.capitalization = camel_case
dotnet_naming_style.prefix_underscore.required_prefix = _
# Public fields should be PascalCase
dotnet_naming_rule.public_fields_should_be_pascalcase.symbols = public_fields
dotnet_naming_rule.public_fields_should_be_pascalcase.style = pascalcase_style
dotnet_naming_rule.public_fields_should_be_pascalcase.severity = error
dotnet_naming_symbols.public_fields.applicable_kinds = field
dotnet_naming_symbols.public_fields.applicable_accessibilities = public
dotnet_naming_symbols.public_fields.required_modifiers =
dotnet_naming_style.pascalcase_style.capitalization = pascal_case
# Interfaces should begin with I
dotnet_naming_rule.interface_should_begin_with_i.symbols = interface
dotnet_naming_rule.interface_should_begin_with_i.style = begins_with_i
dotnet_naming_rule.interface_should_begin_with_i.severity = error
dotnet_naming_symbols.interface.applicable_kinds = interface
dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal
dotnet_naming_style.begins_with_i.required_prefix = I
dotnet_naming_style.begins_with_i.capitalization = pascal_case
# Locals and parameters are camelCase
dotnet_naming_rule.locals_should_be_camel_case.symbols = locals_and_parameters
dotnet_naming_rule.locals_should_be_camel_case.style = camel_case_style
dotnet_naming_rule.locals_should_be_camel_case.severity = warning
dotnet_naming_symbols.locals_and_parameters.applicable_kinds = parameter, local
dotnet_naming_symbols.locals_and_parameters.applicable_accessibilities = *
dotnet_naming_style.camel_case_style.capitalization = camel_case
# Types should be PascalCase
dotnet_naming_rule.types_should_be_pascal_case.symbols = types
dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.types_should_be_pascal_case.severity = error
dotnet_naming_symbols.types.applicable_kinds = namespace, class, struct, interface, enum, property, method, event, delegate, local_function
dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal
dotnet_naming_style.pascal_case.capitalization = pascal_case
Шрифт FiraCode
Использую данный шрифт уже давно. Это хороший бесплатный моноширинный шрифт с лигатурами (которые почему-то не всем не нравятся 🤷♂️). Для отображения лигатур надо включить их в настройках VS Code:
{
"editor.fontFamily": "Fira Code", // или FiraCode-Retina
"editor.fontLigatures": true
}
Inlay Hints
Inlay Hints — это подсказки прямо в коде, которые редактор показывает внутри строки, но которые не являются частью кода. Некоторые не включают их из-за «визуального шума», но я к ним давно привык и всегда использую.
{
"editor.inlayHints.fontFamily": "FiraCode",
"csharp.inlayHints.enableInlayHintsForImplicitObjectCreation": true,
"csharp.inlayHints.enableInlayHintsForImplicitVariableTypes": true,
"csharp.inlayHints.enableInlayHintsForLambdaParameterTypes": true,
"csharp.inlayHints.enableInlayHintsForTypes": true,
"dotnet.inlayHints.enableInlayHintsForIndexerParameters": true,
"dotnet.inlayHints.enableInlayHintsForLiteralParameters": true,
"dotnet.inlayHints.enableInlayHintsForObjectCreationParameters": true,
"dotnet.inlayHints.enableInlayHintsForOtherParameters": true,
"dotnet.inlayHints.enableInlayHintsForParameters": true,
"dotnet.inlayHints.suppressInlayHintsForParametersThatDifferOnlyBySuffix": true,
"dotnet.inlayHints.suppressInlayHintsForParametersThatMatchArgumentName": true,
"dotnet.inlayHints.suppressInlayHintsForParametersThatMatchMethodIntent": true
}
Плагин для Unity
Для завершения интеграции с Unity редактором необходимо установить пакет Visual Studio Editor. Обычно он сразу включён после установки редактора, вместе с плагином для Rider.
Вот такая сборка. Не забываем обновлять расширения. Ждём CoreCLR 😅
Нет комментариев