エディタ上でだけ編集可能にする
「エディタ上で編集不可能にする」ではなく、その逆です。
↓こういうこと
ReadonlyInScript
属性が付いたフィールドはインスペクタでは普通に編集できますが、スクリプトで代入しようとするとエラーで怒られます。
ネタバラし
RoslynAnalyzerで書き込みを禁止しているだけです。 以下のような感じで、すごく愚直に。
public override void Initialize(AnalysisContext context) { // お約束。 context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.EnableConcurrentExecution(); // binary assignment expression全部 var kinds = new SyntaxKind[] { SyntaxKind.SimpleAssignmentExpression, SyntaxKind.AddAssignmentExpression, SyntaxKind.SubtractAssignmentExpression, SyntaxKind.MultiplyAssignmentExpression, SyntaxKind.DivideAssignmentExpression, SyntaxKind.ModuloAssignmentExpression, SyntaxKind.AndAssignmentExpression, SyntaxKind.ExclusiveOrAssignmentExpression, SyntaxKind.OrAssignmentExpression, SyntaxKind.LeftShiftAssignmentExpression, SyntaxKind.RightShiftAssignmentExpression, SyntaxKind.CoalesceAssignmentExpression, SyntaxKind.PreIncrementExpression, SyntaxKind.PreDecrementExpression, SyntaxKind.PostIncrementExpression, SyntaxKind.PostDecrementExpression }; context.RegisterSyntaxNodeAction(AnalyzeSyntax, kinds); } private static void AnalyzeSyntax(SyntaxNodeAnalysisContext context) { var syntax = context.Node switch { AssignmentExpressionSyntax assignExpression => assignExpression.Left, PostfixUnaryExpressionSyntax postUnary => postUnary.Operand, PrefixUnaryExpressionSyntax preUnary => preUnary.Operand, _ => default }; if (syntax == default) return; var symbol = context.SemanticModel .GetSymbolInfo(syntax, context.CancellationToken) .Symbol; var result = symbol switch { IFieldSymbol fieldSymbol => fieldSymbol.GetAttributes() .Any(x => x.AttributeClass.Name.Contains("ReadonlyInScriptAttribute")), IPropertySymbol propertySymbol => IsAutoProperty(propertySymbol) && HasReadonlyAttribute(propertySymbol), _ => false, }; if (result) { // Diagnosticを作ってReportDiagnosticに詰める。 var diagnostic = Diagnostic.Create(Rule, context.Node.GetLocation()); context.ReportDiagnostic(diagnostic); } bool IsAutoProperty(IPropertySymbol propertySymbol) { var node = propertySymbol.DeclaringSyntaxReferences.First().GetSyntax(); if (node is not PropertyDeclarationSyntax propertyDeclarationSyntax) return false; return propertyDeclarationSyntax.AccessorList.Accessors.All(a => a.Body == null); } bool HasReadonlyAttribute(IPropertySymbol propertySymbol) { var node = propertySymbol.DeclaringSyntaxReferences.First().GetSyntax(); if (node is not PropertyDeclarationSyntax propertyDeclarationSyntax) return false; return propertyDeclarationSyntax.DescendantNodes() .OfType<AttributeSyntax>() .Any(a => a.Name.ToString().Contains("ReadonlyInScript")); } }
飽くまでもコードを分析しているだけなので、エディタからの編集は何も問題無いというわけです。
これの何が嬉しいの?って言われたらわからないですが、 アナライザのコードとdllは以下のリポジトリに公開しています。 github.com
以下のページなどを参考に、dllをポイっとUnityにインポートして、ReadonlyInScriptAtribute
って名前の属性を作ればOKです。