Dialogue icon not showing

so i implemented the AIconversant and put it on the enemy while removing the combattarget script and added the dialogue cursor as the sixt element on the playercontroller script on the player. But for some reason the dialogue icon wont show. All the other icons shows up.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using RPG.Control;

public class AIConversant : MonoBehaviour, IRaycastable
{
    // What cursor to display.
    public CursorType GetCursorType()
    {
        return CursorType.Dialogue;
    }

    public bool HandleRaycast(PlayerController callingController)
    {
        return true;
    }
}

Let’s try a Debug to make sure that the Raycastable is being picked up in the first place:

    public bool HandleRaycast(PlayerController callingController)
    {
        Debug.Log("AIConversant HandleRaycast()");
        return true;
    }

Hi yes that works. When i hoover over the enemy with the AIConversant i get back this message in the console. Maybe the bug is in the playercontroller? I cant see any

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
using System;
using RPG.Movement;
using RPG.Combat;
using RPG.Attributes;
using UnityEngine.EventSystems;
using GameDevTV.Inventories;

namespace RPG.Control
{
    public class PlayerController : MonoBehaviour
    {
        Health health;
        
        //  a struct is a box that stores variables. can access the variables with its name, CursorMapping.type = set its value.
        // make variables public so they are serializable and unity will show them in the editor.
        [System.Serializable]
        struct CursorMapping
        {
            public CursorType type;
            // cursor sprite.
            public Texture2D texture;
            // will make sure the structs cursor in unity follows our mouse when we add it to Cursor.SetCursor.
            public Vector2 hotspot;

        }

        [SerializeField] CursorMapping[] cursorMappings = null;
        [SerializeField] float maxNavMeshProjectionDistance = 1f;
        [SerializeField] float raycastRadious = 0.1f;

        bool isDraggingUI = false;

        private void Awake()
        {
            health = GetComponent<Health>();
            
        }

        // Update is called once per frame
        void Update()
        {
            // Use items in actionslots,hotbar.
            CheckSpecialAbilityKeys();
            // if we are interacting with UI we do nothing else.
            if (InteractWithUI()) return;

            // if player is dead do nothing. cant move when dead.
            if (health.IsDead())
            {   // show the none cursor type.
                SetCursor(CursorType.None);
                return;
            }
            
            // if we clicked an enemy skip rest of the body and exit update. we do this so if
            // we click an enemy we wont use interactwithmovement to move to it.
            //if (InteractWithCombat()) return;
            // deals with the raycastables. if we can interact with component we return.
            if (InteractWithComponent()) return;
            if (InteractWithMovement()) return;
            

            // if we didnt interact with UI, component or movement we set the cursor to type none.
            SetCursor(CursorType.None);
            
        }
        
        private void CheckSpecialAbilityKeys()
        {
            var actionStore = GetComponent<ActionStore>();
            if (Input.GetKeyDown(KeyCode.Alpha1))
            {
                actionStore.Use(0, gameObject);
            }
            if (Input.GetKeyDown(KeyCode.Alpha2))
            {
                actionStore.Use(1, gameObject);
            }
            if (Input.GetKeyDown(KeyCode.Alpha3))
            {
                actionStore.Use(2, gameObject);
            }
            if (Input.GetKeyDown(KeyCode.Alpha4))
            {
                actionStore.Use(3, gameObject);
            }
            if (Input.GetKeyDown(KeyCode.Alpha5))
            {
                actionStore.Use(4, gameObject);
            }
            if (Input.GetKeyDown(KeyCode.Alpha6))
            {
                actionStore.Use(5, gameObject);
            }
        }
        
        
        
