using System; using System.Collections.Generic; using UnityEngine; using RAIN.Action; using RAIN.Path; using RAIN.Core; using RAIN.Animation; namespace RAIN.Primitives { /// /// MoveAction is a primitive used to specify a target location to move to, speed at which to move, and optionally an animation to play while moving. /// public class MoveAction : Action.Action { /// /// If the movement target is a GameObject (Transform) then moveContextVariableName contains the name of the variable holding the game object. /// This may have been assigned by a DetectAction primitive. /// public string moveContextVariableName = null; /// /// If the look target is a GameObject (Transform) then moveContextVariableName contains the name of the variable holding the game object. /// This may have been assigned by a DetectAction primitive. /// public string lookContextVariableName = null; /// /// moveTarget is the MoveLookTarget (Vector or Transform) that is moved to /// public MoveLookTarget moveTarget = new MoveLookTarget(); /// /// lookTarget is the MoveLookTarget (Vector or Transform) that is face during movement /// public MoveLookTarget lookTarget = new MoveLookTarget(); /// /// moveSpeed is the target speed for movement. This is limited by the Agent's overall MaxSpeed /// public float moveSpeed = -1.0f; /// /// lookSpeed is the target rotation speed for movement. This is limited by the Agent's overall MaxRotationRate /// public float lookSpeed = -1.0f; /// /// animationOverride is the animation state name of an animation that should be played during movement. If animation is driven by an AIAnimationController, this value will override /// the controller's normal animation. Leave null or blank if no custom animation is desired /// public string animationOverride = null; /// /// animationOverrideBaseSpeed is the baseline speed of the animation state specified in animationOverride. The animation playback speed will be adjusted based on the difference /// between actual movement speed and this base speed /// public float animationOverrideBaseSpeed = 1.0f; private bool _animationStarted = false; public MoveAction() { } /// /// ActionResult.Start /// Sets up move and look targets from variables if necessary /// /// /// /// SUCCESS public override ActionResult Start(Agent agent, float deltaTime) { if (moveContextVariableName != null) moveTarget = GetTargetFromVariable(moveContextVariableName); if (lookContextVariableName != null) lookTarget = GetTargetFromVariable(lookContextVariableName); _animationStarted = false; return ActionResult.SUCCESS; } /// /// ActionResult.Execute /// Move toward the move target, look at the look target. /// /// /// /// SUCCESS if the Agent has reached the target, RUNNING otherwise public override ActionResult Execute(Agent agent, float deltaTime) { bool closeEnough = true; float maxSpeed = agent.Kinematic.MaxSpeed; float maxRotation = agent.Kinematic.MaxRotationRate; if (moveSpeed >= 0) agent.Kinematic.MaxSpeed = Mathf.Min(moveSpeed, maxSpeed); if (lookSpeed >= 0) agent.Kinematic.MaxRotationRate = Mathf.Min(lookSpeed, maxRotation); if ((moveTarget != null) && (moveTarget.TargetType != MoveLookTarget.MoveLookTargetType.NONE)) { agent.MoveTarget = moveTarget; closeEnough = agent.Move(deltaTime); } if ((lookTarget != null) && (lookTarget.TargetType != MoveLookTarget.MoveLookTargetType.NONE)) { agent.LookTarget = lookTarget; closeEnough &= agent.Look(deltaTime); } if (!closeEnough && !_animationStarted) { if ((animationOverride != null) && (animationOverride.Trim().Length > 0)) { agent.Avatar.BroadcastMessage("HandleAIAnimationStateMovementOverride", new AnimationParams(animationOverride, animationOverrideBaseSpeed), SendMessageOptions.DontRequireReceiver); _animationStarted = true; } } agent.Kinematic.MaxSpeed = maxSpeed; agent.Kinematic.MaxRotationRate = maxRotation; if (closeEnough) return ActionResult.SUCCESS; return ActionResult.RUNNING; } /// /// ActionResult.Stop /// Stops custom animation override if enabled /// /// /// /// SUCCESS public override ActionResult Stop(Agent agent, float deltaTime) { if (_animationStarted && (animationOverride != null) && (animationOverride.Trim().Length > 0)) { agent.Avatar.BroadcastMessage("HandleAIAnimationStateMovementOverride", new AnimationParams(null, 0), SendMessageOptions.DontRequireReceiver); } _animationStarted = false; return ActionResult.SUCCESS; } private MoveLookTarget GetTargetFromVariable(string variable) { if (!actionContext.ContextItemExists(variable)) return null; MoveLookTarget target = null; target = actionContext.GetContextItem(variable); if (target != null) return target; target = new MoveLookTarget(); Kinematic k = actionContext.GetContextItem(variable); if (k != null) { target.KinematicTarget = k; return target; } GameObject gobj = actionContext.GetContextItem(variable); if (gobj != null) { target.TransformTarget = gobj.transform; return target; } Vector3 v = actionContext.GetContextItem(variable); target.VectorTarget = v; return target; } } }