コガネブログ

平日更新を目標に Unity や C#、Visual Studio、ReSharper などのゲーム開発アレコレを書いていきます

【ReSharper】Unity におけるコードの問題点を見つける

はじめに

f:id:baba_s:20190511195544p:plain

ReSharper で Unity 連携を有効化すると、Unity において問題のあるコードに
警告の波線が表示されたり、ハイライト表示されるようになります

この記事では、どのようなコードに警告の波線やハイライトが表示されるか紹介していきます

目次

Unity 連携の有効化

Unity 連携の有効化の方法は上記の記事で記載しております

Code Inspections

'MonoBehaviour' instances must be instantiated with 'GameObject.AddComponent()' instead of 'new'

f:id:baba_s:20190511193430p:plain

MonoBehaviour を継承したクラスは
new ではなく AddComponent で作成する必要があるため
new で作成している場合は警告の波線が表示されます

https://github.com/JetBrains/resharper-unity/wiki/MonoBehaviors-must-be-instantiated-with-GameObject.AddComponent-instead-of-new

'ScriptableObject' instances must be instantiated with 'ScriptableObject.CreateInstance()' instead of 'new'

f:id:baba_s:20190511193436p:plain

ScriptableObject を継承したクラスは
new ではなく ScriptableObject.CreateInstance で作成する必要があるため
new で作成している場合は警告の波線が表示されます

https://github.com/JetBrains/resharper-unity/wiki/ScriptableObjects-must-be-instantiated-with-ScriptableObject.CreateInstance-instead-of-new

Alternative non-allocating method available

f:id:baba_s:20190511193440p:plain

Physics.RaycastAll などの関数は、Physics.RaycastAllNonAlloc のように
メモリ割り当てが発生しない、名前に NonAlloc と付いたバージョンの関数が存在するため、
NonAlloc と付いたバージョンを使用していない場合は警告の波線が表示されます

f:id:baba_s:20190511203924p:plain

メモリ割り当てが発生しない、名前に NonAlloc と付いたバージョンの関数を使用すると
警告の波線が消えます

下記の関数は、メモリ割り当てが発生しない NonAlloc 版が存在します

関数 NonAlloc 版
Physics.BoxCastAll Physics.BoxCastNonAlloc
Physics.CapsuleCastAll Physics.CapsuleCastNonAlloc
Physics.RaycastAll Physics.RaycastNonAlloc
Physics.SphereCastAll Physics.SphereCastNonAlloc
Physics.OverlapBox Physics.OverlapBoxNonAlloc
Physics.OverlapCapsule Physics.OverlapCapsureNonAlloc
Physics.OverlapSphere Physics.OverlapSphereNonAlloc
Physics2D.BoxCastAll Physics2D.BoxCastNonAlloc
Physics2D.CapsuleCastAll Physics2D.CapsuleCastNonAlloc
Physics2D.CircleCastAll Physics2D.CircleCastNonAlloc
Physics2D.LinecastAll Physics2D.CapsuleCastNonAlloc
Physics2D.RaycastAll Physics2D.RaycastNonAlloc
Physics2D.GetRayIntersectionAll Physics2D.GetRayIntersectionNonAlloc
Physics2D.OverlapAreaAll Physics2D.OverlapAreaNonAlloc
Physics2D.OverlapBoxAll Physics2D.OverlapBoxNonAlloc
Physics2D.OverlapCapsuleAll Physics2D.OverlapCapsuleNonAlloc
Physics2D.OverlapCircleAll Physics2D.OverlapCircleNonAlloc
Physics2D.OverlapPointAll Physics2D.OverlapPointNonAlloc

https://github.com/JetBrains/resharper-unity/wiki/Avoid-using-allocating-versions-of-Physics-Raycast-functions

Avoid 'base.OnGUI()' in classes derived from 'PropertyDrawer'

f:id:baba_s:20190511193553p:plain

PropertyDrawer の OnGUI の中で base.OnGUI を呼び出すと、表示崩れが発生するため
base.OnGUI を呼び出している場合は警告の波線が表示されます

Incorrect method signature

f:id:baba_s:20190511202235p:plain

Awake、Start、Update などの Unity が自動で呼び出す関数の引数が間違っている場合、
警告の波線が表示されます

Expensive method invocation

f:id:baba_s:20190511194340p:plain

Update や LateUpdate、FixedUpdate 、コルーチンなどは、
少し処理が遅いため、目立つようにハイライト表示されます

また、これらの関数の中で下記のような処理を記述した場合も
少し処理が遅くなる可能性があるため、ハイライト表示されます

  • AddComponent
  • GetComponent 系の関数
  • Find 系の関数
  • Debug.Log 系の関数
  • 文字列による関数呼び出し

https://github.com/JetBrains/resharper-unity/wiki/Performance-critical-context-and-costly-methods

Expensive null compatison

f:id:baba_s:20190511194232p:plain

UnityEngine.Object の null チェックは少し処理が遅いため、
Update や LateUpdate、FixedUpdate 、コルーチンなどの中で使用している場合、
ハイライト表示されます

'Camera.main' is expensive

f:id:baba_s:20190511194146p:plain

Camera.main は少し処理が遅いため、Update や LateUpdate、FixedUpdate 、
コルーチンなどの中で使用している場合、ハイライト表示されます

Possible incorrect application of attribute to multiple fields

f:id:baba_s:20190511194633p:plain

FormerlySerializedAs 属性を複数の変数定義に適用している場合、
警告の波線が表示されます

f:id:baba_s:20190511205426p:plain

このようなコードに書き直すことで警告の波線が消えます

https://github.com/JetBrains/resharper-unity/wiki/Possible-mis-application-of-FormerlySerializedAs-attribute-to-multiple-fields

'??' on a type deriving from 'UnityEngine.Object' bypasses the lifetime check on the underlying Unity engine object

f:id:baba_s:20190511193845p:plain

UnityEngine.Object を継承しているインスタンスに対して null 合体演算子を使用すると、
null かどうかが正しくチェックできないことがあります

f:id:baba_s:20190511205731p:plain

このようなコードに書き直すことで警告の波線が消えます

'?.' on a type deriving from 'UnityEngine.Object' bypasses the lifetime check on the underlying Unity engine object

f:id:baba_s:20190511194002p:plain

UnityEngine.Object を継承しているインスタンスに対して null 条件演算子を使用すると、
null かどうかが正しくチェックできないことがあります

f:id:baba_s:20190511205954p:plain

このようなコードに書き直すことで警告の波線が消えます

Attribute is reducant when applied to this declaration type

f:id:baba_s:20190511201306p:plain

例えば、変数に適用するべき属性をプロパティに適用してしまっているなど、
属性の適用方法が間違っている場合、属性が暗めに表示されます

https://github.com/JetBrains/resharper-unity/wiki/Attribute-is-redundant-when-applied-to-this-declaration-type

Redundant 'FormerlySerializedAs' attribute

f:id:baba_s:20190511201550p:plain

FormerlySerializedAs 属性は、シリアライズされる変数に適用するものなので、
シリアライズされない変数に FormerlySerializedAs 属性を適用してしまっていると、
FormerlySerializedAs 属性が暗めに表示されます

Redundant 'HideInInspector' attribute

f:id:baba_s:20190511201612p:plain

HideInInspector 属性は、シリアライズされる変数に適用するものなので、
シリアライズされない変数に HideInInspector 属性を適用してしまっていると、
HideInInspector 属性が暗めに表示されます

Redundant 'InitializeOnLoad' attribute

f:id:baba_s:20190511201659p:plain

InitializeOnLoad 属性は、static クラスに適用するものなので、
static ではないクラスに InitializeOnLoad 属性を適用してしまっていると、
InitializeOnLoad 属性が暗めに表示されます

Redundant 'SerializeField' attribute

f:id:baba_s:20190511201842p:plain

NonSerialized 属性が適用されている変数に SerializeField 属性を適用しても
その変数はシリアライズされないため、SerializeField 属性が暗めに表示されます

Redundant Unity event function

f:id:baba_s:20190511194846p:plain

Awake や Start、Update などの関数は中身が実装されていなくても
Unity から呼び出されてしまい、処理負荷が少しかかってしまうため、
Unity から呼び出されるが、中身が実装されていない関数は、暗めに表示されます

https://github.com/JetBrains/resharper-unity/wiki/Redundant-Unity-event-function

Repeated access of property on built in component is inefficient

f:id:baba_s:20190511195544p:plain

transform.localPosition などは複数回参照するよりも、
一時変数に代入してから参照した方が良いパフォーマンスになるため、
transform.localPosition などを複数回参照している場合、警告の波線が表示されます

f:id:baba_s:20190511195547p:plain

このようなコードに書き直すことで警告の波線が消えます

https://github.com/JetBrains/resharper-unity/wiki/Avoid-multiple-unnecessary-property-accesses

Setting 'parent' property on built in component is inefficient

f:id:baba_s:20190511195026p:plain

オブジェクトを Instantiate してから親オブジェクトを設定するよりも
Instantiate の引数に親オブジェクトを指定した方が良いパフォーマンスになるため、
オブジェクトを Instantiate してから親オブジェクトを設定している場合、
警告の波線が表示されます

f:id:baba_s:20190511195029p:plain

このようなコードに書き直すことで警告の波線が消えます

https://github.com/JetBrains/resharper-unity/wiki/Avoid-using-Object.Instantiate-without-%E2%80%9CTransform-Parent%E2%80%9D-parameter-and-using-SetParent-later

String based graphics property lookup is inefficient

f:id:baba_s:20190511203045p:plain

Animator や Material などのパラメータを設定する時は、パラメータ名を
文字列ではなくハッシュ値で指定した方が良いパフォーマンスになるため、
文字列でパラメータ名を指定している場合、警告の波線が表示されます

f:id:baba_s:20190511203049p:plain

このようなコードに書き直すことで警告の波線が消えます

https://github.com/JetBrains/resharper-unity/wiki/Prefer-using-generic-method-overload-instead-of-string

String based lookup of component type is inefficient

f:id:baba_s:20190511195723p:plain

GetComponent などの関数を使用する時は、型名を文字列ではなく
ジェネリックで指定した方が良いパフォーマンスになるため、
文字列で型名を指定している場合、警告の波線が表示されます

f:id:baba_s:20190511195725p:plain

このようなコードに書き直すことで警告の波線が消えます

https://github.com/JetBrains/resharper-unity/wiki/Prefer-using-generic-method-overload-instead-of-string

Use 'CompareTag' instead of explicit string comparison

f:id:baba_s:20190511195214p:plain

タグを比較する時は、tag プロパティではなく CompareTag を使用した方が
良いパフォーマンスになるため、tag プロパティを使用している場合、
警告の波線が表示されます

f:id:baba_s:20190511195217p:plain

このようなコードに書き直すことで警告の波線が消えます

https://github.com/JetBrains/resharper-unity/wiki/Use-CompareTag-instead-of-explicit-string-comparison

設定変更

f:id:baba_s:20190511212510p:plain

Visual Studio メニューの「RESHARPER > Options」から
「Code Inspection > Inspection Severity」を選択して
「C# > Unity」を選択すると、警告を表示するかどうかを変更できます

関連記事