        // raycasts through the world getting all of the raycast hits. we go over all the hits and get the 
        // gameobjects. then we get all the components on the gameobjects that implements IRaycastable. The first
        // raycastable that can handle the raycast sets the cursortype.
        private bool InteractWithComponent()
        {
            // returns sorted list of hit results. returns all the things the ray hits.
            RaycastHit[] hits = RaycastAllSorted();
            // codeblock will run for each hit in the hits array.
            foreach (RaycastHit hit in hits)
            {
                // get all the raycastable components on the gameobject we hit.
                IRaycastable[] raycastables = hit.transform.GetComponents<IRaycastable>();
                // go through each raycastable component and check if it can the handle raycast.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
                foreach (IRaycastable raycastable in raycastables)
                {
                    // pass in the playercontroller component. if the handleraycast is true return true and set cursor.
                    if (raycastable.HandleRaycast(this))
                    {
                        SetCursor(raycastable.GetCursorType());
                        return true;
                    }
                }
            }
            // no racastable components that could handle the raycast.
            return false;
        }

        // sorts raycast hits based on distance. this way we always get the objects closest to us
        // when we search for a raycastable.
        RaycastHit[] RaycastAllSorted()
        {
            // get all the rays. use a spherecastall with a ray and a radious. this way we get a 
            // fatter raycast so its easier to hover over enemies.
            RaycastHit[] hits = Physics.SphereCastAll(GetMouseRay(), raycastRadious);
            // array of floats with lenght same as hits.
            float[] distances = new float[hits.Length];
            // add for each hit the raycast distance to distances array.
            for (int i = 0; i < hits.Length; i++)
            {
                distances[i] = hits[i].distance;
            }
            // sorts the hits array based on the distances array.
            Array.Sort(distances, hits);
            // gets sorted list with closest array first.
            return hits;
        }

        private bool InteractWithUI()
        {
            // can release it when we are not over ui.
            if (Input.GetMouseButtonUp(0) || Input.GetMouseButtonUp(1))
            {
                isDraggingUI = false;
            }
            // are our mouse over a game object that is a piece of UI, not a regular gameobject. returns true if we are.
            // return true if we are over a UI. This can place an eventsystem in your scene, must make sure we have one in every scene.
            if (EventSystem.current.IsPointerOverGameObject())
            {
                // can only set it if we are over ui.
                if (Input.GetMouseButtonDown(0) || Input.GetMouseButtonDown(1))
                {
                    isDraggingUI = true;
                }
                SetCursor(CursorType.UI);
                return true;
            }
            // if we are dragging we are interacting with ui.
            if (isDraggingUI == true)
            {
                return true;
            }
            // if we are not over a UI return false.
            return false;
            
        }

        
        // move to clicked position.
        private bool InteractWithMovement()
        {
            // target position we move to.
            Vector3 target;
            // we raycast to the navmesh, if we hit some point on the navmesh, we move there. and set cursor to move.
            bool hasHit = RaycastNavmesh(out target);
            if (hasHit)
            {
                // If we cant move to target return false so we dont move. Its out of range.
                if (!GetComponent<Mover>().CanMoveTo(target)) return false;

                if (Input.GetMouseButton(1))
                {
                    GetComponent<Mover>().StartMoveAction(target, 1f);
                }
                SetCursor(CursorType.Movement);
                return true;
            }
            return false;
        }


        // see if we hover over an area with navmesh, if not dont change the cursor to move.
        // returns true if we hit a navmesh and an out paramater that will give us the location we should start moving to on the navmesh.
        private bool RaycastNavmesh(out Vector3 target)
        {
            target = new Vector3();
            // get hit point of ray and move to clicked position.
            RaycastHit hit;
            // Pass in the ray itself and hit stores the information about 
            // where the raycast hits. the ray shoots continuely out of the mouse without clicking.
            bool hasHit = Physics.Raycast(GetMouseRay(), out hit);
            // if we dont hit anything return false.
            if (!hasHit) return false;
            // A hit on the navmesh.

            // 1 sample point on navmesh, if theres no navmesh we cant move to it.
            NavMeshHit navMeshHit;
            // Finds nearest navmesh point. Give it a position, resulting location, maxdistance it should try and find the nearest navmeshpoint, area mask just use the default.
            bool hasCastToNavMesh = NavMesh.SamplePosition(hit.point, out navMeshHit, maxNavMeshProjectionDistance, NavMesh.AllAreas);
            // return false if it dont find a navmesh point.
            if (!hasCastToNavMesh) return false;
            
            // get the position on the navmesh. this is returned from the function.
            target = navMeshHit.position;

            return true;
        }

       

