GameObject State management

Started by
3 comments, last by SeanMiddleditch 10 years, 2 months ago

I am trying to use the 2D portion of Unity3D for the first time so I am creating a breakout clone.

My issue is that the state management is getting decentralized... and I am not 100% certain if it is because a) It has to be, or more likely b) I'm doing something "wrong".

I have 4 major game objects, The ball, the paddle, walls, and blocks. The blocks state is simple, it starts at State N and each time the ball collides with it it moves to state N-1, at state N=0 it gets destroyed.

The walls and the paddle are also simple as they have only a single state each.

The ball is where it is getting tricky..

The ball has three states: Setup, LockedToPaddle and Moving.

It has a public function setState(state) :It's only public so the animation event can see it. SetState only changes to the new state if the new state is a valid state to transition to (For example, attempting to setState(Moving) from setup will not do anything, nor will setState(x) from state x.

When a state is successfully changed, it will also update the state variable in the animator.

The animator has an integer parameter State: 1=Setup, 2=lockedToPaddle,3=Moving

Each state has it's own animation, at the start of each animation there is an animation event which calls setState(State).

The setup state has a transition with a 3 loop exit condition, which moves to LockedToPaddleState

LockedPaddleState has a conditional transition on State=3 to transition to Moving.

Moving has a conditional transition on State=1 to Setup.

Further, I have an inputmanager game object with a delegate OnBallFire which triggers when the user presses the space bar. The ball gameobject has a method ball_OnBallFire() which calls setState(Moving)

Then In the collision2d method for the ball, if the ball collides with the "deadzone" (the area below the paddle). It calls setState(Setup).

As you can see... stateTransitions are made from all over the place... is this normal? Is there a way to centralize the state transition logic? Is it an issue that the animator can update the state, but the state can also update the animator?

Advertisement


As you can see... stateTransitions are made from all over the place... is this normal? Is there a way to centralize the state transition logic? Is it an issue that the animator can update the state, but the state can also update the animator?

It is correct that events which (may) cause a transition come from various places. Nothing to worry about.

It would be a bit more decoupled if others would not call setState(…) but send an event like "ball_hit_deadzone", "ball_hit_block", … to the state machine (i.e. they are passed to the current state). However, whether this decoupling is worth the effort in your case is on your decision. But notice that the same events may trigger other effects, too. E.g. the sound sub-system can be triggered to play the appropriate collision or "loss in deadzone" indicating sounds on the same events.

The animation may send events to the state machine, too, but I suspect that it is needed in your use case. A typical case would be that the end of an animation timeline was reached (which does not occur in your case, AFAIS). Another typical case would be that specific timestamps on the timeline cause some effect, e.g. footstep sound or so, but that also is not needed for your use case (again AFAIS).


Is it an issue that the animator can update the state, but the state can also update the animator?

I think it's an issue that both the ball and the animator have the same state. You're duplicating state here - they're always the same, so they should probably leverage the same value (which could be stored in the ball) so there are never any synching issues. If you want, you can achieve better decoupling between the ball and the animator by using an interface (I'm not sure how much the ball/animator need to know about each other).

As haegarr suggested, you could coalesce your state logic into one piece of code and create new abstractions (e.g. events) to drive transitions between states.

Cool.

Another question. I noticed in the asset store an AI State machine that worked the same as the animation state machine... in what instances would it be beneficial to use a separate AI state machine rather than just doubling your animation states as AI states? From my limited usage it seems that each task an AI Machine might contain would require an animation and each animation represents a task or action... even if multiple AI States utilize the same animation but have different transition conditions, the animation state only holds a pointer to the animation clip so it would not be outrageous to have multiple animation states that play the same animation right?

Another question. I noticed in the asset store an AI State machine that worked the same as the animation state machine... in what instances would it be beneficial to use a separate AI state machine rather than just doubling your animation states as AI states?


Non-trivial games typically have a lot of animation states that really have nothing to do with what an AI is trying to achieve. The AI might simply be following a path from the navigation system which might include climbing, jumping, dropping, opening a door, etc. The AI doesn't need to care about all of these, but the animation system certainly has to.

More complex games can't even represent animation with a simple state machine. There are often hierarchical state trees, blend trees, procedural animations, and so on. Such games typically isolate most of the animation state from everything else and rely only on a set of inputs (direction/velocity, whether on the ground or not, etc.) and use a very specialized animation tool for defining the animation states, transitions, blend weights, IK parameters, procedural animations, etc. Physics and AI then provide data for the animation system to make decisions based upon.

Sean Middleditch – Game Systems Engineer – Join my team!

This topic is closed to new replies.

Advertisement