[SUGGESTION] Improved Point & Click Navigation

DankP3

Active member
Currently I see two undesirable outcomes in the Point and Click movement type:

1. The mouse position is polled constantly whilst the 'click button' is down, a single nav path is set (move towards location set) and the character moves. A second click will not reassign the movement until the first one is concluding. Enabling a reclick enables continuous movement and IMO better UX.

2. clicking off the nav mesh will move the move towards location to an obtainable location and the stick in movement animation at the edge of the nav mesh
(I dont think this is compatible with my suggested bug fix here: https://www.opsive.com/forum/index....rds-timeout-and-navagent-position-error.7398/ perhaps because it warps off the nav mesh).

Suggested improvements:
- subscribe to input event so you can poll GetButtonDown instead of GetButton.
- change existing method GetInputVector method to return Vector2.zero:
- Have new method triggered by input event that carries the navigation code formally in GetInputVector.
An example method with two graded NavMesh location checks that seems to work:

Code:
        private void SelectDestination(){
            // PointClick does not have any direct input, but it will tell the Move Towards ability to move towards the clicked location.
            var ray = m_Camera.ScreenPointToRay(m_PlayerInput.GetMousePosition());
            if (Physics.Raycast(ray, out var hit, float.MaxValue, m_LayerManager.SolidObjectLayers, QueryTriggerInteraction.Ignore)) {
                //UnityEngine.AI.NavMeshHit prelimHit;
                //We need to check the target is on the NavMesh
                if (UnityEngine.AI.NavMesh.SamplePosition(hit.point, out var confirmedHit, 0.1f, m_LayerManager.SolidObjectLayers)) {
                    //Debug.Log("ON MESH");
                }
                //Note increased SamplePosition distances are expensive - this additional check gives a nvagiation target if slightly off the navmesh
                else if (UnityEngine.AI.NavMesh.SamplePosition(hit.point, out confirmedHit, 5f, m_LayerManager.SolidObjectLayers)) {
                    //Debug.Log("NOT ON MESH");
                }
                else {
                    return;
                }
                // Do not allow movement if the location is close to the character.
                var sqrDistance = Vector3.SqrMagnitude(m_Transform.position - confirmedHit.position);
                if (sqrDistance >= m_MinPointClickDistanceSqr) {
                    m_CharacterLocomotion.MoveTowardsAbility.MoveTowardsLocation(confirmedHit.position);
                }
            }
            
            // If a SpeedChange ability exists then the character can move at a faster speed further away from the target.
            if (m_CharacterLocomotion.MoveTowardsAbility.IsActive && m_SpeedChange != null && m_MoveSpeed.MinValue != m_MoveSpeed.MaxValue) {
                var distance = (m_PathfindingMovement.GetDestination() - m_Transform.position).sqrMagnitude;
                m_SpeedChange.MaxSpeedChangeValue = m_SpeedChange.SpeedChangeMultiplier = Mathf.Lerp(m_MoveSpeed.MinValue, m_MoveSpeed.MaxValue, Mathf.Clamp01(distance / m_RunMaxSquaredDistance));
                m_SpeedChange.MinSpeedChangeValue = -m_SpeedChange.MaxSpeedChangeValue;
            }
        }

EDIT: Probably this could be better improved by confirming a navigable path prior to executing a navigation.
EDIT: Fixed code
 
Last edited:
Top