        // gets cursormapping from cursormapping array in unity, sets the values so we can use the cursor.
        private void SetCursor(CursorType type)
        {
            // gets the correct cursormapping.
            CursorMapping mapping = GetCursorMapping(type);
            // use unity method for setting cursor. takes a texture2d(the cursor sprite), a vector2d hotspot(cursors location, which follows the mouse),
            // cursermode set it always to auto.
            Cursor.SetCursor(mapping.texture, mapping.hotspot, CursorMode.Auto);
        }

        // returns cursor mapping from cursormapping array.
        private CursorMapping GetCursorMapping(CursorType type)
        {
            foreach (CursorMapping mapping in cursorMappings)
            {
                if(mapping.type == type)
                {
                    return mapping;
                }
            }
            // if we dont find anything return the first in the array.
            return cursorMappings[0];
        }

        // get ray from camera to clicked position.
        private static Ray GetMouseRay()
        {
            // when we hover our mouse over the scene we get a ray from our
            // camera origin to the mouse position.
            return Camera.main.ScreenPointToRay(Input.mousePosition);
        }








        // no longer in use.
        // we dont use this code anymore, implemented alternative in combattarget. this just shows how it can be done.
        private bool InteractWithCombat()
        {
            // returns list of hit results. returns all the things the ray hits.
            RaycastHit[] hits = Physics.RaycastAll(GetMouseRay());
            // codeblock will run for each hit in the hits array.
            foreach (RaycastHit hit in hits)
            {
                CombatTarget target = hit.transform.GetComponent<CombatTarget>();
                // if we click on something that does not have a combat target, stop.
                // continue means skip the rest of the code and go directly to the next item in the loop.
                if (target == null) continue;

                // if we execute the code below that means we have found a hit with a CombatTarget that is
                // not null(it has a health component) and is not dead.
                if (GetComponent<Fighter>().CanAttack(target.gameObject) == false)
                {
                    continue;
                }
                // if we clicked the left mouse button, attack! or are holding it down while
                // we point on the enemy, attack!
                if (Input.GetMouseButton(0))
                {
                    // we pass in the gameobject of the target so we know who we attacked. 
                    GetComponent<Fighter>().Attack(target.gameObject);
                }
                // if we have found an enemy change the cursor. must do this before we return.
                SetCursor(CursorType.Combat);
                // return true if target was not null or dead.
                return true;
            }
            // return false if all targets was null.
            return false;
        }
    }
}

No, with the given code, if it wasn’t working for the AIConversant, it wouldn’t be working for any of them. My first suspicion was a lack of a collider on the AIConversant.

Are you getting the Movement, UI, or None icon when you hover?

I get the None icon. There is a capsule collider on the enemy.

Zip up your project and upload it to https://gdev.tv/projectupload and I’ll take a look at it in the morning.
Be sure to remove the Library and .git folders to conserve space.

Thnx i have uploaded the project. I removed the library folder but i didnt find any git folders. I copy pasted the folder into another drive before I removed folders and zipped it. Before I have got some bugs when i do this, hope this doesnt happen this time.

When I looked at the Prefab and Player in Scene 1, I found that the Dialogue cursor was set in the Prefab, but was not set in either of the scenes. This is an issue where the Core prefab serialized (overwrote) the value…
Prefab:

Sandbox:

Go to the Core object in your scene, and in the inspector press Select, and then Open
Then while in the Prefab mode of the Core, navigate to the Player in the Core and scroll to the PlayerController. On the hamburger icon in the upper right of the PlayerController’s inspector, click on it and select Modified Component / Revert

Then save the Core prefab and everything should be working normally.

Thnx! I will write this down, i guess it can happen often.

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms