Script Management best practiecs

Hello people who are smarter than me.

I’m am just getting into some of the more subtle techniques of programming and had a question about script management in Unity.

From my studies and talks with more experienced programmers than myself, I’ve come across the concept of control a lot. What script is in control of this one? Who is setting this object’s values? Who is getting them? Are you sending messages up and not down? What script owns this script?

Some of it is well above my head, but I am running into a problem that I’m not sure the best way to tackle it.

It is basically this: I have two scripts on my character prefab. He has a couple animations–run, idle, and two attacks. All of the animation tutorials I have looked at seem to have the animation script and the controller script separate things. This I don’t have a problem with, necessarily. What bothers me is that the controller script will do something like this:

//This is the controller script
function Update() {
	if (Input.GetKeyDown(KeyCode.W) {
		//Make the character run forward.
	}
}

And then in the animation script, they would do something like this:

//This is the animation script
function Update() {
	if (Input.GetKeyDown(KeyCode.W) {
		//Crossfade in the run animation.
	}
}

My issue is that it feels like you build inherit problems of your animations not necessarily syncing up with your actions. I can understand that you want a separate script for setting up any animations, layers, wrap modes, and animation events–that much makes sense. But to have the two both looking for the same action seems like you’re creating more work for yourself in the long run and not really understanding who is in control of what.

Which brings me to my question of “What is the best practice here?”

I was thinking something like this:

//This is the controller script
var anims : AnimationScript;
anims = GetComponent("AnimationScript");

function Update() {
	if (Input.GetKeyDown(KeyCode.W) {
		//Make the character move forward.
		//Crossfade the animation via the animationscript and a
		//custom function to handle weight blending.
		anims.StartRunning();
	}
}

Thank you in advance for your wisdom on this matter.

In my experience, the way to approach this kind of thing is to have the user input stuff behave independently from other systems. I wouldn’t have the user input code directly in my character controller. Rather, I’d have some kind of “user input” script that I could theoretically attach to any game object.

In the project I’m working on right now, for example, I have a component which handles all actor movement, whether driven by AI or by user input. It has methods like MoveForward, TurnLeft, etc. This works for me because of the block-aligned nature of movement, but I could easily change things to work in a more fluid environment by having the movement script use impulse flags instead of one-shot movements.

if(Input.GetKeyDown(KeyCode.W)) {
    GetComponent<CharacterController>().ForwardImpulse();
}

^ this would be in the user input script, and then in the update of the character controller…

if(hasForwardImpulse) {
    // If we are in an idle state at the moment,
    // kick off the animation and whatnot.
}