- Home /
My script isn't working - what are some ways I can start debugging?
Let's say I have a generic script and it isn't doing what I want it to.
What are some best practices to use to try to figure out what is going wrong?
(Each major point in your answers should probably be a separate answer, for vote sorting and to keep discussions focused.)
@Tetrad, while I understand the motivation - but having separate Answers with separate votes, implies that one debugging method is better than the others, and that there is a right Answer. Sorry to say, but this Question really... bugs me. It's really not a good UnityAnswers Question. (And yeah, I know everyone else is doing it. :)
Certain problems are more prevalent than others, and people can use their votes to vote up which ones have helped them more often in the past. If you want to see this format being used, just check out the "subjective" section on StackOverflow: http://stackoverflow.com/questions/tagged?tagnames=subjective&sort=votes&pagesize=15
@Tetrad, yes, I'm familiar with StackOverflow :) And I didn't really want to bring up my next point, but - as long as you're referencing SO - when people post subjective questions there, they also make them wikis. If this was on SO, it would have been downvoted already. Now, I have no problem with people far$$anonymous$$g points - it makes up for all those no-reply posts :) But again, I just don't care for the results - Answers that are ranked higher, when they should be complementary.
I'll just have to disagree with you on the results, then. Personally I find giant single-answer community wikis of any length to turn out to be a giant wall of text that isn't very useful to anybody. Case in point: http://answers.unity3d.com/questions/4897/how-can-i-start-learning-unity-fast-list-of-tutorials/7235#7235. If individual links could be discussed and voted on, in theory "better" sources would float to the top.
@Tetrad, so then you'd be voting on the "2D/3D platform tutorial" Answer versus the "Will Goldstone's Book" Answer versus the "Head-Controller Project" Answer versus... I'm not sure that's an improvement. :) I don't really consider his Answer a wall-of-text, either, given that it is separated into Sections. Y$$anonymous$$$$anonymous$$V...
Answer by Ricardo · Jun 28, 2010 at 05:21 PM
Debug.DrawLine and Debug.DrawRay are your friends
All too often people's code seeems OK, but they're missing something obvious about the position or direction of their objects. For instance:
- Is your actor not moving in the right direction? Draw his forward vector and where he should be looking at to ensure they're the values you expect.
- Is your Physics.Raycast not hitting the collider you expect? Draw the vector actually being cast so that you can perceive if it's being snagged in an unexpected collider, or overshooting/undershooting the target.
- Unsure of the area being perceived as an obstacle? Use them to draw the object's bounding box.
Unity lends itself very well for visual debugging, take advantage of it.
Answer by Tetrad · Jun 28, 2010 at 02:59 PM
Check the log
The log may not be open by default, but that's where error messages are sent to. You may have an exception being thrown (exceptions are internal mechanisms to say things aren't the way they should be). Your script may have a parsing error (i.e. your code isn't well-formed).
Either way, if you have any script errors, they should go along with your question for ease of finding out what's wrong.
Answer by Tetrad · Jun 28, 2010 at 03:03 PM
Break apart complicated statements
Let's say you have a line of code like myOtherScript.Property.X = GameObject.Find("MyCustomObject").GetComponent("MyFirstScript").publicMemberVariable
. Chances are if things aren't working, you're getting a NullReferenceException
. Break apart that line into separate parts, and do a test on each one to make sure that things are happening the way you want to.
I.e., in the example above, try doing something like this.
GameObject myCustomObject = GameObject.Find( "MyCustomObject" );
if( myCustomObject == null )
{
Debug.Log( "can't find my custom object" );
return;
}
MyFirstScript myFirstScript = myCustomObject.GetComponent( "MyFirstScript" );
if( myFirstScript == null )
{
Debug.Log( "my custom object doesn't have my first script attached?" );
}
// etc
Answer by Tetrad · Jun 28, 2010 at 04:52 PM
Use care when finding objects by name
There are three main caveats of doing something like GameObject.Find( "MyObjectName" )
- Find() only returns the first instance of an object with that name. If you have two objects in the world both named "Player", which one you'll get is non-deterministic.
- Misspellings. Self-explanatory
- Instantiated objects append the phrase " (Clone)" to the end of the name. If you have a prefab named "MyEnemy", and you Instantiate it, you'll end up with "MyEnemy (Clone)".
GameObject.Find() is also really slow. In practice, finding objects by name should be avoided. There are several ways to avoid calling these methods.
- Making fields to objects in your scripts and connecting them ahead of time in the inspector
- Saving off variables to things you instantiate so you can access them later (i.e. maybe have an enemy manager class that has a list of all the enemies)
- Global variables/singleton style pattern to things you only have one of (i.e. have a public static "instance" variable in your player class that you can access)
@Tetrad, I suppose not putting in bugs, in the first place, counts as a debugging technique. :)
re: slowness of Find - what if you you use find only in the Start() function?
@ina It's better than doing it every frame in Update, but it's still a cost. If you're instantiating a bunch of objects at once that all do Find() it'll be slower than if you just connected things in the editor or have some other way of getting the object directly.
Answer by Cyclops · Jun 28, 2010 at 05:49 PM
Turn on Debug Mode in the Inspector
Using the drop-down box to the right of the Inspector tab, you can set mode from Normal to Debug. This makes all script variables visible in the Inspector, not just public variables. You can't change them at runtime (the non-public ones that is), but you can see them all.
Just remember to set it back to Normal after debugging (some things become un-editable otherwise).
Your answer
Follow this Question
Related Questions
The name 'Joystick' does not denote a valid type ('not found') 2 Answers
Accessing other objects efficiently 1 Answer
Can I output the name of the current class and/or function? 1 Answer
Script testing problems 1 Answer
Not getting a Debug.Log 2 Answers