Forum rules - please read before posting.

Using Move to point sometimes causes player to get stuck

edited 6:57AM in Technical Q&A

Unity 6.2
AC 1.84.3

Hi

I'm using a Unity Starter Assets First Person Controller with AC using the AC integration found somewhere on these forums/ downloads page.

Sometimes when I use the Action Character: Move to point with Enforce time limit and teleport to destination enabled, especially if the player is already close to the marker, the Action gets stuck at that point in the cutscene (that Action remains highlighted in green and doesn't move on to the next Action in the Action List) In the editor I'm forced to "stop" the Action List to regain control. Most times it works fine.

Here are some screenshots of my Player inspector and the modified Starter Assets Input_AC script I'm using -

Screenshot-1
Screenshot-2
Screenshot-3
Screenshot-4
Screenshot-16

using UnityEngine;
#if ENABLE_INPUT_SYSTEM
using UnityEngine.InputSystem;
#endif
using AC;

namespace StarterAssets
{

    public class StarterAssetsInputs_AC : StarterAssetsInputs
    {
        public bool forceDisableController = false;
        public bool acTurnsCamera;
        bool wasInGameplay = true;
        FirstPersonController playerInput;


        AC.Char acCharacter;
        bool underACControl;

        void Awake()
        {
            acCharacter = GetComponent<AC.Char>();
            acCharacter.motionControl = MotionControl.Manual;
            playerInput = GetComponent<FirstPersonController>();

        }

        void Update()
        {
            bool isGameplay = KickStarter.stateHandler.IsInGameplay();


            if (isGameplay && !wasInGameplay)
            {
                if (playerInput != null && !forceDisableController)
                    playerInput.enabled = true;

                LookInput(Vector2.zero);
            }
            if (!isGameplay)
            {
                if (playerInput != null)
                    playerInput.enabled = false;
            }


            wasInGameplay = isGameplay;

            underACControl = !isGameplay ||
                             (!acCharacter.IsPlayer || KickStarter.settingsManager.movementMethod == MovementMethod.PointAndClick) ||
                             acCharacter.IsMovingAlongPath();

            if (underACControl)
            {
                Vector3 moveDirection = acCharacter.GetTargetPosition() - transform.position;
                MoveInput(moveDirection);

                if (acTurnsCamera)
                {
                    Vector3 lookDirection = acCharacter.GetTargetRotation() * Vector3.forward;
                    lookDirection.y = 0f;
                    LookInput(lookDirection);
                }
            }
        }


        private Vector2 GetInputVector(Vector3 worldDirection)
        {
            worldDirection.y = 0f;
            if (worldDirection.sqrMagnitude > 1f) worldDirection.Normalize();
            Vector3 cameraForward = KickStarter.CameraMainTransform.forward;
            cameraForward.y = 0f;
            cameraForward.Normalize();

            Vector3 cameraRight = KickStarter.CameraMainTransform.right;
            cameraRight.y = 0f;
            cameraRight.Normalize();

            float forwardAmount = Vector3.Dot(cameraForward, worldDirection.normalized);
            float rightAmount = Vector3.Dot(cameraRight, worldDirection.normalized);

            return new Vector2(rightAmount, forwardAmount);
        }

#if ENABLE_INPUT_SYSTEM
        public new void OnMove(InputValue value)
        {
            if (underACControl) return;
            MoveInput(value.Get<Vector2>());
        }

        public new void OnLook(InputValue value)
        {
            if (cursorInputForLook)
            {
                LookInput(value.Get<Vector2>());
            }
        }

        public new void OnJump(InputValue value)
        {
            if (underACControl) return;
            JumpInput(value.isPressed);
        }

        public new void OnSprint(InputValue value)
        {
            if (underACControl) { SprintInput(acCharacter.isRunning); return; }
            SprintInput(value.isPressed);
        }
#endif

    }

}

Also my FPS controller - https://pastebin.com/jRzQVduM

Comments

  • edited 7:21AM

    Seem to have fixed it (I think) by setting both Minimum distance and Time limit in Move to point to 0.1
    Edit: Still gets stuck

  • Minimum distance and Time limit values of zero will have no effect.

    Does this still occur if you uncheck the Copy Marker angle after? option?

  • I once again seem to have fixed it with a few changes to the Starter Assets script. If it occurs again I'll try unchecking the Copy Marker angle after option.
    Btw for future reference - do you mean values of zero for min distance and time limit have no effect as in they will have no effect for fixing my particular issue, or 0 basically disables their functionality? I'm guessing it's the former but just want to make sure.

    Script with the fixes -

    using UnityEngine;
    #if ENABLE_INPUT_SYSTEM
    using UnityEngine.InputSystem;
    #endif
    using AC;
    
    namespace StarterAssets
    {
        public class StarterAssetsInputs_AC : StarterAssetsInputs
        {
            public bool forceDisableController = false;
            public bool acTurnsCamera;
    
            bool wasInGameplay = true;
            bool underACControl;
    
            FirstPersonController playerInput;
            AC.Char acCharacter;
    
            void Awake()
            {
                acCharacter = GetComponent<AC.Char>();
                acCharacter.motionControl = MotionControl.Manual;
                playerInput = GetComponent<FirstPersonController>();
            }
    
            void Update()
            {
                bool isGameplay = KickStarter.stateHandler.IsInGameplay();
    
                if (isGameplay && !wasInGameplay)
                {
                    if (playerInput != null && !forceDisableController)
                        playerInput.enabled = true;
    
                    LookInput(Vector2.zero);
                }
    
                wasInGameplay = isGameplay;
    
                underACControl =
                    !isGameplay ||
                    (!acCharacter.IsPlayer || KickStarter.settingsManager.movementMethod == MovementMethod.PointAndClick) ||
                    acCharacter.IsMovingAlongPath();
    
                if (underACControl)
                {
                    Vector3 targetPos = acCharacter.GetTargetPosition(true);
                    Vector3 toTarget = targetPos - transform.position;
                    toTarget.y = 0f;
    
                    Vector2 moveInput = GetInputVector(toTarget);
                    MoveInput(moveInput);
    
                    if (!acCharacter.IsMovingAlongPath())
                    {
                        MoveInput(Vector2.zero);
                    }
    
                    if (acTurnsCamera)
                    {
                        Quaternion targetRot = acCharacter.GetFrameRotation();
                        Vector3 euler = targetRot.eulerAngles;
                        transform.rotation = Quaternion.Euler(0f, euler.y, 0f);
                        LookInput(Vector2.zero);
                    }
                }
            }
    
            private Vector2 GetInputVector(Vector3 worldDirection)
            {
                worldDirection.y = 0f;
                if (worldDirection.sqrMagnitude > 1f)
                    worldDirection.Normalize();
    
                Vector3 cameraForward = KickStarter.CameraMainTransform.forward;
                cameraForward.y = 0f;
                cameraForward.Normalize();
    
                Vector3 cameraRight = KickStarter.CameraMainTransform.right;
                cameraRight.y = 0f;
                cameraRight.Normalize();
    
                float forwardAmount = Vector3.Dot(cameraForward, worldDirection.normalized);
                float rightAmount = Vector3.Dot(cameraRight, worldDirection.normalized);
    
                return new Vector2(rightAmount, forwardAmount);
            }
    
    #if ENABLE_INPUT_SYSTEM
            public new void OnMove(InputValue value)
            {
                if (underACControl) return;
                MoveInput(value.Get<Vector2>());
            }
    
            public new void OnLook(InputValue value)
            {
                if (underACControl) return;
    
                if (cursorInputForLook)
                    LookInput(value.Get<Vector2>());
            }
    
            public new void OnJump(InputValue value)
            {
                if (underACControl) return;
                JumpInput(value.isPressed);
            }
    
            public new void OnSprint(InputValue value)
            {
                if (underACControl)
                {
                    SprintInput(acCharacter.isRunning);
                    return;
                }
    
                SprintInput(value.isPressed);
            }
    #endif
        }
    }
    
  • The latter - a value of zero in those fields will disable their functionality.

  • Interesting, I'll keep that in mind, thanks!

  • edited 8:22AM

    @armaan Would you mind giving this script a test? It's an adaption of your changes with some tweaks:

    using UnityEngine;
    #if ENABLE_INPUT_SYSTEM
    using UnityEngine.InputSystem;
    #endif
    using AC;
    
    namespace StarterAssets
    {
    
        public class StarterAssetsInputs_AC : StarterAssetsInputs
        {
    
            public bool acTurnsCamera;
            public bool forceDisableController;
    
            FirstPersonController firstPersonController;
            AC.Char acCharacter;
            bool underACControl;
    
    
            void Awake ()
            {
                acCharacter = GetComponent<AC.Char> ();
                acCharacter.motionControl = MotionControl.Manual;
                firstPersonController = GetComponent<FirstPersonController>();
            }
    
    
            void OnEnable ()
            {
                EventManager.OnEnterGameState += OnEnterGameState;
            }
    
            void OnDisable ()
            {
                EventManager.OnEnterGameState -= OnEnterGameState;
            }
    
            void Update ()
            {
                underACControl = !KickStarter.stateHandler.IsInGameplay () ||
                                 (!acCharacter.IsPlayer || KickStarter.settingsManager.movementMethod == MovementMethod.PointAndClick) ||
                                 acCharacter.IsMovingAlongPath ();
    
                if (underACControl)
                {
                    if (acCharacter.IsMovingAlongPath())
                    {
                        Vector3 moveDirection = acCharacter.GetTargetPosition () - transform.position;
                        Vector2 moveInput = GetInputVector (moveDirection);
                        MoveInput (moveInput);
                    }
                    else
                    {
                        MoveInput(Vector2.zero);
                    }
    
                    if (acTurnsCamera)
                    {
                        Vector3 lookDirection = acCharacter.GetTargetRotation () * Vector3.forward;
                        Vector3 lookInput = GetInputVector (lookDirection);
                        LookInput (lookInput);
                    }
                }
            }
    
            private void OnEnterGameState (GameState gameState)
            {
                if (!forceDisableController || firstPersonController == null) return;
    
                switch (gameState)
                {
                    case GameState.Normal:
                        firstPersonController.enabled = true;
                        LookInput(Vector2.zero);
                        break;
    
                    case GameState.Cutscene:
                    case GameState.DialogOptions:
                        firstPersonController.enabled = false;
                        break;
    
                    default:
                        break;
                }
            }
    
            private Vector2 GetInputVector (Vector3 worldDirection)
            {
                worldDirection.y = 0f;
                if (worldDirection.sqrMagnitude > 1f) worldDirection.Normalize ();
                Vector3 cameraForward = KickStarter.CameraMainTransform.forward;
                cameraForward.y = 0f;
                cameraForward.Normalize ();
    
                Vector3 cameraRight = KickStarter.CameraMainTransform.right;
                cameraRight.y = 0f;
                cameraRight.Normalize ();
    
                float forwardAmount = Vector3.Dot (cameraForward, worldDirection.normalized);
                float rightAmount = Vector3.Dot (cameraRight, worldDirection.normalized);
    
                return new Vector2 (rightAmount, forwardAmount);
            }
    
    #if ENABLE_INPUT_SYSTEM
            public new void OnMove(InputValue value)
            {
                if (underACControl) return;
                MoveInput(value.Get<Vector2>());
            }
    
            public new void OnLook(InputValue value)
            {
                if(cursorInputForLook)
                {
                    LookInput(value.Get<Vector2>());
                }
            }
    
            public new void OnJump(InputValue value)
            {
                if (underACControl) return;
                JumpInput(value.isPressed);
            }
    
            public new void OnSprint(InputValue value)
            {
                if (underACControl) { SprintInput (acCharacter.isRunning); return; }
                SprintInput(value.isPressed);
            }
    #endif
    
        }
    
    }
    
  • Thanks. This doesnt work for my use case - two things that I immediately noticed are that my Custom Action Toggle Player Movement doesn't work (it moves around when I've disabled it) and also the camera spins when I pause the game. The latter was a major issue I had with the original script, which is why I explicitly disable the FPS controller during cutscenes, pause etc.

    For reference this is the custom Action

    using UnityEngine;
    using AC;
    using StarterAssets;
    
    [System.Serializable]
    public class ActionTogglePlayerMotion : Action
    {
        public override ActionCategory Category { get { return ActionCategory.Custom; } }
        public override string Title { get { return "Toggle Player Movement"; } }
        public override string Description { get { return "Enable or disable player movement manually (e.g., without pausing the game)."; } }
    
        public enum ToggleType { Enable, Disable }
        public ToggleType toggleMotion = ToggleType.Disable;
    
        public override float Run()
        {
            if (KickStarter.player == null)
            {
                Debug.LogWarning("No Player found in scene.");
                return 0f;
            }
    
            GameObject playerObj = KickStarter.player.gameObject;
    
            FirstPersonController controller = playerObj.GetComponent<FirstPersonController>();
            StarterAssetsInputs_AC inputOverride = playerObj.GetComponent<StarterAssetsInputs_AC>();
    
            bool enable = (toggleMotion == ToggleType.Enable);
    
            if (controller != null)
                controller.enabled = enable;
    
            if (inputOverride != null)
                inputOverride.forceDisableController = !enable;
    
            return 0f;
        }
    
    #if UNITY_EDITOR
    
        public override void ShowGUI()
        {
            toggleMotion = (ToggleType)UnityEditor.EditorGUILayout.EnumPopup("Motion:", toggleMotion);
        }
    
        public override string SetLabel()
        {
            return toggleMotion.ToString() + " Player";
        }
    
    #endif
    }
    
Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Welcome to the official forum for Adventure Creator.