Forum rules - please read before posting.

WASD/Click to Move

We built the game around the click to move, with A* pathfinding installed, but we want to make it an option to be able to switch to using WASD to move. Is there an easy way to do this built-in? and if not, do you have any recommendation how to implement this?

Comments

  • WASD movement is referred to as "Direct" movement in AC terms. You can swtich to this with the Settings Manager's Movement method field.

    Having both Direct and Point And Click movement options depends on how you want them to be merged. Do you want the user to be able to switch between them automatically based on input, or from a setting in e.g. the Options menu?

    If the former, you'll need to rely on a custom script to alter this field based on input. A page on the AC wiki related to this can be found here:

    https://adventure-creator.fandom.com/wiki/Combining_PointAndClick_with_Direct_Movement_Methods

    If the latter, you can use the Engine: Manage systems Action - run when e.g. a Button is clicked in a Menu, to set the movement method and use a Global Variable to keep track the user's choice.

    Just be mindful that altering this field at runtime - using either method - will cause its value change to be retained when exiting Play mode. Therefore, you should run this Action when your game begins to set it to your intended initial state. This can be done by running it in your ActionList when start game asset, as set in the Settings Manager.

  • since Ive been building for point and click, how do I get the player character to respect the point and click navmesh? right now I can walk the player everywhere and they walk through navmeshes.

  • Nevermind! I found the answer after searching the forums! Took me a bit of digging as I kept finding older threads on the subject, the involved some complicated colliders/rigidbody2d/circle colliders updates. But, then I stumbled on a newer thread and see the problem has been solved since then.

    for anyone else: simply check on auto-stick to navmesh in your player root object and look for player settings.

  • I did run into another problem. I frequently make scenes with 3-4 locations in it, and each location has its own navmesh. (a single navmesh with multiple 2d poly colliders on it)

    It apppears that direct movement wtih autostick to navmesh makes the player stuck on the original poly2d collider, and trying to leave it, teleports them back

  • here's a really straight forward use case. In this instance I have a ladder that connects the main area with this isolated area. (both are the same navmesh, the bottom one is the original poly 2d collider segment, and the isolated section is a seperate 2dpoly componet attached to the navmesh.)

    the character walks up the ladder by using a character move to point, with pathfinding turned off.

  • Currently, the auto-stick to NavMesh option only works with the first-found Polygon Collider associated with the NavMesh. It should be possible to extend this to allow for multiple components, however - I'll look into this and see if it can be added into the next update.

  • Try this: open up AC's Player script, and replace the current SnapToNavMesh2D function with the following:

    private PolygonCollider2D[] autoStickPolys;
    protected void SnapToNavMesh2D ()
    {
        if (IsMovingAlongPath () || !SceneSettings.IsUnity2D () || KickStarter.sceneSettings == null || KickStarter.sceneSettings.navMesh == null || KickStarter.settingsManager.movementMethod == MovementMethod.PointAndClick) return;
    
        #if UNITY_2019_2_OR_NEWER
    
        if (autoStickPolys == null || autoStickPolys.Length == 0 || autoStickPolys[0].gameObject != KickStarter.sceneSettings.navMesh.gameObject)
        {
            autoStickPolys = KickStarter.sceneSettings.navMesh.GetComponents<PolygonCollider2D> ();
        }
    
        float minSqrDist = 0f;
        int bestIndex = -1;
        Vector3 bestPosition = Vector3.zero;
    
        for (int i = 0; i < autoStickPolys.Length; i++)
        {
            Vector3 newPosition = autoStickPolys[i].ClosestPoint (transform.position);
    
            float sqrDist = (newPosition - transform.position).sqrMagnitude;
            if (sqrDist == 0f)
            {
                // Already inside
                return;
            }
    
            if (bestIndex < 0 || sqrDist < minSqrDist)
            {
                minSqrDist = sqrDist;
                bestIndex = i;
                bestPosition = newPosition;
            }
        }
    
        if (bestIndex >= 0)
        {
            Teleport (bestPosition);
        }
        #endif
    }
    

    Does that resolve it?

  • yep! that appears to have fixed it, Very useful feature, thank you!

  • On further testing it made new problems, namely regarding scene switching. The camera would stop smoothly following the player, or switch to a new camera when moving directly.

    before you sent your snippet, we used this bit of code to fix it, and it seems to be working correctly.

        protected void SnapToNavMesh2D()
        {
            if (IsMovingAlongPath() || !SceneSettings.IsUnity2D() ||
                KickStarter.sceneSettings == null ||
                KickStarter.sceneSettings.navMesh == null ||
                KickStarter.settingsManager.movementMethod == MovementMethod.PointAndClick)
            {
                return;
            }
    

    if UNITY_2019_2_OR_NEWER

    Vector3 playerPos = transform.position;
    // Get *all* PolygonCollider2D components on the NavMesh
    PolygonCollider2D[] polygonColliders =
        KickStarter.sceneSettings.navMesh.GetComponentsInChildren<PolygonCollider2D>();
    
    if (polygonColliders != null && polygonColliders.Length > 0)
    {
        float bestDist = Mathf.Infinity;
        Vector3 bestPos = playerPos;
    
        // Iterate over each polygon, and choose whichever “ClosestPoint” is actually closest
        foreach (PolygonCollider2D poly in polygonColliders)
        {
            // Get the closest point on this particular polygon
            Vector3 testPos = poly.ClosestPoint(playerPos);
            float dist = (playerPos - testPos).sqrMagnitude;
    
            if (dist < bestDist)
            {
                bestDist = dist;
                bestPos = testPos;
            }
        }
    
        // Only teleport if the "bestPos" is different to avoid micro-teleportation
        if (bestPos != transform.position)
        {
            Teleport(bestPos);
        }
    }
    

    endif

        }
    
  • The camera and player's motion are two separate operations. Share full details of the original issue, including steps to recreate, and I can look into an official fix.

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.