FANDOM


The following custom Action allows you to specify an exact position to move a character to.  To use it, create a new C# file named ActionCharPathFindVector, and follow the instructions in the "Custom Actions" chapter of the Manual.

ActionCharPathFindVector.cs:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

#if UNITY_EDITOR
using UnityEditor;
#endif

namespace AC
{

    [System.Serializable]
    public class ActionCharPathFindVector : Action
    {

        public Vector3 moveToVector;
        public int moveToVectorParameterID = -1;

        public int charToMoveParameterID = -1;

        public int charToMoveID = 0;

        public bool isPlayer;
        public Char charToMove;
        public PathSpeed speed;
        public bool pathFind = true;
        public bool doFloat = false;

        public bool doTimeLimit;
        public int maxTimeParameterID = -1;
        public float maxTime = 10f;
        [SerializeField] private OnReachTimeLimit onReachTimeLimit = OnReachTimeLimit.TeleportToDestination;
        private enum OnReachTimeLimit { TeleportToDestination, StopMoving };
        private float currentTimer;

        
        public ActionCharPathFindVector ()
        {
            this.isDisplayed = true;
            category = ActionCategory.Character;
            title = "Move to vector";
            description = "Moves a character to a given vector.";
        }


        public override void AssignValues (List<ActionParameter> parameters)
        {
            charToMove = AssignFile <Char> (parameters, charToMoveParameterID, charToMoveID, charToMove);
            moveToVector = AssignVector3 (parameters, moveToVectorParameterID, moveToVector);

            if (isPlayer)
            {
                charToMove = KickStarter.player;
            }

            maxTime = AssignFloat (parameters, maxTimeParameterID, maxTime);
        }
        
        
        override public float Run ()
        {
            if (!isRunning)
            {
                isRunning = true;

                if (charToMove)
                {
                    Paths path = charToMove.GetComponent <Paths>();
                    if (path == null)
                    {
                        ACDebug.LogWarning ("Cannot move a character with no Paths component");
                    }
                    else
                    {
                        if (charToMove is NPC)
                        {
                            NPC npcToMove = (NPC) charToMove;
                            npcToMove.StopFollowing ();
                        }

                        path.pathType = AC_PathType.ForwardOnly;
                        path.pathSpeed = speed;
                        path.affectY = true;

                        Vector3[] pointArray;
                        Vector3 targetPosition = moveToVector;

                        if (SceneSettings.ActInScreenSpace ())
                        {
                            targetPosition = AdvGame.GetScreenNavMesh (targetPosition);
                        }

                        float distance = Vector3.Distance (targetPosition, charToMove.transform.position);
                        if (distance <= KickStarter.settingsManager.destinationAccuracy)
                        {
                            isRunning = false;
                            return 0f;
                        }

                        if (pathFind && KickStarter.navigationManager)
                        {
                            pointArray = KickStarter.navigationManager.navigationEngine.GetPointsArray (charToMove.transform.position, targetPosition, charToMove);
                        }
                        else
                        {
                            List<Vector3> pointList = new List<Vector3>();
                            pointList.Add (targetPosition);
                            pointArray = pointList.ToArray ();
                        }

                        if (speed == PathSpeed.Walk)
                        {
                            charToMove.MoveAlongPoints (pointArray, false, pathFind);
                        }
                        else
                        {
                            charToMove.MoveAlongPoints (pointArray, true, pathFind);
                        }

                        if (charToMove.GetPath ())
                        {
                            if (!pathFind && doFloat)
                            {
                                charToMove.GetPath ().affectY = true;
                            }
                            else
                            {
                                charToMove.GetPath ().affectY = false;
                            }
                        }

                        if (willWait)
                        {
                            currentTimer = maxTime;
                            return defaultPauseTime;
                        }
                    }
                }

                return 0f;
            }
            else
            {
                if (charToMove.GetPath () == null)
                {
                    isRunning = false;
                    return 0f;
                }
                else
                {
                    if (doTimeLimit)
                    {
                        currentTimer -= Time.deltaTime;
                        if (currentTimer <= 0)
                        {
                            switch (onReachTimeLimit)
                            {
                                case OnReachTimeLimit.StopMoving:
                                    charToMove.EndPath ();
                                    break;

                                case OnReachTimeLimit.TeleportToDestination:
                                    Skip ();
                                    break;
                            }

                            isRunning = false;
                            return 0f;
                        }
                    }

                    return (defaultPauseTime);
                }
            }
        }


