using System; using Framework.Services; namespace Framework.Actors { /// Action that can be performed by an actor /// /// /// Think of a move as when someone says "cool moves" - these are actions, /// feats or stunts an actor can perform. For player-controlled actors, possible moves /// might be standing around, running, jumping, punching, falling over and so on. /// For AI-controlled actors, moves are usually atomic actions such as /// "run to position x" or "jump onto the platform". /// /// /// Each move can decide which other moves it can transition to. For example, /// crawling while jumping doesn't make much sense, but jumping while running does. /// /// /// Usually, moves have a class derived from this one to add more properties /// specific to the actor implementation (eg. platformer moves would reference a /// platformer actor). Overriding moves to use custom implementations can be done /// through the specific move repository classes. /// /// /// Moves have to be cancellable at any time and also needs to be reusable. /// /// public class Move { /// Initializes the move on the specified actor /// Actor that will perform the move public void Initialize(ActorController actor) { if(this.isInitialized) { return; } ServiceInjector.InjectDependencies(this); Awake(actor); this.isInitialized = true; } /// Whether the move has completed executing /// /// /// This is checked by the to see whether its /// currently active move has ended (allowing it to decide on a new move). /// Moves are not required to ever finish, but they have to be interruptible at /// any time. It is also okay to for the moves themselves to take care of their /// transition to other moves. /// /// /// If a move can finish, this property should return 'true' as soon as the move /// finishes and reset to 'false' when the move receives the /// notification or the notification. /// /// /// Moves that can finish are usually only used for AI characters where moves are /// scheduled by a 'strategy' (or other high-level control system) that uses them /// in a fashion similar to behavior tree nodes (eg. a 'MoveTowardsPlayer' strategy /// or behavior tree node might use multiple 'run' and 'jump' moves to achieve its goal. /// /// /// When a move completes, the /// method is invoked. By default, this just sets the active move to null, but /// custom actor controllers can override this to notify their AI 'strategy' or /// fall back to some kind of default move, for example. /// /// public virtual bool IsCompleted { get { return false; } } /// Called once when the move is assigned to an actor /// Actor the move has been assigned to protected virtual void Awake(ActorController actor) {} /// Called when the actor has started the move public virtual void OnStarted() {} /// Called when the move has completed or was interrupted public virtual void OnEnded() {} /// Called once per physics frame /// /// Use this method to update the world position of the actor and do other /// things that have an impact on game play. Input processing should happen /// in this method alone. /// public virtual void FixedUpdate() {} /// Called once per visual frame /// /// Use this method to update the visual state of the actor. /// public virtual void Update() {} /// Whether the move has been initialized yet private bool isInitialized; } } // namespace Framework.Actors