Students of Unity generally come to think of scripts as a programming concept, but it isn’t. The original meaning of the word script is just a text file, and their original purpose was to customize the behavior of an application. Unity uses the word script, so it sticks, but in all cases the primary programming concept of C# is the class, not a script. When Unity creates a script from within the editor, it is a class. The name of the class is also the name of the script file, which is a convention of C# and other languages, but that doesn’t mean the script is a programming concept by itself, it really isn’t.
You’ll notice, then, as a result of this, that in your question when you ask if you should “just [create] a script”, in reality that is a class. It is derived from MonoBehaviour, and appears as a component attached to a GameObject. From there you can create additional classes where it is appropriate to do so. The focus of object oriented programming in languages like C# is to determine what concepts are being represented. We focus on what classes should be doing particular jobs. Vector3 itself is a good example. Without Vector3 we would have to perform all of the math associated with vectors based on knowledge of linear algebra using what just happens to be the appropriate 3 variables, namely x, y and z. Vector3 wraps the concepts of rotating by quaternions, finding lengths or distances, or translating vectors (and a lot more) into the Vector3 class, so you don’t actually have to do the linear algebra to accomplish the calculations. The class does this for you.
When you ask “for practical reasons”, that’s a good bit of thinking. What are those reasons? If you don’t have them in mind at the moment, a class is not yet indicated. However, think about Vector3 again for a moment. What you would discover if you did not have Vector3 is that you would find code repeating a number of calculations, over and over, in the code. You’d see code repeated frequently, doing the same thing in multiple locations in your code. That is a hint that an object should exist, but has not yet been written.
At first, the script attached to a GameObject, which is a class remember, may be the very class that should perform the character behavior (and storage of character data) required in your design. At some point, though, you might notice a tendency for something to be repeated. It could be as simple as a bunch of “if/elseif/elseif” tests that seem to repeat in Update. This may hint to an object that doesn’t yet exist.
Update tends to become a mess for student programmers. Sometimes repeated code merely indicates a concept should be wrapped up into a method (a function). A method can be a good way to wrap up a single, simple concept that is repeated. An example of this can be where “if” tends to test the state of two or three bools, over and over with different pattern. If “has weapon” and “weapon is ready” and “health > 10” then…with alternative “else if” for various permutations of the 3 bool pattern. It may be better to make functions that do these tests, named for the purpose of the test. If ( readyToFire()==true) is clearer than the 3 bool test required to determine this. Trust the compiler to make the functions fast (it can inline such a test, but the code is easier to comprehend).
On the other hand, sometimes member variables require more robust “management” to handle correctly. A position, represented by a Vector3, is exactly this kind of thing. So is the Quaternion representing a rotation, which is why Unity created a Transform, combining these two. It is a good example to follow.
Update itself is a very generic concept. It is a slice of time in which various actions are performed for that slice of time. FixedUpdate is a physics engine associated counterpart to it. These two methods represent the cyclic operation of the game engine. Filling update with a bunch of input tests and analysis makes it messy. Breaking those into generic steps makes Update more sane and readable, while possibly separating tasks into methods that make each one clearer.
At some point, though, when something appears repeated, and represents a higher level concept, it requires a class instead of just a method. Reading up on the general concepts behind object oriented programming in C# is, as a result, a required objective of any Unity student.