Adventure Creator Wikia
Register
Advertisement

The following custom Action allows you to have a character move randomly within a circle, given the circle's centre position and minimum/maximum radius to move within.  To use it, create a new C# file named ActionCharMoveRandom.cs and follow the instructions in the "Custom Actions" chapter of the Manual.

ActionCharMoveRandom.cs:

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

#if UNITY_EDITOR
using UnityEditor;
#endif

namespace AC
{

    [System.Serializable]
    public class ActionCharMoveRandom : Action
    {

        public Marker centerMarker;
        public int centerMarkerConstantID = 0;
        public int centerMarkerParameterID = -1;

        public float minRadius = 0f;
        public int minRadiusParameterID = -1;

        public float maxRadius = 10f;
        public int maxRadiusParameterID = -1;

        public Char charToMove;
        public int charToMoveID = 0;
        public int charToMoveParameterID = -1;

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


        public ActionCharMoveRandom ()
        {
            this.isDisplayed = true;
            category = ActionCategory.Character;
            title = "Move randomly";
            description = "Moves a random point within a circle, given a centre-point and a maximum radius.";
        }


        public override void AssignValues (List<ActionParameter> parameters)
        {
            centerMarker = AssignFile <Marker> (parameters, centerMarkerParameterID, centerMarkerConstantID, centerMarker);
            minRadius = AssignFloat (parameters, minRadiusParameterID, minRadius);
            maxRadius = AssignFloat (parameters, maxRadiusParameterID, maxRadius);
            minRadius = Mathf.Clamp (minRadius, 0f, maxRadius);

            charToMove = AssignFile <Char> (parameters, charToMoveParameterID, charToMoveID, charToMove);
            if (isPlayer)
            {
                charToMove = KickStarter.player;
            }
        }
        
        
        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 = GetRandomPoint ();

                        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)
                        {
                            return defaultPauseTime;
                        }
                    }
                }

                return 0f;
            }
            else
            {
                if (charToMove.GetPath () == null)
                {
                    isRunning = false;
                    return 0f;
                }
                else
                {
                    return defaultPauseTime;
                }
            }
        }


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

                if (charToMove is NPC)
                {
                    NPC npcToMove = (NPC) charToMove;
                    npcToMove.StopFollowing ();
                }
                
                Vector3[] pointArray;
                Vector3 targetPosition = GetRandomPoint ();
                
                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]);
            }
        }


        public Vector3 GetRandomPoint ()
        {
            float radius = Random.Range (minRadius, maxRadius);
            Vector2 randomInCircle2D = (Vector3) Random.insideUnitCircle * radius;

            if (SceneSettings.IsUnity2D ())
            {
                return centerMarker.transform.position + new Vector3 (randomInCircle2D.x, randomInCircle2D.y, 0f);
            }

            return centerMarker.transform.position + new Vector3 (randomInCircle2D.x, 0f, randomInCircle2D.y);
        }

        
        #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);
                }
            }

            centerMarkerParameterID = Action.ChooseParameterGUI ("Marker to reach:", parameters, centerMarkerParameterID, ParameterType.GameObject);
            if (centerMarkerParameterID >= 0)
            {
                centerMarkerConstantID = 0;
                centerMarker = null;
            }
            else
            {
                centerMarker = (Marker) EditorGUILayout.ObjectField ("Centre-point:", centerMarker, typeof (Marker), true);
                
                centerMarkerConstantID = FieldToID <Marker> (centerMarker, centerMarkerConstantID);
                centerMarker = IDToField <Marker> (centerMarker, centerMarkerConstantID, false);
            }

            minRadiusParameterID = Action.ChooseParameterGUI ("Minimum radius:", parameters, minRadiusParameterID, ParameterType.Float);
            if (minRadiusParameterID < 0)
            {
                minRadius = EditorGUILayout.FloatField ("Minimum radius:", minRadius);
            }

            maxRadiusParameterID = Action.ChooseParameterGUI ("Maximum radius:", parameters, maxRadiusParameterID, ParameterType.Float);
            if (maxRadiusParameterID < 0)
            {
                maxRadius = EditorGUILayout.FloatField ("Maximum radius:", maxRadius);
            }

            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);

            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
        
    }

}
Advertisement