        override public void Skip ()
        {
            if (charToMove)
            {
                charToMove.EndPath ();

                if (charToMove is NPC)
                {
                    NPC npcToMove = (NPC) charToMove;
                    npcToMove.StopFollowing ();
                }
                
                Vector3[] pointArray;
                Vector3 targetPosition = moveToVector;
                
                if (SceneSettings.ActInScreenSpace ())
                {
                    targetPosition = AdvGame.GetScreenNavMesh (targetPosition);
                }
                
                if (pathFind && KickStarter.navigationManager)
                {
                    pointArray = KickStarter.navigationManager.navigationEngine.GetPointsArray (charToMove.transform.position, targetPosition);
                    KickStarter.navigationManager.navigationEngine.ResetHoles (KickStarter.sceneSettings.navMesh);
                }
                else
                {
                    List<Vector3> pointList = new List<Vector3>();
                    pointList.Add (targetPosition);
                    pointArray = pointList.ToArray ();
                }
                
                int i = pointArray.Length-1;

                if (i>0)
                {
                    charToMove.SetLookDirection (pointArray[i] - pointArray[i-1], true);
                }
                else
                {
                    charToMove.SetLookDirection (pointArray[i] - charToMove.transform.position, true);
                }

                charToMove.Teleport (pointArray [i]);
            }
        }

        
        #if UNITY_EDITOR

        override public void ShowGUI (List<ActionParameter> parameters)
        {
            isPlayer = EditorGUILayout.Toggle ("Is Player?", isPlayer);

            if (!isPlayer)
            {
                charToMoveParameterID = Action.ChooseParameterGUI ("Character to move:", parameters, charToMoveParameterID, ParameterType.GameObject);
                if (charToMoveParameterID >= 0)
                {
                    charToMoveID = 0;
                    charToMove = null;
                }
                else
                {
                    charToMove = (Char) EditorGUILayout.ObjectField ("Character to move:", charToMove, typeof (Char), true);
                    
                    charToMoveID = FieldToID <Char> (charToMove, charToMoveID);
                    charToMove = IDToField <Char> (charToMove, charToMoveID, false);
                }
            }

            moveToVectorParameterID = Action.ChooseParameterGUI ("Position to reach:", parameters, moveToVectorParameterID, ParameterType.Vector3);
            if (moveToVectorParameterID < 0)
            {
                moveToVector = EditorGUILayout.Vector3Field ("Position to reach:", moveToVector);
            }

            speed = (PathSpeed) EditorGUILayout.EnumPopup ("Move speed:" , speed);
            pathFind = EditorGUILayout.Toggle ("Pathfind?", pathFind);
            if (!pathFind)
            {
                doFloat = EditorGUILayout.Toggle ("Ignore gravity?", doFloat);
            }
            willWait = EditorGUILayout.Toggle ("Wait until finish?", willWait);

            if (willWait)
            {
                EditorGUILayout.Space ();
                doTimeLimit = EditorGUILayout.Toggle ("Enforce time limit?", doTimeLimit);
                if (doTimeLimit)
                {
                    maxTimeParameterID = Action.ChooseParameterGUI ("Time limit (s):", parameters, maxTimeParameterID, ParameterType.Float);
                    if (maxTimeParameterID < 0)
                    {
                        maxTime = EditorGUILayout.FloatField ("Time limit (s):", maxTime);
                    }
                    onReachTimeLimit = (OnReachTimeLimit) EditorGUILayout.EnumPopup ("On reach time limit:", onReachTimeLimit);
                }
            }

            AfterRunningOption ();
        }


        override public void AssignConstantIDs (bool saveScriptsToo)
        {
            if (saveScriptsToo)
            {
                if (!isPlayer && charToMove != null && charToMove.GetComponent <NPC>())
                {
                    AddSaveScript <RememberNPC> (charToMove);
                }
            }

            if (!isPlayer)
            {
                AssignConstantID <Char> (charToMove, charToMoveID, charToMoveParameterID);
            }
        }

        #endif
        
    }

}