-
Notifications
You must be signed in to change notification settings - Fork 134
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
More Unity Inspections #107
Comments
gameObject.Invoke as and SendMessage can lead to hard to maintain code... |
Note: SendMessage cost does become more affordable when multiple Components receive it. Someone should do testing on how @WeslomPo, I can't tell whether you're agreeing or disagreeing, but keep in mind that stringly typed code is inherently riskier than strongly typed, and that all inspections are opinionated at best. And just because something can lead to code that is hard to follow doesn't mean it always does, or that it's not useful. I just brought over the tips from the other repository as suggestions. |
You can prevent that in the base class methods are already available Update, Awake, etc. ? |
@Temka193 The blog post 10000 Update() calls has some more information, but the key point is: Update/Awake/etc aren't Unity's native code keeps a list of (Oops, did not mean to hit the Close and comment button....) |
Possible automatic refactoring tied to above warnings:
This should limit the method to only being present "in a player which was built with the “Development Build” option enabled", but currently for me it's showing up in every build. That could just be user error, however.
When finding something on another object, it's best practice to wait until
|
Unfortunately,
|
Why would you ever want to listen for SysReq @nkAlex? In any case, I think I agree on the use of |
Well, I'm mostly calling
|
@CAD97 You did not understand correctly. public class MyClass : BaseMyClass
{
//It should be highlighted the error - "Method awake is already defined in the base class, make protected virtual method in the base class and protected override in the current class."
void Awake()
{
//Here code for additional initialization MyClass
}
void Update()
{
//other code
}
}
public class BaseMyClass : MonoBehaviour
{
void Awake()
{
//Code for initialization BaseMyClass
}
} |
@Temka193 For best practice Unity development, however, You should not unnecessarily implement Unity's magic methods. Doing so causes unnecessary performance overhead, especially if said magic method is called every frame. The key point is, you control your code. You control the methods which are defined in your base class. Due to the way Unity handles magic methods (see the blog post 10000 Update calls), you should not provide a definition when you aren't running code in it. I would argue that by the principle of Composition over Inheritance and Unity's Component-based architecture, you shouldn't need to use a custom base class. But that's less a universal design rule in Unity and just my opinion. |
Hello all! I am the current maintainer of the linked Roslyn analyzer in the OP. In general I agree with @CAD97 regarding creating a base class in Unity. Furthermore, it's also generally considered good practice to "pool" update logic into one component when the number of update calls of similar methods gets large - though this is not something that can be analyzed via static code analysis. It's also worth noting that the devirtualization analyzer is mostly useful when targeting IL2CPP. We've recently added an analyzer that confirms that the function mentioned in the |
I imagine a warning about |
@hymerman, I will admit I haven't worked on any large projects, but I can't think of any occasion where you should need to write rare running code in Unity is callback-based. For e.g. the Timer example, the Unity way of doing so would be to |
Take this with a pinch of salt: I'm just an old-school C++ developer and I care more about performance than ease of use! Unity's event-based approach is great for toy examples and smaller games, but for large games the tiny performance impacts (memory allocation in that case, CPU in others) of things like coroutines really start to add up. Death by a thousand paper cuts and all that. My approach is like that in the 10,000 updates article, but pushed to the extreme; just one bootstrapper game object with an I know my approach would be 'special case', but the same happens to lesser degrees in other codebases. I feel like a warning about this would be noisy for anything other than tiny projects. The other warnings look good though :) |
I'd be happy to take a stab at implementing these inspections @citizenmatt (even if only so I can have them myself), but I don't know where I should start; I've never worked on a R# plugin before. Do you have any suggestions or links for what I could look at to get a quick idea of how this project is structured and how I'd go about adding an inspection? I'd love to contribute, I just lack the knowledge needed to start. Also, I've gone ahead and categorized the suggested inspections into Warnings or Suggestion/Hints: warnings for things suggested against by Unity Technologies, and suggestions/hints for the subtler and more opinion-based on this list. As a compromise for |
Hey. I've somehow managed to miss most of the conversation on this thread. Some great ideas here, thanks. I'm going to pull some of them out into separate issues as they're being worked (mostly because I like closing issues with commit messages. Gives me a lovely sense of progress 😄). As for working on this yourselves with pull requests and whatnot, that'd be brilliant. I have to confess that the SDK isn't as easy or as complete as we'd like it (ReSharper's APIs and capabilities are kind of huge, and time, resources and priorities are limited, sadly). But there is still a lot of good stuff in the SDK's devguide. And of course, the current code is also a good place to start, to see what's going on. Inspections are best handled with a class that derives from Quick Fixes are Alt+Enter actions that are attached automatically to highlights - warnings and errors. And then there's Code Completion, and another useful tool is external annotations. The work to add code completion, find usages, rename, etc. to string literals, such as If you do clone and try and build, I'd recommend unloading any Rider projects right now. Rider's headless version of ReSharper is more or less the head of master at the time of the EAP, which means it needs its own set of SDK NuGet packages, and they're not publicly available right now. And loading the plugin in Rider right now is undocumented and subject to change. We'll have more of an SDK closer to release, hopefully. |
There is no more need to borrow ideas from UnityEngineAnalyzer, you can relatively easy add it to your solution. Rider will display roslyn warning directly in Errors in Solution view. |
Unless there's any plans to add any of these still, I'm fine to see this closed! |
UnityEngineAnalyzer is a Roslyn-based tool for Unity-specific code inspections. Below are some of the inspections from UEA, which would make good further inspections for this plugin.
This issue exists to serve as a task-list grouping of inspections "borrowed" from UEA, and individual issues will likely be extracted (and linked) to be worked on.
Where possible I've included sources for these recommendations. Some phrasing is slightly changed to fit my understanding of the hints.
OnGUI
should not be used inMonoBehaviour
s for production UI WarningSendMessage
,SendMessageUpwards
, andBroadcastMessage
can lead to hard to maintain code, and are slower than delegates, events, and direct method calls. Note that it's unlikely we can add static typing to these (Add method reference for BroadcastMessage #84). Suggestion/HintStart
,Update
, etc.) cause unnecessary calling overhead. Warning (Mark empty event functions as dead code #137)CompareTag
instead ofgameobject.tag ==
Warning (Inspection for CompareTag #82)Find<>
andGetComponent<>
style methods should not be used within Update or Rendering functions. Cache the result inAwake
orStart
instead. Warningoverride
/virtual
functions which are not overridden should besealed
to benefit from devirtualization. Suggestion/HintThe text was updated successfully, but these errors were encountered: